简体   繁体   English

Meteor JS:如何将文档插入集合中,但仅限于客户端?

[英]Meteor JS: How do I insert a document into a collection, but only on the client-side?

I'm new to Meteor and building a simple app to learn the framework. 我是Meteor的新手,并构建了一个简单的应用程序来学习框架。 The app I'm building let's you place words on an image of a kitten. 我正在构建的应用程序让你在小猫的图像上放置文字。

The desired behavior is this: 期望的行为是这样的:

A user clicks anywhere on the kitten, and a contenteditable element appears letting the user enter text. 用户单击小猫的任何位置,并且出现一个允许用户输入文本的可信元素。 Clicking outside of the element saves the element, and it remains in place. 单击元素外部可以保存元素,并保留在原位。

The problem I'm running into: 我遇到的问题:

If I have two browser windows opened with the app, and I click on one kitten in one window, an empty field appears in both windows. 如果我在应用程序中打开了两个浏览器窗口,并且在一个窗口中单击一只小猫,则两个窗口中都会显示一个空白字段。 Ideally, the empty field would appear only on the window I clicked on. 理想情况下,空字段仅出现在我单击的窗口上。 Once a word is saved, then in should be visible in both windows. 保存一个单词后,应该在两个窗口中都可以看到。

My question: 我的问题:

Is there a way to insert a document into a collection on the client-side only, and then use upsert later to add the document to servert-side collection? 有没有办法只在客户端insert文档插入到集合中,然后使用upsert将文档添加到servert-side集合?

Here's what I tried: 这是我试过的:

I created a stub method that exists only on the client-side for inserting the document. 我创建了一个存根方法,该方法仅存在于客户端以插入文档。 The problem with this, is that when I click on the image, an empty field appears for a split-second, and then disappears again. 这个问题是,当我点击图像时,会出现一个空白字段,持续一秒钟,然后再次消失。

Here's the code: 这是代码:

image-tags.js 图像tags.js

if (Meteor.isClient) {
  var isEditing;

  Template.image.image_source = function () {
    return "http://placekitten.com/g/800/600";
  };

  Template.tag.rendered = function(){
    var tag = this.find('.tag');
    if (isEditing && !tag.innerText) {
      tag.focus();
    }
  }

  Template.image.events({
    'click img' : function (e) {
      if (isEditing) {
        isEditing = false;
      } else {
        isEditing = true;
        var mouseX = e.offsetX;
        var mouseY = e.offsetY;

        // Tags.insert({x:mouseX, y:mouseY});

        // Insert tag on the client-side only.
        // Upsert later when the field is not empty.
        Meteor.call('insertTag', {x:mouseX, y:mouseY});
      }
    },

    'click .tag' : function (e) {
      isEditing = true;
    },

    'blur .tag' : function (e) {
      var currentTagId = this._id;
      var text = e.target.innerText;

      if(text) {
        Tags.upsert(currentTagId, {$set: {name: text}});
      } else {
        Tags.remove(currentTagId);
      }
    }
  });

  Template.image.helpers({
    tags: function() {
      return Tags.find();
    }
  });

  // Define methods for the collections
  Meteor.methods({
    insertTag: function(attr) {
      Tags.insert({x:attr.x, y:attr.y});
    }
  });
}

// Collections
Tags = new Meteor.Collection('tags');

image-tags.html 图像tags.html

<head>
  <title>Image Tagger</title>
</head>

<body>
  {{> image}}
</body>

<template name="image">
  <figure>
    <img src="{{image_source}}" />
    <figcaption class="tags">
        {{#each tags}}
          {{> tag}}
        {{/each}}
      </figcaption>
  </figure>
</template>


<template name="tag">
  <div class="tag" contenteditable style="left: {{x}}px; top: {{y}}px;">
    {{name}}
  </div>
</template>

You should store the temporary tag (and probably your isEditing var) in Session : 您应该在Session存储临时标记(可能还有您的isEditing var):

Session.set("isEditing", true);
Session.set("newTag", {x:mouseX, y:mouseY});

You can also create a local collection by passing null instead of a collection name when initializing it. 您还可以通过在初始化时传递null而不是集合名称来创建本地集合。 However, Session should work for what you're doing. 但是, Session应该适用于你正在做的事情。 Check out the leaderboard for an example. 查看排行榜以获取示例。

Edit: 编辑:

<figcaption class="tags">
  {{#each tags}}
    {{> tag}}
  {{/each}}
  {{#with newTag}}
    {{> tag}}
  {{/with}}
</figcaption>

Template.image.newTag = function() {
  return Session.get("newTag");
}

If you create the collection on client-side only you might have problem if you are disconnected : your new docs won't be stored on server. 如果仅在客户端创建集合,则在断开连接时可能会出现问题:新的文档将不会存储在服务器上。

To my mind the best way is to set a property "published" or "editing" or "status" (with value published / eiditing / ...) in your document. 在我看来,最好的方法是在文档中设置“已发布”或“编辑”或“状态”属性(带有值已发布/ eiditing / ...)。 Then your publish methods should return : 然后你的发布方法应该返回:

  1. All the documents of the current user 当前用户的所有文档
  2. All the documents "published" or not in "editing" status 所有文件“已发布”或未处于“编辑”状态

When a user create a document it's stored on server but with the editing status. 当用户创建文档时,它存储在服务器上但具有编辑状态。 then when you save you can decide to publish it, and then all other user will receive the document in their subscription. 然后,当您保存时,您可以决定发布它,然后所有其他用户将在其订阅中收到该文档。

Hope that alternative solution will help you 希望替代解决方案能够帮助您

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用express / mongoose和客户端JS将HTML类发布到mongoDB集合中? - How do I post an HTML class into a mongoDB collection using express/mongoose and client-side JS? 将新的集合项添加到Meteor视图后,如何运行客户端代码? - How do I run client-side code after a new collection item has been added to a Meteor view? 流星:等待客户端排序收集 - Meteor: wait for client-side sort of collection 如何为 GatsbyJS 制作仅客户端的组件? - How do I make a client-side only component for GatsbyJS? 如何获取在Meteor上的客户端的subscription方法上发布的数据? - How do I get the data published at client-side's subscribe method on Meteor? 在客户端javascript中从Meteor集合获取数据 - get data from Meteor collection in client-side javascript 如何在仅客户端的Gatsby.js页面上设置默认组件 - How can I set a default component on client-side only Gatsby.js page 如何将集合插入流星的表单中 - how do I insert a collection into a form in meteor 如何从服务器(Node JS和Express)的客户端上接收和使用JSON对象? - How do I receive and use a JSON object on the client-side from the server (Node JS and Express)? 如何使用客户端less.js导出缩小的CSS文件? - How do I export a minified CSS file using client-side less.js?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM