w3ctech

(译)使用Vue & deepstream构建实时CRUD应用

原文9号彩票地址 :https://scotch.io/tutorials/build-a-realtime-crud-app-with-vue-deepstream

译者注:在9号彩票Win dows下需使用管理员权限启动deepstream server


JavaScript是当前最流行的语言,因为9号彩票你 可以用它为任何平台(包括网站,9号彩票服务 器,移动设备和桌面)构建应用程序。

JS入门教程

代码

Vue是一个渐进式的JavaScript UI9号彩票工具 ,很容易上手,您可以在一天之内就学会它。另一方面,它拥有足够强大的功能以满足您的前端需求。

实时9号彩票技术 正在逐渐展现出新的形态;实时9号彩票服务 器现在用作处理实时相关任务的抽象。deepstream是一个开源,免费和极速的实时9号彩票服务 器,您可以在您的机器上安装。

本文演示了使用deepstream和Vue作为9号彩票9号彩票我 们 的前端9号彩票工具 来构建实时应用程序。下面的GIF就是9号彩票9号彩票我 们 将要实现的内容:

在开始代码之前,让9号彩票9号彩票我 们 说服自己为什么非得如此。

为什么要使用Vue

Vue.js Homepage

依9号彩票我 拙见,Vue是一个迄今为止最简单的而且值得一试的UI框架。首先它很容易上手,其次它帮9号彩票9号彩票我 们 实现了数据绑定,9号彩票服务 端渲染和状态管理等在考虑UI库时所遇到的复杂的概念。

Vue考虑到现有UI库的复杂性,并简化了这些复杂性,使9号彩票9号彩票我 们 的9号彩票生活不像9号彩票软件 工程师那么沮丧。它也支持9号彩票9号彩票我 们 最喜欢的后端9号彩票工具 ,Laravel--使用的集成更简单。这当然不意味着9号彩票你 不能与任何其他后端平台集成。

为什么是Deepsteam

deepstream Homepage

deepstream是一个独立的9号彩票服务 器--它比大多数的实时解决方案都要--它允许您使用持久状态作为数据同步,pub/sub模式作为事件或者请求/响应模式作为RPC。

您可以放心,通过丰富的选项,deepstream可以集成在9号彩票你 正在开发的任何性质的应用程序中。包括但不限于聊天,实时新闻更新,库存信息,CRUD/CMS应用,数据可视化,数据监控等。

安装Vue和deepstream

安装Vue和deepstream相当简单,您只需要几条CLI命令就可以完成安装。

deepstream是跨平台的,可以安装在Linux,9号彩票Win dows和OSX上。与此同时,9号彩票你 也可以通过Docker和npm来安装它。对于这篇文章,9号彩票9号彩票我 们 将9号彩票下载 操作系统相对应的deepstream。解压9号彩票下载 的文件,然后在解压后的文件夹根目录执行以下命令来启动9号彩票服务 器:

./deepstream

vue-cli是一个可以让9号彩票你 快速创建Vue项目的CLI9号彩票工具 。9号彩票9号彩票我 们 需要安装这个9号彩票工具 以便创建9号彩票9号彩票我 们 的demo应用。

npm i -g vue-cli

通过全局安装vue-cli9号彩票工具 ,9号彩票9号彩票我 们 可以在任何地方使用这个命令。Vue脚手架有不同的模版,9号彩票9号彩票我 们 只需要通过以下命令使用最简单的模版即可:

vue init webpack my-project

用Vue实现CRUD

在9号彩票9号彩票我 们 尝试构建一个实时应用之前,让9号彩票9号彩票我 们 先创建一个平台。一个图书的CRUD(增删查改)应用 看起来是个好主意。

Creating

src文件夹中的App.vue文件是9号彩票9号彩票我 们 的主要和唯一的组件,这对于9号彩票9号彩票我 们 正在尝试构建的应用而言是足够的。打开app.vue文件创建一个简单的form:

<!-- ./src/App.vue -->
<template>
  <div id="app">
    <h1> {{ title }} </h1>
    <h3>New Book</h3>
    <form v-on:submit.prevent="onSubmit">
      <div>
        <input name="title" type="text" placeholder="title" v-model="book.title" />
      </div>
      <div>
        <input name="year" type="text" placeholder="year" v-model="book.year" />
      </div>
      <div>
        <input name="author" type="text" placeholder="author" v-model="book.author" />
      </div>
      <div>
        <label for="read">Read?</label>
        <input type="checkbox" v-model="book.read" id="read" name="read" />
      </div>
      <button v-if="updating">Update</button>
      <button v-else>Add</button>
    </form>
  </div>
</template>

<script>

export default {
  name: 'app',
  data () {
    return {
      title: 'My Books Manager',
      updating: false,
      book: {
        title: '',
        year: '',
        author: '',
        read: false
      }
    }
  }
}
</script>

app.vue就是9号彩票9号彩票我 们 熟知的Vue单文件组件。这是Vue应用的一个很好的策略,它允许每个组件将其模版,样式和业务逻辑保存在一个文件中。

9号彩票9号彩票我 们 用Vue数据绑定实现了一个基本的表单。每一个表单项都通过v-model与Vuedata9号彩票方法 返回的book对象的属性进行绑定。Vue data9号彩票方法 还返回了用作APP头部的标题和切换addupdate按钮的更新标识。通过v-if...v-else指令可以实现切换。

当有按钮被点击时,onSubmit9号彩票方法 便会触发,因为在上面9号彩票9号彩票我 们 通过v-on:submit指令给form绑定了这个9号彩票方法 。因此接下来9号彩票9号彩票我 们 需要创建这样一个9号彩票方法 :

export default {
  name: 'app',
  data () {
    return {
      // ...
      updateIndex: 0,
      books: [],
      book: {
        title: '',
        year: '',
        author: '',
        read: false
      }
    }
  },
  methods: {
    onSubmit () {
      if (this.updating) {
        this.onUpdate();
        return;
      }
      this.book.push(this.book);
      this.book = {
        title: '',
        year: '',
        author: '',
        read: false
      }
    }
  }
}

onSubmit会检查是否是更新操作。如果是更新操作,它将调用onUpdate9号彩票方法 来处理更新。反之,它将把新的book对象push到books数组里面。

Reading

通过使用v-for指令迭代books数组,9号彩票9号彩票我 们 可以通过表格将其展示出来。

<template>
  <div id="app">
    <h1> {{ title }} </h1>
    <h3>New Book</h3>
    <!-- For markup truncated -->
    <h3>All Books</h3>
    <table>
      <tr>
        <th>Title</th>
        <th>Year</th>
        <th>Author</th>
        <th>Read</th>
        <td>Update</td>
        <td>Delete</td>
      </tr>
      <tr v-for="(b, index) in books">
        <td>{{ b.title }}</td>
        <td>{{ b.year }}</td>
        <td>{{ b.author }}</td>
        <td v-if="b.read">✓</td>
        <td v-else> </td>
        <td v-on:click.prevent="onEdit(index)"><a>✎</a></td>
        <td v-on:click.prevent="onDelete(index)"><a>✗</a></td>
      </tr>
    </table>
  </div>
</template>

表格数据行中额外的两个链接来处理编辑(不是更新)和9号彩票删除 记录,它们分别调用onEditonDelete9号彩票方法 。您可以在表单中输入一些信息,然后在表格中查看结果:

Updating

更新操作需要两个步骤 - 从表中选择9号彩票9号彩票我 们 需要更新的记录,这将使它展现在表单中,并更改数组以更新值。

onEdit9号彩票方法 负责第一个阶段:

data () {
  return {
    updating: false;
    updateIndex: 0,
    books: [],
    book: {
      title: '',
      year: '',
      author: '',
      read: false
    }
  }
},
methods: {
  // ...
  onEdit (index) {
    this.updating = true;
    this.updateIndex = index;
    this.book = this.books[index];
  }
}

onEdit9号彩票方法 首先将更新标识设置为true,然后将updateIndex设置为正在编辑的索引,并用在更新的索引中找到的记录替换书模型。

updateIndex用于跟踪调用onUpdate时正在更新的内容.

onUpdate () {
  this.updating = false;
  this.book[this.updateIndex] = this.book;
  this.book = {
    title: '',
    year: '',
    author: '',
    read: false
  }
},

onUpdate重置了更新标识,并更新了数组中位置为updateIndex的book对象,然后将book对象清空了。

Deleting

这是最简单的一部分;9号彩票9号彩票我 们 使用数组splice9号彩票方法 从数组中9号彩票删除 一个项目:

onDelete (index) {
  // Remove one item starting at
  // the specified index
  this.book.splice(index, 1)
}

使用deepstream实现实时

9号彩票9号彩票我 们 已经创建了一个可以运行的应用,但这并不是9号彩票9号彩票我 们 的最终目的,当表格中的数据发生变化时9号彩票9号彩票我 们 需要让所有连接的客户端都可以接收到变化,这正是deepstream的用武之地。目前9号彩票9号彩票我 们 这么做,其他客户端并不会接受到更新。

deepstream客户端 记录 & 列表

在这篇文章的开头,9号彩票9号彩票我 们 安装并启动了deepstream9号彩票服务 器。实际上,这个9号彩票服务 器运行在本机的6020端口上,且处于空闲状态等待客户端连接交换数据。

deepstream客户端可以是任何形式的,从Web,桌面,移动,甚至物联网。9号彩票9号彩票我 们 今天所关心的只是Web,所以9号彩票9号彩票我 们 需要使用deepstream的JS SDK来连接9号彩票服务 器。您可以通过执行下面的命令来安装SDK:

npm i --save deepstream.io-client-js

deepstream中的记录和任何其他表示数据的形式的记录一样,它是单个实体并存储给定的信息项。唯一的区别在于deepstream中的记录是实时的,这意味着记录中存储的数据可以被客户端订阅,并且以最小的有效载荷通知客户端。

另一方面,列表可以很好的像集合那样9号彩票组织 数据。列表也是实时的,所以他们的实时更新也可以被客户端订阅。9号彩票9号彩票我 们 将在9号彩票9号彩票我 们 的应用程序中使用deepstream的这些功能,使应用程序实时。

身份验证

身份验证就是在任何情况下您都可以确认用户的身份是否和她表明的身份一致。通常的HTTP验证在处理这个问题时和deepstream有那么一点不同。然而,好消息是,9号彩票你 可以很简单的把它们结合在一起使用

对于每一个deepstream的连接客户端,身份验证是必须的,但这并不意味着必须提供凭据。登录可以是匿名的,并适用于9号彩票9号彩票我 们 当前的情况。

import * as ds from 'deepstream.io-client-js';

export default {
  name: 'app',
  data () {
    return {
      ds: ds('localhost:6020'),
      books$$: null
      // . . .
    }
  },
  created () {
    this.ds.login({}, () => {
      console.log('logged in');
    });
  },
  methods: {/* . . .*/}
}

首先9号彩票9号彩票我 们 导入了client模块,然后创建了一个9号彩票成员 变量ds来保存对deepstream的引用,同时传递9号彩票服务 器的URL。

created9号彩票方法 在组件处于ready状态时被Vue调用。这使得9号彩票9号彩票我 们 可以在这个9号彩票方法 中处理deepstream身份验证,通过调用接收凭证对象和回调的deepstream.login9号彩票方法 来执行认证。

books$$属性将引用9号彩票9号彩票我 们 尚未创建的deepstream中的数据列表。

9号彩票9号彩票我 们 将改写CRUD过程,并用deepstream对其进行更新。但是在这之前,9号彩票9号彩票我 们 需要使所有连接的客户端能够监听到值的改变,以便它们可以相应的更新。

订阅List和Records

created () {
    this.ds.login({}, () => {
      console.log('logged in');
    });

    this.books$$ = this.ds.record.getList('books');
    /*
    * Entry added
    */
    this.books$$.on('entry-added', (recordName, index) => {
       this.ds.record.getRecord(recordName).whenReady(record => {

        // The scond paramaeter,
        // a boolean, is a flag to specify whether 
        // the callback should be invoked immediatly
        // with the current value
         record.subscribe(data => {
              if(!data.id) {
                if(data.title) {
                  data.id = record.name;
                  this.books.push(data);
                }
              } else {

              this.books = this.books.map(b => {
                      if(data.id == b.id) {
                            b = data;
                        }
                        console.log(b)
                          return b;
                    });
              }
         }, true) 
       });
    });
    /*
     * Entry removed
     */

    this.books$$.on('entry-removed', (recordName, index) => {
       this.ds.record.getRecord(recordName).whenReady(record => {
         record.subscribe(data => {
             this.books.splice(this.books.indexOf(data, 1));
         }, true) 
       });
    });
  },
  • Lists和records API依赖record对象,9号彩票9号彩票我 们 可以通过给getList9号彩票方法 传入一个名称来创建或检索列表。
  • entry-added事件在记录添加到列表中时触发。
  • 当记录已经添加,whenReady9号彩票方法 确保该记录在9号彩票9号彩票我 们 通过subscribe9号彩票方法 订阅之前处于ready状态。
  • subscribe9号彩票方法 接受一个回调来检查数据,如果数据存在,则更新它。反之则用传入的数据更新记录,同时将数据的id设置为记录名称(id),books数组随着数据的进入而更新。
  • entry-removed正好和entry-added事件刚好相反。它在9号彩票9号彩票我 们 9号彩票删除 记录的时候触发,以便从books数组中9号彩票删除 记录的数据。

Creating

onSubmit9号彩票方法 需要重写。9号彩票9号彩票我 们 不会直接将data push到books数组中因为这部分的工作已经被9号彩票9号彩票我 们 的订阅处理了。9号彩票9号彩票我 们 仅仅需要调用9号彩票方法 创建一个带数据的record对象并将它添加到列表中:

onSubmit() {
   const recordName = this.book.id || 'book/' + this.ds.getUid();

   this.ds.record.has(recordName, (err, has) => {
     if(has){
       this.onUpdate();
       return;
     } else {
        const bookRecord = this.ds.record.getRecord(recordName);
         bookRecord.set(this.book);

         this.books$$.addEntry(recordName)

         this.book = {
           title: '',
           year: '',
           author: '',
           read: false
         }
     }
   })
 },

如果数据存在,则使用UUID或附加到数据的Id来创建/获取记录。has用于检查该记录是否存在,如果存在,9号彩票9号彩票我 们 调用onUpdate9号彩票方法 ;反之,9号彩票9号彩票我 们 将nnew book设置为记录,并使用addEntry更新book$$列表.

Updating

onUpdate() {
   const recordName = this.books[this.updateIndex].id;
   const bookRecord = this.ds.record.getRecord(recordName);
   bookRecord.set(this.book);
   this.book = {
     title: '',
     year: '',
     author: '',
     read: false
   }

   this.updating = false;
 }

onSubmit中,如果记录名字存在则调用了onUpdate9号彩票方法 进行更新。

onUpdate通过updateIndex在books数组里检索记录名称。9号彩票9号彩票我 们 得到相应的记录并用book去更新记录。这里不需要对list进行任何操作,它会自动的进行相应的更新。

Deleting

onDeleting9号彩票方法 仅仅调用了list的removeEntry来9号彩票删除 一个记录:

onDelete(index) {
  this.books$$.removeEntry(this.books[index].id);
 }

总结

随着更先进的解决方案的出现,构建实时应用程序变得越来越好。 您还可以使用HTTP认证或JWT认证,以及当您需要持久化数据时将您的数据库连接到deepstream。

令人着迷的是9号彩票9号彩票我 们 可以使用Vue和deepstream构建更好的UI应用程序。Vue并不是唯一一个受到社区欢迎的框架。您可以使用相同的初始化和身份验证策略将deepstream与任何其他UI库集成在一起。

w3ctech微信

扫码关注w3ctech微信9号彩票公众号

共收到0条回复