sharedb結合elementUi編寫的實時小工具


  我是使用sharedb 作為后端 ,然后前端使用的elementUI樣式,編寫的一個值班小工具。接下來,讓我們先來了解一下sharedb是什么吧?

  • sharedb工具

  github地址:https://github.com/share/sharedb.git

  官方概念:ShareDB是基於JSON文檔的操作轉換(OT)實時數據庫后端它是DerbyJS Web應用程序框架的實時后端

  特征:

    1. 實時同步任何JSON文檔
    2. 並發多用戶協作
    3. 具有異步最終一致性的同步編輯API
    4. 實時查詢訂閱
    5. 與任何數據庫輕松集成-MongoDBPostgresQL(實驗性)
    6. 通過發布/訂閱集成可水平擴展
    7. 從文檔和操作中選擇所需字段的投影
    8. 用於實現訪問控制和自定義擴展的中間件
    9. 非常適合在瀏覽器或服務器上使用
    10. 重新連接后脫機更改同步
    11. 用於單元測試的數據庫和pub / sub的內存中實現

   在這里,我只列出sharedb的概念以及特征,其中的其他特性(包括中間件等等),大家可以自行去github上去看。

   對於我來說,我是把github上的代碼克隆下來,然后選擇了其中的counter作為例子模板,去編寫工具代碼,首先對其中的server.js進行更改.

在server.js中,我只改了 doc.create({ name1: [], date: [] }, callback);這一行代碼,在sharedb文檔中doc.create(data[, type][, options][, function(err) {...}]) 在本地創建文檔,然后將創建操作發送到服務器。因為對於我的需求,就是要將名字,以及對應名字所選的日期發送到服務器上,所以在這里我創建了這個對象。

  server.js

var http = require('http');
var express = require('express');
var ShareDB = require('sharedb');
var WebSocket = require('ws');
var WebSocketJSONStream = require('websocket-json-stream');

var backend = new ShareDB();
createDoc(startServer);
// Create initial document then fire callback
function createDoc(callback) {
  var connection = backend.connect();
  var doc = connection.get('examples', 'counter');
  doc.fetch(function (err) {
    if (err) throw err;
    if (doc.type === null) {
      doc.create({ name1: [], date: [] }, callback);
      return;
    };
    callback();
  });
}
function startServer() {
  // Create a web server to serve files and listen to WebSocket connections
  var app = express();
  app.use(express.static('static'));
  var server = http.createServer(app);
  // Connect any incoming WebSocket connection to ShareDB
  var wss = new WebSocket.Server({ server: server });
  wss.on('connection', function (ws, req) {
    var stream = new WebSocketJSONStream(ws);
    backend.listen(stream);
  });

  server.listen(8080);
  console.log('Listening on http://localhost:8080');
}

  client.js代碼:

var sharedb = require('sharedb/lib/client');

// Open WebSocket connection to ShareDB server
var socket = new WebSocket('ws://' + window.location.host);
var connection = new sharedb.Connection(socket);

// Create local Doc instance mapped to 'examples' collection document with id 'counter'
var doc = connection.get('examples', 'counter');

// 獲取文檔的初始值並訂閱更改
doc.subscribe(showNames);
doc.subscribe(dateRanges);
// 當文檔更改時(由此客戶端或任何其他客戶端或服務器),
// 更新頁面上的名字以及日期范圍
doc.on('op', showNames);
doc.on('op', dateRanges);

function dateRanges() {
  app.$data.items = doc.data.date[0];
};
function showNames() {
  app.$data.messages1 = doc.data.name1[0] ? doc.data.name1[0] : [];
};
// 當點擊提交名字的時候,更改本地的名字,並將同步更改服務器和其它鏈接的客戶端//提交日期
function submite() {
  doc.submitOp([{ p: ['date', 0], li: app.$data.items }]);
};
//提交名字
function display() {
  doc.submitOp([{ p: ['name1', 0], li: app.$data.messages1 }]);
};
// Expose to index.html
global.display = display;
global.submite = submite;

html代碼

這個代碼就沒什么好說的啦,主要功能 就是可以先輸入名字,然后再選擇想要進行值班的日期。而輸入的名字不可以有重復的,主要是靠一個復選框實現的,以及日期選擇器,感興趣的同學可以看看哦!,大家也可以看到這里面引用的js是bundle.js,所以我們要把寫在client.js中的代碼,復制到bundle.js中才可以實現哦。

<!DOCTYPE html>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<link rel="icon" href="1.ico">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<title>值班小工具</title>

<body>
  <div id="app" >
    <router-view> </router-view>
  </div>
</body>
<script src="dist/bundle.js"></script>
<script>
  const inputName = {
    template: `<div>
                 <el-header>
                  <el-input id="date" placeholder="請輸入用戶名" name="date" v-model="message"></el-input>
                  <el-button v-on:click="display1" type="primary">提交 名字</el-button> 
                  </el-header> 
                  <el-main>
                      <span class="date">日 期</span>
                      <span class="name">姓 名</span>
                  <el-checkbox-group  v-model="checked"  >
                      <li v-for="(item,index) in $root.items" :key="item.checked">
                         <el-checkbox 
                              v-on:change="checked1(index,checked)" 
                              :label="item"
                              name="item"
                              >
                              {{item}}
                              <span class="messages">{{[$root.messages1[index]].join("|")}}</span>
                         </el-checkbox>
                      </li>
                  </el-checkbox-group>
                  </el-main>
              </div>` ,
    data() {
      name: inputName;
      return {
        message: '',
        messages1: [],
        checked: []
      }
    },
    methods: {
      checked1: function () {
      },
      display1: function (index, checked) {
        var a = document.getElementsByName('item');
        this.messages1 = this.$root.messages1;
        var cashName = document.getElementById("date").value;
        var result = cashName.match(/[\s`~!@#¥$%^&*()_+<>?:"{},.\/;'[\]\w]/im);
        for (var i = 0; i < a.length; i++) {
          if (result !== null) {
            this.$message({
              message: '請輸入正確的名字哦!',
              type: 'warning'
            });
            break
          }
          if (a[i].checked && this.messages1[i] == null) {
            this.messages1[i] = new Array;
          }
          if (a[i].checked && this.messages1[i] !== null && this.messages1[i][0] !== this.message) {
            this.messages1[i].push(this.message);
          }
          if (a[i].checked && this.messages1[i] !== null && this.messages1[i].length > 2) {
            this.messages1[i].pop(this.message);
            this.$message({
              message: '前面已經有兩人選擇了哦,請選擇其它日期吧!',
              type: 'warning'
            });
          }
        }
        display()
      }
    }
  };
  const inputDate = {
    template: `<div>
                 <el-header>
                  <el-date-picker
                      v-model="value"
                      type="daterange"
                      range-separator=""
                      start-placeholder="開始日期"
                      end-placeholder="結束日期"
                      format="yyyy年M月d日"
                      value-format="yyyy-MM-dd"
                      v-on:change="change1"
                    >
                  </el-date-picker>
                  <el-button onclick="submite()" type="primary">提交 日期</el-button>
                  </el-header>
                   <el-main>
                      <span class="date">日 期</span>
                      <span class="name">姓 名</span>
                      <li v-for="(item,index) in $root.items" :key="item.index">
                            {{item}}
                            <span class="messages1">{{[$root.messages1[index]].join('&')}}</span>
                      </li>
                  </el-main>
              </div>`,
    data() {
      name: inputDate;
      return {
        items: [],
        value: '',
      }
    },
    methods: {
      change1(value) {
        var begin = value[0];
        var end = value[1];
        var item = new Array();
        app.$data.items = item;
        var ab = begin.split("-");
        var ae = end.split("-");
        var db = new Date();
        db.setUTCFullYear(ab[0], ab[1] - 1, ab[2]);
        var de = new Date();
        de.setUTCFullYear(ae[0], ae[1] - 1, ae[2]);
        var unixDb = db.getTime();
        var unixDe = de.getTime();
        for (var k = unixDb; k <= unixDe;) {
          item.push(new Date(parseInt(k)).format().toString());
          k = k + 24 * 60 * 60 * 1000;
        }
      }
    }
  };
  const routes = [
    { path: '/inputDate', component: inputDate },
    { path: '/inputName', component: inputName }
  ];
  const router = new VueRouter({
    routes
  });
  Date.prototype.format = function () {
    var s = "";
    s += this.getFullYear() + "-";
    s += this.getMonth() + 1 + "-";
    s += this.getDate();
    return s;
  };
  var app = new Vue({
    router,
    data() {
      return {
        value6: '',
        items: [],
        checked: [],
        message: '',
        messages1: [],
        checked: []
      }
    }
  }).$mount('#app');
</script>
<style scoped>
  #app {
    /* width: 1200px;
    height: 848px; */
    background-position: center;
    padding-top: 0%;
  }

  body {
    margin: 0%;
  }

  .el-checkbox__label {
    display: inline-block;
    padding-left: 10px;
    line-height: 19px;
    font-size: 14px;
    width: 100%;
  }

  .el-date-picker {
    width: 30%;
  }

  h3 {
    margin: 40px 0 0;
  }

  a {
    color: #42b983;
  }

  .el-header {
   
    color: #333;
    text-align: center;
    line-height: 88px;
  }

  li {
    padding-top: 2%;
    list-style-image: url('./4.ico');
  }

  p {
    font-size: 20px;
    font-family: 'Segoe UI', Tahoma, Verdana, sans-serif
  }

  .date {
    padding-left: 10%;
  }

  .name {
    padding-left: 40%;
  }

  .el-main {
    padding-top: 1%;
    padding-left: 35%;
    width: 70%;
    height: 550px;
  }

  .el-input {
    width: 30%;
  }

  .messages1 {
    float: right;
    padding-right: 27%;
    text-decoration: underline;
  }

  .messages {
    float: right;
    padding-right: 24%;
    text-decoration: underline;
  }

  .el-checkbox {
    width: 80%;
    color: black;

  }
</style>

第一次寫博客,可能有些地方寫的不是很完整,歡迎大家提出意見!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM