<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          vue el-upload 和form表單一起提交

          前端達人

          圖片上傳和表單同時一起提交

          1. <!-- 彈出框 --> <el-dialog :title="titleMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-form :model="form" :rules="rules" ref="form"> <el-form-item label="商品名稱" prop='goodsName' style="width:40%"> <el-input v-model="form.goodsName" auto-complete="off" placeholder="請輸入商品名稱" size="medium"></el-input> </el-form-item> <el-form-item label="商品圖片" prop='goodsImg'> <el-upload action="uploadAction" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :limit="1" :show-file-list="true" name="img" ref="upload" :data="form" accept="image/png,image/gif,image/jpg,image/jpeg" :headers="headers" :on-exceed="handleExceed" :auto-upload="false" :on-error="uploadError" :before-upload="handleBeforeUpload" :on-change="changeFile"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="50px" :src="dialogImageUrl" alt=""> </el-dialog> </el-form-item> <el-form-item label="商品對應積分" prop='goodsIntegral'> <el-input v-model="form.goodsIntegral" auto-complete="off" placeholder="請輸入積分" size="medium" type="number"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="cancel">取 消</el-button> <el-button type="primary" @click="uploadFileFun('form')">確 定</el-button> "注意uploadFileFun('form')  括號內記得帶引號不然可能會報validate is not defined" </div> </el-dialog> 
                              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29

          2.data部分

           data() { return { //新增和編輯彈框標題 titleMap: { addStore: '新增商品', editStore: "修改商品" }, dialogStatus: "", //新增編輯彈出框 dialogFormVisible: false, dialogVisible: false, //表格數據 tableData: [], form: { id: '', goodsName: '', goodsImg: '', goodsIntegral: '', }, rules: { goodsName: [{ required: true, message: '請輸入商品名稱', trigger: 'blur' }], goodsIntegral: [{ required: true, message: '請輸入商品積分', trigger: 'blur' }], }, headers: { Authorization: 'Bearer ' + window.localStorage.getItem("token") }, dialogImageUrl: '', //圖片回顯 uploadFiles: '', //formData img 文件 goodsId: '', //判斷是新增還是編輯 }, 
                              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          1. methods部分 手動上傳圖片 **var fd = new FormData()**添加
          // 上傳文件之前的鉤子 handleBeforeUpload(file) { console.log('按鈕', this.titleMap) if (!(file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/jpg' || file.type === 'image/jpeg')) { this.$notify.warning({ title: '警告', message: '請上傳格式為image/png, image/gif, image/jpg, image/jpeg的圖片' }) } let size = file.size / 1024 / 1024 / 2 if (size > 2) { this.$notify.warning({ title: '警告', message: '圖片大小必須小于2M' }) } }, //圖片上傳超過數量限制 handleExceed(files, fileList) { this.$message.error("上傳圖片不能超過1張!"); }, handleRemove(file, fileList) { this.$message.error("刪除成功!"); }, // 圖片上傳失敗時 uploadError() { this.$message.error("圖片上傳失敗!"); }, //預覽圖片 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, //文件改變時 on-change方法 ,fileList[0].raw 就是傳給后端的值 //filelist這個對象里面有很多屬性,我們上傳文件時,實際上傳的是filelist列表中每一項的raw,只有raw可以正常上傳, 獲取到文件后,需要定義變量保存文件。所以需要獲取filelist中的raw進行保存。 //這里我用的formdata上傳多文件,console打印formdata,文件在控制臺中顯示的格式為binary。 changeFile(file, fileList) { this.uploadFiles = fileList[0].raw }, uploadFileFun(formName) { this.$refs[formName].validate((valid) => { let fd = new FormData(); fd.append('id', this.form.id); fd.append('goodsName', this.form.goodsName); fd.append('goodsIntegral', this.form.goodsIntegral); fd.append('img', this.uploadFiles); let config = { headers: { 'Content-Type': 'multipart/form-data' } } 根據goodsID判斷是編輯提交還是新增提交,主要針對新增編輯使用同一個彈框 if (valid && !this.goodsId) { this.$axios.post("接口地址", fd, config).then(res => { if (res.data.success == true) { this.dialogFormVisible = false this.$message({ message: res.data.msg, type: 'success' }); //新增完清空表單內容 setTimeout(() => { this.$refs.form.resetFields(); }, 200) this.reload() } else { this.$message.error(res.data.msg); } }).catch(res => { console.log(res) }) } else { this.$axios.post("接口地址", fd, config).then(res => { if (res.data.success == true) { this.dialogFormVisible = false this.$message({ message: res.data.msg, type: 'success' }); //編輯完清空表單內容 setTimeout(() => { this.$refs.form.resetFields(); }, 200) this.reload() } else { this.$message.error(res.data.msg); } }).catch(res => { console.log(res) }) } }) }, add() { this.dialogStatus = "addStore" this.dialogFormVisible = true this.goodsId = "" //新增商品是商品ID為空 }, // 取消 cancel() { this.dialogFormVisible = false this.$refs[formName].resetFields() }, //編輯 handleEdit(index, row) { this.form = this.tableData[index] this.dialogStatus = "editStore" this.goodsId = row.id this.currentIndex = index this.dialogFormVisible = true }, 
                              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
          • 110
          • 111
          • 112
          • 113
          • 114
          • 115
          • 116
          • 117
          • 118
          • 119
          文章


          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務、UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司


          使用Node.js的formidable模塊實現文件上傳

          前端達人

          在我上一篇寫的Node.js實現簡單的POST請求
          里面POST請求接受參數需要寫兩個事件,這難免有些不太方便
          在這里插入圖片描述

          如果我們用formidable來接受參數的話,會變得特別方便。

          下面我們來寫一個Demo,來利用formidable來實現圖片上傳

          1.下面來看一眼 目錄結構

          在這里插入圖片描述

          2.先來寫一個簡單的前端上傳頁面

          index.html
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <meta http-equiv="X-UA-Compatible" content="ie=edge">
              <title>Document</title>
          </head>
          <body>
              <form class="upload" action="shangchuan" enctype="multipart/form-data" method="post"><!--  上傳接口是/shangchuan -->
                  <p>
                      請上傳一個頭像
                      <input type="file" name="wenjian">
                  </p>
                  <p>
                      <input type="submit" value="提交">
                  </p>
              </form>
          </body>
          </html> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20

          2.package.json 文件

          安裝依賴,執行下面這三句npm語句

          npm install finalhandler --save
          npm install serve-static --save
          npm install formidable --save

          之后會自動生成下面這個package.json文件

          {
            "dependencies": {
              "finalhandler": "^1.1.1",
              "formidable": "^1.2.1",
              "serve-static": "^1.13.2"
            }
          } 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8

          3.post.js

          var finalhandler = require('finalhandler')
          var http = require('http')
          var serveStatic = require('serve-static')
          var url = require('url')
          var fs = require('fs')
          var querystring = require('querystring')
          var formidable = require('formidable')
          var path = require('path')
          // Serve up public/ftp folder
          //配置靜態資源服務器,將public文件夾靜態化出來
          
          var serve = serveStatic('public', {'index': ['index.html', 'index.htm']})
          
          // Create server
          var server = http.createServer(function onRequest (req, res) {
              //路由
              var pathname = url.parse(req.url).pathname;
              if(pathname == '/shangchuan'){
                  //創建一個表單的實例,formidable
                  var form = new formidable.IncomingForm();
                  //設置上傳的文件存放在哪里
                  form.uploadDir = './uploads';
                  //處理表單
                  form.parse(req,(err,fields,files) => {
                      //fields 表示普通控件
                      //files 表示文件控件
                      if(!files.wenjian){
                          return;
                      }
                      if(!files.wenjian.name){
                          return;
                      }
                      var extname = path.extname(files.wenjian.name);獲取文件的擴展名,便于下面修改上傳后的文件名字
                      //改名
                      fs.rename(files.wenjian.path, files.wenjian.path + extname,() => {
                          res.end('上傳成功')
                      })
                      // console.log(fields);
                  })
                  return;
              }
              serve(req, res, finalhandler(req, res))
          })
          
          // Listen
          server.listen(3000);
          console.log('服務已經啟動在3000端口'); 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47

          4.最后找到post文件的目錄,然后開始node post.js

          會看到這個頁面

          在這里插入圖片描述

          然后選擇任意文件點擊提交
          會發現在很短的時間內你的文件會提交成功在你的uploads文件夾下。




          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          關于vue.js element ui 表單驗證 使用this.$refs[formName].validate()

          前端達人

          實現form表單提交驗證功能

          model : 綁定整個表單model
          rules : 整個表單校驗規則
          ref :獲取該表單form組件
          prop : 綁定每個表單的規則,寫在el-form-item
          validate : 對整個表單進行校驗的方法
          valid : 每個必填表單項都提交為true,否則為false

          1、簡易版 表單提交

          //使用element-ui 頁面組件 <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="活動名稱" prop="name"> <el-input v-model="ruleForm.name"></el-input> </el-form-item> <el-form-item label="活動區域" prop="region"> <el-select v-model="ruleForm.region" placeholder="請選擇活動區域"> <el-option label="區域一" value="shanghai"></el-option> <el-option label="區域二" value="beijing"></el-option> </el-select> </el-form-item> </el-form> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')">立即創建</el-button> </el-form-item> //data中定義form表單中每項表單model值、和每個表單校驗的規則 <script> export default { data() { return { ruleForm: { name: '', region: '', }, rules: { name: [ { required: true, message: '請輸入活動名稱', trigger: 'blur' }, { min: 3, max: 5, message: '長度在 3 到 5 個字符', trigger: 'blur' } ], region: [ { required: true, message: '請選擇活動區域', trigger: 'change' } ], }; }, //定義表單提交方法 methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); }, } } 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51

          2、復雜版 表單提交

          • 對于頁面有多個整體的form提交,每個form表單里類型為文本框、下拉框、單選框、復選框等類型,可對類型進行封裝,使用循環遍歷使頁面呈現不同類型表單項
          <el-form v-if="fromHtmlList.deviceInfo.sitsb.length" :model="fasj" :rules="rules" label-position="left" label-width="125px" ref='sitsb'> <el-form-item label-width="100%" > <div slot="label" class="titleInfo">局端設備</div> </el-form-item> <el-form-item v-for="(item, i) in fromHtmlList.deviceInfo.sitsb" :key="`F_key_${i}`" :label="`${item.label}:`" :class="item.class" :label-width="item.labelWidth" :prop="`${item.rule ? 'deviceInfo.sitsb.'+item.rule : ''}`"> <el-select v-if="item.el === 'slt'" v-model="fasj.deviceInfo.sitsb[item.model]" placeholder="請選擇" style="width:200px;" clearable> <el-option v-for="(op, n) in options[item.option]" :key="`vop_key_${n}`" :label="op.label" :value="op.value"> </el-option> </el-select> <el-input  v-if="item.el === 'ipt'" v-model="fasj.deviceInfo.sitsb[item.model]" @focus="()=>{ item.focus && handleFocus('sitsb', item.model)}" :placeholder="`${item.placeholder ? item.placeholder : '請輸入'}`" style="width:200px;"></el-input> <span v-if="item.el === 'txt'">{{fasj.base[item.model]}}</span> </el-form-item> </el-form> <div class="btn-list"> <el-button type="primary" @click="checkRequired">提 交</el-button> </div> <script> export default { data() { return { fasj: { base: {}, // 基本信息 deviceInfo: {}, }, //定義 頁面表單結構 fromHtmlList: { baseInfo: [], deviceInfo: { ywzsb: [], sitsb: [] } }, //定義 表單校驗規則 rules: { 'deviceInfo.sitsb.IPType': [ { required: true, message: '請輸入', trigger: 'blur' } ], 'deviceInfo.sitsb.IPAddr': [ { required: true, message: '請輸入', trigger: 'blur' } ], 'deviceInfo.sitsb.netmask': [ { required: true, message: '請輸入', trigger: 'blur' } ], 'deviceInfo.sitsb.vlanId': [ { required: true, message: '請輸入', trigger: 'blur' } ], }, options: { IPType: [ {label: 'ipv4', value: 'ipv4'}, {label: 'ipv6', value: 'ipv6'} ], rmSite: [], room: [], }, } }, created(){ const orderType = '業務開通' ;//頁面初始加載用到的變量值,可通過組件傳值獲取 //created中初始定義頁面表單結構 this.fromHtmlList = { baseInfo: orderType === '業務開通' ? [ {label: '接入方式', labelWidth: '100px', rule: '' , model: 'serviceType', option: '', el: 'txt', class: 'w2'}, {label: '標準九級地址', labelWidth: '120px', rule: '', model: 'aendAdreesName', option: '', el: 'txt', class: 'w2'}, {label: '城鄉類型', labelWidth: '100px', rule: 'cityType', model: 'cityType', option: 'cityType', el: 'slt', class: 'w2'}, {label: '方案設計附件', labelWidth: '120px', rule: '', model: 'fileId', option: '', el: 'btn', class: 'w2'}, ] : orderType === '移機' ? [ {label: '接入方式', labelWidth: '100px', rule: '' , model: 'serviceType', option: '', el: 'txt', class: 'w2'}, {label: '標準九級地址', labelWidth: '120px', rule: '', model: 'aendAdreesName', option: '', el: 'txt', class: 'w2'}, {label: '城鄉類型', labelWidth: '100px', rule: 'cityType', model: 'cityType', option: 'cityType', el: 'slt', class: 'w2'}, {label: '方案設計附件', labelWidth: '120px', rule: '', model: 'fileId', option: '', el: 'btn', class: 'w2'}, {label: '移機場景', labelWidth: '100px', rule: 'moveScene', model: 'moveScene', option: 'moveScene', el: 'slt', class: 'w2'}, {label: '是否需要網絡調整', labelWidth: '', rule: 'netChange', model: 'netChange', option: 'netChange', el: 'slt', class: 'w2'} ] : [ {label: '接入方式', labelWidth: '100px', rule: '' , model: 'serviceType', option: '', el: 'txt', class: 'w2'}, {label: '標準九級地址', labelWidth: '120px', rule: '', model: 'aendAdreesName', option: '', el: 'txt', class: 'w2'}, {label: '城鄉類型', labelWidth: '100px', rule: 'cityType', model: 'cityType', option: 'cityType', el: 'slt', class: 'w2'}, {label: '方案設計附件', labelWidth: '120px', rule: '', model: 'fileId', option: '', el: 'btn', class: 'w2'}, {label: '是否需要網絡調整', labelWidth: '', rule: 'netChange', model: 'netChange', option: 'netChange', el: 'slt', class: 'w2'}, {label: '是否更換末端設備', labelWidth: '', rule: 'devChange', model: 'devChange', option: 'devChange', el: 'slt', class: 'w2'} ], deviceInfo: { ywzsb: serviceType === 'PON' ? [ // 默認PON {label: '機房', labelWidth: '90px', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: '設備名稱', labelWidth: '90px', rule: '', model: 'deviceName', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: '設備端口', labelWidth: '90px', rule: '', model: 'devicePort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: '延伸設備', labelWidth: '90px', rule: '', model: 'deviceExtend', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'} ] : [ // 裸光纖、傳輸下沉、傳輸延伸(ywzsb) {label: '機房', labelWidth: '', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: '站點', labelWidth: '', rule: '', model: 'site', option: '', el: 'ipt', class: 'w2'}, {label: '設備名稱', labelWidth: '', rule: '', model: 'deviceName', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: '設備端口', labelWidth: '', rule: '', model: 'devicePort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, ], sitsb: serviceType === 'PON' ? [ {label: '機房名稱', labelWidth: '', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2'}, {label: '站點名稱', labelWidth: '', rule: '', model: 'site', option: '', el: 'ipt', class: 'w2'}, {label: '匯聚交換機', labelWidth: '', rule: '', model: 'switch', option: '', el: 'ipt', class: 'w2'}, {label: '匯聚交換機端口', labelWidth: '', rule: '', model: 'switchPort', option: '', el: 'ipt', class: 'w2'}, {label: 'SR/BARS', labelWidth: '', rule: '' , model: 'srbars', option: '', el: 'ipt', class: 'w2'}, {label: 'SR/BARS端口', labelWidth: '', rule: '', model: 'srbarsPort', option: '', el: 'ipt', class: 'w2'}, {label: 'IP地址類型', labelWidth: '', rule: 'IPType', model: 'IPType', option: 'IPType', el: 'slt', class: 'w2'}, {label: 'IP地址', labelWidth: '', rule: 'IPAddr', model: 'IPAddr', option: '', el: 'ipt', class: 'w2'}, {label: '子網掩碼', labelWidth: '', rule: 'netmask', model: 'netmask', option: '', el: 'ipt', class: 'w2'}, {label: 'VLAN ID', labelWidth: '', rule: 'vlanId', model: 'vlanId', option: '', el: 'ipt', class: 'w2'} ] : serviceType === '裸光纖' ? [ // 裸光纖 {label: '機房名稱', labelWidth: '', rule: '' , model: 'siteRoom', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: '站點名稱', labelWidth: '', rule: '', model: 'site', option: '', el: 'ipt', class: 'w2'}, {label: 'SR', labelWidth: '', rule: '', model: 'SR', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: 'SR端口', labelWidth: '', rule: '', model: 'SRPort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: 'BARS', labelWidth: '', rule: '' , model: 'BARS', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, {label: 'BARS端口', labelWidth: '', rule: '', model: 'BARSPort', option: '', el: 'ipt', class: 'w2', focus: true, placeholder: '點擊查詢'}, ] : [ // 傳輸下沉、傳輸延伸 ] } } }, methods:{ async checkRequired() { let checkName = ['base','sitsb'];//表單校驗定義ref let text; for(let key of checkName){ if(this.$refs[key]){ this.$refs[key].validate((valid) => { if(!valid){ text = '請檢查必填項'; }else { return false; } }); } } if(text){ this.$message.warning(text); return false; } let _res_ = await this.saveFasjData('', true);//頁面表單要保存后才能提交 if(!!_res_ && _res_.code === 200){ this.commit(_param, _url);//保存表單再提交 }else{ this.$message.error(_res_.msg) } }, async commit(param, url) { this.loadings.body = true; let _res = await postDataRequest(url, param); this.loadings.body = false; if (_res && _res.code === 200) { this.$message.success("提交成功"); this.$router.go(-1); } } } } </script> 
                  
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
          • 110
          • 111
          • 112
          • 113
          • 114
          • 115
          • 116
          • 117
          • 118
          • 119
          • 120
          • 121
          • 122
          • 123
          • 124
          • 125
          • 126
          • 127
          • 128
          • 129
          • 130
          • 131
          • 132
          • 133
          • 134
          • 135
          • 136
          • 137
          • 138
          • 139
          • 140
          • 141
          • 142
          • 143
          • 144
          • 145
          • 146
          • 147
          • 148
          • 149
          • 150
          • 151
          • 152
          • 153
          • 154
          • 155
          • 156
          • 157
          • 158
          • 159
          • 160
          • 161
          • 162
          • 163
          • 164
          • 165
          • 166
          • 167
          • 168
          • 169
          • 170
          • 171
          • 172
          • 173
          • 174
          • 175
          • 176
          • 177
          • 178

          什么是 Vite?

          前端達人

          一、什么是 Vite 

          Vite 是 vue 的作者尤雨溪在開發 vue3.0 的時候開發的一個 web 開發構建工具。由于其原生 ES 模塊導入方式,可以實現閃電般的冷服務器啟動。

          二、Vite 和 Webpack 區別

          Vite 優勢:

          1. vite 開發服務器啟動速度比 webpack 快
            webpack 會先打包,然后啟動開發服務器,請求服務器時直接給予打包結果。
            vite 在啟動開發服務器時不需要打包,也就意味著不需要分析模塊的依賴、不需要編譯,因此啟動速度非???。當瀏覽器請求某個模塊時,再根據需要對模塊內容進行編譯。這種按需動態編譯的方式,極大的縮減了編譯時間,項目越復雜、模塊越多,vite的優勢越明顯。
          2. 由于現代瀏覽器本身就支持ES Module,會自動向依賴的Module發出請求。vite充分利用這一點,將開發環境下的模塊文件,就作為瀏覽器要執行的文件,而不是像webpack那樣進行打包合并。
          3. vite 熱更新比 webpack 快
            在 HMR 方面,當改動了一個模塊后,vite僅需讓瀏覽器重新請求該模塊即可,不像webpack那樣需要把該模塊的相關依賴模塊全部編譯一次,效率更高。
          4. vite 使用esbuild(Go 編寫) 預構建依賴,比 webpack 的 nodejs,快 10-100 倍。

          Vite 劣勢:

          1. 生態不及webpack,加載器、插件不夠豐富
          2. 打包到生產環境時,vite使用傳統的 rollup(也可以自己手動安裝webpack來)進行打包
          3. 項目的開發瀏覽器要支持 ES Module,而且不能識別 CommonJS 語法

          其他區別:

               1. 打包原理的區別

          webpack
          webpack打包原理
           
          vite打包原理

               2. 項目入口文件的區別
                   
          項目根目錄的 index.html 是 Vite 項目的入口文件,而 webpack 的入口文件是 webpack 配置 entry 中指定的 js 文件。

          三、Esbuild

          Esbuild 是一款基于 Go 語言開發的 javascript 打包工具,最大的一個特征就是。

          通過官網提供的一張圖,我們可以清晰的看到 Esbuild 的表現是多么優秀:

          Esbuild 之所以能這么快,主要原因有兩個:

          • Go 語言開發,可以多線程打包,代碼直接編譯成機器碼;

            Webpack 一直被人詬病構建速度慢,主要原因是在打包構建過程中,存在大量的 resolve、loadtransform、parse 操作(詳見 為什么有人說 vite 快,有人卻說 vite 慢?- 快速的冷啟動 ),而這些操作通常是通過 javascript 代碼來執行的。要知道,javascript 并不是什么高效的語言,在執行過程中要先編譯后執行,還是單線程并且不能利用多核 cpu 優勢,和 Go 語言相比,效率很低。

          • 可充分利用多核 cpu 優勢;

          關鍵 API - transfrom & build

          Esbuild 并不復雜,它對外提供了兩個 API:transform 和 build,使用起來非常簡單。

          transfrom,轉換的意思,將 ts、jsx、tsx 等格式的內容轉化為 js。 transfrom 只負責文件內容轉換,并不會生成一個新的文件。

          build,構建的意思,根據指定的單個或者多個入口,分析依賴,并使用 loader 將不同格式的內容轉化為 js 內容,生成一個或多個 bundle 文件。

          Esbuild 在 Vite 中的巧妙使用

          我們來看看Vite 是怎么利用 Esbuild 來做預構建和內容轉換的。

          預構建

          為什么要做預構建?原因有兩點:

          • 將非 ESM 規范的代碼轉換為符合 ESM 規范的代碼;

          • 將第三方依賴內部的多個文件合并為一個,減少 http 請求數量;

          middlewares 中內容轉換

          Vite 中源文件的轉換是在 dev server 啟動以后通過 middlewares 實現的。

          當瀏覽器發起請求以后,dev sever 會通過相應的 middlewares 對請求做處理,然后將處理以后的內容返回給瀏覽器。

          middlewares 對源文件的處理,分為 resolve、load、transform、parser 四個過程:

          1. resolve - 解析 url,找到源文件的絕對路徑;

          2. load - 加載源文件。如果是第三方依賴,直接將預構建內容返回給瀏覽器;如果是業務代碼,繼續 transform、parser。

          3. transfrom - 對源文件內容做轉換,即 ts -> jsless -> css 等。轉換完成的內容可以直接返回給瀏覽器了。

          4. parser - 對轉換以后的內容做分析,找到依賴模塊,對依賴模塊做預轉換 - pre transform 操作,即重復 1 - 4

            pre transform 是 Vite 做的一個優化點。預轉換的內容會先做緩存,等瀏覽器發起請求以后,如果已經完成轉換,直接將緩存的內容返回給瀏覽器。

          Vite 在處理步驟 3 時,是通過 esbuild.transform 實現的,對比 Webpack 使用各個 loader 處理源文件,那是非常簡單、快捷的。

          四、關于 Vite 的一些其他知識

          • 在工程中不是所有的引用模塊都是ES寫法,可能是CommonJS 和 UMD 、AMD 等等,這個時候Vite 會進行預構建,將其轉換為ESM模塊,以支持Vite。
          • 對于JSX、或者TS 等需要編譯的文件,Vite是用esbuild來進行編譯的。

          五、Webpack 和 Rollup 區別

          經驗法則:對于應用使用 webpack,對于類庫使用 Rollup。

          如果你需要代碼拆分(Code Splitting),或者你有很多靜態資源需要處理,再或者你構建的項目需要引入很多CommonJS模塊的依賴,那么 webpack 是個很不錯的選擇。

          如果您的代碼庫是基于 ES2015 模塊的,而且希望你寫的代碼能夠被其他人直接使用,你需要的打包工具可能是 Rollup 。

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務、UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          nodejs--圖片上傳

          前端達人

          前端部分

          html部分

          
          
          1. <div class="add">
          2. <p>商品名稱: <input type="text" class="productName"></p>
          3. <p>商品價格: <input type="number" class="price" ></p>
          4. <!-- multiple: 允許同時上傳多張圖片 -->
          5. <!-- <p>商品圖片: <input type="file" class="file" multiple="multiple"></p> -->
          6. <p>商品圖片: <input type="file" class="file"></p>
          7. <p><button class="add-btn">添加商品</button></p>
          8. </div>
          9. <script src="js/axios.js"></script>
          10. <script src="js/util.js"></script>
          11. <script src="js/upload.js"></script>

          upload.js

          
          
          1. // 新建表單數據對象,用來存儲上傳的文件及上傳的其它數據
          2. let param = new FormData()
          3. $(".file").onchange = function(){
          4. //獲取圖片信息
          5. let file = this.files[0]
          6. //"file"為前后端約定vb的屬性名
          7. param.append("file",file)
          8. }
          9. $(".add-btn").onclick = function(){
          10. let productName = $(".productName").value;
          11. let price = $(".price").value;
          12. param.append("productName",productName)
          13. param.append("price",price)
          14. axios.post("/product",param,{
          15. headers: {
          16. // 默認提交的類型
          17. // "content-type": "application/json"
          18. // 復雜的表單數據(只要上傳文件,就必須是下面的類型)
          19. "content-type": "multipart/form-data"
          20. }
          21. })
          22. .then((res)=>{
          23. console.log(res.data);
          24. })
          25. }

          postman

           

          Express后端部分

          使用multer實現圖片上傳

          下載

          npm i multer -S

          引入

          
          
          1. const multer = require("multer")
          2. const path = require("path")

          配置

          注意: 該文件在/router文件夾中,而uploads存放上傳圖片文件夾在根目錄

          
          
          1. var storage = multer.diskStorage({
          2. // 配置文件上傳后存儲的路徑
          3. destination: function (req, file, cb) {
          4. // NodeJS的兩個全局變量
          5. // console.log(__dirname); //獲取當前文件在服務器上的完整目錄
          6. // console.log(__filename); //獲取當前文件在服務器上的完整路徑
          7. cb(null, path.join(__dirname,'../uploads'))
          8. },
          9. // 配置文件上傳后存儲的路徑和文件名
          10. filename: function (req, file, cb) {
          11. console.log('file',file);
          12. cb(null, Date.now() + path.extname(file.originalname))
          13. }
          14. })
          15. var upload = multer({ storage: storage })

          在路由中使用

          
          
          1. //添加商品
          2. router.post("/product",upload.single("file1"),(req,res)=>{
          3. //接收普通文本參數
          4. let {productName,price} = req.body;
          5. 、接收上傳文件數據 -->
          6. let imgUrl = req.file.filename;
          7. let sql = "insert into product (productName,price,imgUrl) values (?,?,?)"
          8. conn.query(sql,[productName, price , imgUrl],(err,result)=>{
          9. if (err){
          10. console.log('增加失敗');
          11. return;
          12. }
          13. let data;
          14. if (result.affectedRows === 1){
          15. data = {
          16. code: 0,
          17. msg: '添加成功'
          18. }
          19. }else{
          20. data = {
          21. code: 1,
          22. msg: '添加失敗'
          23. }
          24. }
          25. res.send(data)
          26. })
          27. })

          如果抽離路由模塊中的處理函數upload.single("file1")寫在Router模塊

          實現寫在抽取的模塊 

           NODEJS--express圖片上傳 - 簡書

          如果req.body為空,可以用nodejs后臺文件上傳模塊connect-multiparty

          使用方法如下:

          1.  安裝模塊

          npm install connect-multiparty --save

          2.  引入模塊

          var multipart = require('connect-multiparty');

          var multipartMiddleware = multipart();

          3.  使用模塊

          const express = require('express')

          const router = express.Router()

          router.post('/formdata',multipartMiddleware, function (req,res) {

          console.log(req.query)

          //分別返回body,文件屬性,以及文件存放地址

          });
          ————————————————
          原文鏈接:https://blog.csdn.net/zjwengyidong/article/details/51407903




          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務、UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          HTML生日快樂-生日祝福(煙花+粒子動畫)

          前端達人

          一、HTML頁面制作

          1、更換title

          在HappyBirthday/HappyBirthday.html中的title換成相應人的名字

           
          
          1. <head>
          2. <meta charset="utf-8">
          3. <title>XXX生日快樂</title>
          4. <style>
          5. html,body{
          6. margin:0px;
          7. width:100%;
          8. height:100%;
          9. overflow:hidden;
          10. background:linear-gradient(to left top,blue, #ffc0cb);
          11. }
          12. </style>
          13. <link href="favicon.ico" rel="shortcut icon">
          14. </head>

          2、粒子名字

          在粒子展示祝福的名字進行更換

           在HappyBirthday/js/index.js#44行處修改

           
          
          1. if (i !== -1) {
          2. S.UI.simulate(decodeURI(action).substring(i + 3));
          3. } else {
          4. S.UI.simulate('|#countdown 3||祝|XXX|生日快樂|祝你|生日快樂|祝你幸福|祝你健康|前途光明|祝你|生日快樂!|#icon heart|#icon heart-empty|#icon heart');
          5. }

          3、粒子顏色

          修改粒子動畫展示的顏色,視頻中使用了粉色(255,192,203)

          HappyBirthday/js/index.js#417行處修改

           
          
          1. S.Dot = function (x, y) {
          2. this.p = new S.Point({
          3. x: x,
          4. y: y,
          5. z: 5,
          6. a: 1,
          7. h: 0
          8. });
          9. this.e = 0.07;
          10. this.s = true;
          11. this.c = new S.Color(255, 192, 203, this.p.a);
          12. this.t = this.clone();
          13. this.q = [];
          14. };

          4、設備兼容

          在原版代碼中,僅僅在電腦瀏覽器有一個較為好的展示效果,在手機瀏覽器上字顯示效果不佳以及延時不足,但是無法正常顯示,主要調整了粒子間距和延時時間

          粒子間距:先設置默認間距為8(手機較好顯示),然后判斷屏幕是否大于手機一般尺寸,調整大一點13(平板和電腦較好顯示)。

          粒子間距變小,數量變多,加載起來就慢。

          HappyBirthday/js/index.js#525行處修改

           
          
          1. if ((window.innerWidth>500 && window.innerHeight>500)){
          2. gap = 13;
          3. }

          延時時間:當粒子數量變多,加載慢, 按照原作者設置的時間來展示,可能上一個字沒展示完就要去展示下一個字,導致變成一坨。

          HappyBirthday/js/index.js#119行處修改

          HappyBirthday/js/index.js#177行處修改

           
          
          1. // 118行
          2. var delay1,delay2;
          3. delay1 = 3000;
          4. delay2 = 5000;
          5. // 177行
          6. if (window.innerWidth>500 && window.innerHeight>500){
          7. delay1 = 1000;
          8. delay2 = 2000;
          9. }

          5、音樂播放

          由于在某些設備上,無法自動播放音樂,需要通過點擊觸發,增加點擊愛心,開始播放。

          二、阿里云部署

          通過部署在阿里云,可以通過網址進行訪問。

          我租了一個阿里云,通過簡單部署靜態頁面就可以訪問。

          (如果有兄弟緊急使用,也可以叫我幫忙部署一下,哈

          1、開放80端口

          找到自己的實例,點擊完全組,配置開放一個80端口 

          開放80端口

          2、安裝httpd

          yum -y install httpd

           3、啟動httpd

           
          
          1. service httpd start
          2. service httpd status

           啟動之后可以看到如下畫面

           4、移動httpd.conf

          默認會發布var/www/html下面的網頁

          cp /etc/httpd/conf/httpd.conf /var/www/html

          5、上傳資源到var/www/html

           
          
          1. # 解壓壓縮包
          2. unzip HappyBirthday.zip
          3. # 刪除壓縮包
          4. rm -rf HappyBirthday.zip

          6、重啟hhtpd

           service httpd restart

          7、地址訪問

          http://8.130.106.21/HappyBirthday/HappyBirthday.html
          

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。

          分享此文一切功德,皆悉回向給文章原作者及眾讀者. 免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務、UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          Vue3中全局配置 axios 的兩種方式

          前端達人

          目錄

          一、回顧 Vue2 的全局引用方式

            1. 簡單項目的全局引用

          2. 復雜項目的三步封裝

          二、Vue3 中的使用 

          1. provide/inject 方式

          2. getCurrentInstance 組合式API引入


           

           

          一、回顧 Vue2 的全局引用方式

            1. 簡單項目的全局引用

              如果只是簡單幾個頁面的使用,無需太過復雜的配置就可以直接再 main.js 中進行掛載

          
          
          1. import Vue from "vue";
          2. /* 第一步下載 axios 命令:npm i axios 或者yarn add axios 或者pnpm i axios */
          3. /* 第二步引入axios */
          4. import axios from 'axios'
          5. // 掛載一個自定義屬性$http
          6. Vue.prototype.$http = axios
          7. // 全局配置axios請求根路徑(axios.默認配置.請求根路徑)
          8. axios.defaults.baseURL = 'http://yufei.shop:3000'

             頁面使用

          
          
          1. methods:{
          2. getData(){
          3. this.$http.get('/barry').then(res=>{
          4. console.log('res',res)
          5. )}
          6. }
          7. }

          2. 復雜項目的三步封裝

            ① 新建 util/request.js (配置全局的Axios,請求攔截、響應攔截等)

                  關于 VFrame 有疑問的同學可以移步  前端不使用 il8n,如何優雅的實現多語言?

          
          
          1. import axios from "axios";
          2. import { Notification, MessageBox, Message } from "element-ui";
          3. import store from "@/store";
          4. import { getToken } from "@/utils/auth";
          5. import errorCode from "@/utils/errorCode";
          6. import Cookies from "js-cookie";
          7. import VFrame from "../framework/VFrame.js";
          8. import CONSTANT from '@/CONSTANT.js'
          9. axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
          10. // 創建axios實例
          11. const service = axios.create({
          12. // axios中請求配置有baseURL選項,表示請求URL公共部分
          13. baseURL: process.env.VUE_APP_BASE_API,
          14. // 超時
          15. timeout: 120000
          16. });
          17. // request攔截器
          18. service.interceptors.request.use(
          19. config => {
          20. // 是否需要設置 token
          21. const isToken = (config.headers || {}).isToken === false;
          22. if (getToken() && !isToken) {
          23. config.headers["Authorization"] = "Bearer " + getToken(); // 讓每個請求攜帶自定義token 請根據實際情況自行修改
          24. }
          25. var cultureName = Cookies.get(CONSTANT.UX_LANGUAGE);
          26. if (cultureName) {
          27. config.headers[CONSTANT.UX_LANGUAGE] = cultureName; // 讓每個請求攜帶自定義token 請根據實際情況自行修改
          28. }
          29. // get請求映射params參數
          30. if (config.method === "get" && config.params) {
          31. let url = config.url + "?";
          32. for (const propName of Object.keys(config.params)) {
          33. const value = config.params[propName];
          34. var part = encodeURIComponent(propName) + "=";
          35. if (value !== null && typeof value !== "undefined") {
          36. if (typeof value === "object") {
          37. for (const key of Object.keys(value)) {
          38. let params = propName + "[" + key + "]";
          39. var subPart = encodeURIComponent(params) + "=";
          40. url += subPart + encodeURIComponent(value[key]) + "&";
          41. }
          42. } else {
          43. url += part + encodeURIComponent(value) + "&";
          44. }
          45. }
          46. }
          47. url = url.slice(0, -1);
          48. config.params = {};
          49. config.url = url;
          50. }
          51. return config;
          52. },
          53. error => {
          54. console.log(error);
          55. Promise.reject(error);
          56. }
          57. );
          58. // 響應攔截器
          59. service.interceptors.response.use(
          60. res => {
          61. // 未設置狀態碼則默認成功狀態
          62. const code = res.data.code || 200;
          63. // 獲取錯誤信息
          64. const msg = errorCode[code] || res.data.msg || errorCode["default"];
          65. if (code === 401) {
          66. MessageBox.alert(
          67. VFrame.l("SessionExpired"),
          68. VFrame.l("SystemInfo"),
          69. {
          70. confirmButtonText: VFrame.l("Relogin"),
          71. type: "warning"
          72. }
          73. ).then(() => {
          74. store.dispatch("LogOut").then(() => {
          75. location.href = "/index";
          76. });
          77. });
          78. } else if (code === 500) {
          79. Message({
          80. message: msg,
          81. type: "error"
          82. });
          83. if (res.data.data) {
          84. console.error(res.data.data)
          85. }
          86. return Promise.reject(new Error(msg));
          87. } else if (code !== 200) {
          88. Notification.error({
          89. title: msg
          90. });
          91. return Promise.reject("error");
          92. } else {
          93. if (res.data.uxApi) {
          94. if (res.data.success) {
          95. return res.data.result;
          96. } else {
          97. Notification.error({ title: res.data.error });
          98. console.error(res);
          99. return Promise.reject(res.data.error);
          100. }
          101. } else {
          102. return res.data;
          103. }
          104. }
          105. },
          106. error => {
          107. console.log("err" + error);
          108. let { message } = error;
          109. if (message == "Network Error") {
          110. message = VFrame.l("TheBackEndPortConnectionIsAbnormal");
          111. } else if (message.includes("timeout")) {
          112. message = VFrame.l("TheSystemInterfaceRequestTimedOut");
          113. } else if (message.includes("Request failed with status code")) {
          114. message =
          115. VFrame.l("SystemInterface") +
          116. message.substr(message.length - 3) +
          117. VFrame.l("Abnormal");
          118. }
          119. Message({
          120. message: VFrame.l(message),
          121. type: "error",
          122. duration: 5 * 1000
          123. });
          124. return Promise.reject(error);
          125. }
          126. );
          127. export default service;

            ② 新建 api/login.js (配置頁面所需使用的 api)

          
          
          1. import request from '@/utils/request'
          2. // 登錄方法
          3. export function login(username, password,shopOrgId,counter, code, uuid) {
          4. const data = {
          5. username,
          6. password,
          7. shopOrgId,
          8. counter,
          9. uuid
          10. }
          11. return request({
          12. url: '/login',
          13. method: 'post',
          14. data: data
          15. })
          16. }
          17. // 獲取用戶詳細信息
          18. export function getInfo() {
          19. return request({
          20. url: '/getInfo',
          21. method: 'get'
          22. })
          23. }
          24. // 退出方法
          25. export function logout() {
          26. return request({
          27. url: '/logout',
          28. method: 'post'
          29. })
          30. }

            ③ 頁面使用引入

          
          
          1. import { login } from "@/api/login.js"
          2. 接下來不用多說,相信大家已經會使用了

          二、Vue3 中的使用 

           上面回顧完 Vue2 中使用 axios 我們來一起看看 Vue3 中axios的使用( 簡單Demo,前臺使用Vue3,后臺使用 node.js ),僅供學習!

          1. provide/inject 方式

              ① main.js 中 使用 provide 傳入

          
          
          1. import {
          2. createApp
          3. } from 'vue'
          4. import App from './App.vue'
          5. import router from './router'
          6. import store from './store'
          7. import "lib-flexible/flexible.js"
          8. import axios from "@/util/request.js"
          9. const app = createApp(App);
          10. app.provide('$axios', axios)
          11. app.use(store).use(router).mount('#app');

              ② 需要用到的頁面使用 inject 接受

          
          
          1. import { ref, reactive, inject, onMounted} from "vue";
          2. export default {
          3. setup() {
          4. const $axios = inject("$axios");
          5. const getData = async () => {
          6. data = await $axios({ url: "/one/data" });
          7. console.log("data", data);
          8. };
          9. onMounted(() => {
          10. getData()
          11. })
          12. return { getData }
          13. }
          14. }

          這個就是借助 provide 做一個派發,和 Vue2 中的差距使用方法差距不大 

           

          2. getCurrentInstance 組合式API引入

           ① main.js 中掛載

          
          
          1. import {
          2. createApp
          3. } from 'vue'
          4. import App from './App.vue'
          5. import router from './router'
          6. import store from './store'
          7. import "lib-flexible/flexible.js"
          8. import axios from "@/util/request.js"
          9. const app = createApp(App);
          10. /* 掛載全局對象 */
          11. app.config.globalProperties.$axios = axios;
          12. app.use(store).use(router).mount('#app');

          /* 掛載全局對象 */
          app.config.globalProperties.$axios = axios;

          重點就是上面這句

          ② 需要用的頁面使用 Composition Api -- getCurrentInstance 拿到

          
          
          1. <script>
          2. import { reactive, onMounted, getCurrentInstance } from "vue";
          3. export default {
          4. setup() {
          5. let data = reactive([]);
          6. /**
          7. * 1. 通過getCurrentInstance方法獲取當前實例
          8. * 再根據當前實例找到全局實例對象appContext,進而拿到全局實例的config.globalProperties。
          9. */
          10. const currentInstance = getCurrentInstance();
          11. const { $axios } = currentInstance.appContext.config.globalProperties;
          12. /**
          13. * 2. 通過getCurrentInstance方法獲取上下文,這里的proxy就相當于this。
          14. */
          15. const { proxy } = currentInstance;
          16. const getData = async () => {
          17. data = await $axios({ url: "/one/data" });
          18. console.log("data", data);
          19. };
          20. const getData2 = async () => {
          21. data = await proxy.$axios({ url: "/one/data" });
          22. console.log("data2", data);
          23. };
          24. onMounted(() => {
          25. getData()
          26. });
          27. return { getData };
          28. },
          29. };
          30. </script>

          下圖可以看到我們確實調用了 2次 API 

          其實通過 Composition API 中的 getCurrentInstance 方法也是有兩種方式的

           1. 通過 getCurrentInstance 方法獲取當前實例,再根據當前實例找到全局實例對象appContext,進而拿到全局實例的config.globalProperties。        

          
              
          1. const currentInstance = getCurrentInstance();
          2. const { $axios } = currentInstance.appContext.config.globalProperties;

           2. 通過getCurrentInstance方法獲取上下文,這里的proxy就相當于this。

          
              
          1. const currentInstance = getCurrentInstance();
          2. const { proxy } = currentInstance;
          3. const getData2 = async () => {
          4. data = await proxy.$axios({ url: "/one/data" });
          5. console.log("data2", data);
          6. };

           


          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          用 JavaScript 檢測瀏覽器在線/離線狀態(JavaScript API?—?navigator.onLine)

          前端達人

          如今HTML5 移動應用或 Web app 中越來越普遍的使用了離線瀏覽技術,所以用 JavaScript 檢測瀏覽器在線/離線狀態非常常見。

          無論瀏覽器是否在線,navigator.onLine 屬性都會提供一個布爾值。 如果瀏覽器在線,則設置為 true ,否則設置為 false 。

           if(navigator.onLine) { // true|false // ... }

          online 和 offline 事件:

          當瀏覽器脫機或上線時,瀏覽器還支持 online 和 offline 事件。

          window.addEventListener('online', function(e){console.log('online')});
          window.addEventListener('offline', function(e){console.log('offline');});

          你可以使用幾種熟悉的方式來注冊事件:

          • 在 windowdocument,或 document.body 上使用 addEventListener
          • 將 document 或 document.body 的 ononline 或 onoffline 屬性設置為一個 JavaScript Function 對象。(注意:由于兼容性原因,不能使用 window.ononline 或 window.onoffline。)
          • 在 HTML 標記中的 body 標簽上指定 οnοnline=”…” 或 οnοffline=”…” 特性。

          注意事項:

          • IE8中需要給document.body綁定事件而不是window
          • 在線離線的變化指的是物理上的網絡鏈接變化,如果是在控制臺將網絡限制為 offline 則不會觸發相應的事件。

          實例代碼:

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>用 JavaScript 檢測瀏覽器在線/離線狀態(JavaScript API?—?navigator.onLine)</title>
              <style type="text/css"> #status {
                      position: fixed;
                      width: 100%;
                      font: bold 1em sans-serif;
                      color: #FFF;
                      padding: 0.5em;
                  }
                  #log {
                      padding: 2.5em 0.5em 0.5em;
                      font: 1em sans-serif;
                  }
                  .online {
                      background: green;
                  }
                  .offline {
                      background: red;
                  } </style>
          </head>
          <body>
          <div id="status"></div>
          <div id="log"></div>
          <button type="button" id="test">檢查狀態</button>
          <script> window.addEventListener('load', function () { var testBtn = document.getElementById("test"); var status = document.getElementById("status"); var log = document.getElementById("log");
          
              function updateOnlineStatus(event) { var condition = navigator.onLine ? "online" : "offline";
                  status.className = condition;
                  status.innerHTML = condition.toUpperCase();
          
                  log.insertAdjacentHTML("beforeend", "Event: " + (event?event.type:"-") + "; Status: " + condition+ " | ");
              }
          
              window.addEventListener('online', updateOnlineStatus);
              window.addEventListener('offline', updateOnlineStatus);
              testBtn.addEventListener("click", updateOnlineStatus);
              updateOnlineStatus();
          }); </script>
          </body>
          </html>
              

          總結:

          1、navigator.online屬性提供瀏覽器是否在線的布爾值

          2、瀏覽器脫機或上線還支持online和offline事件(IE8需要給document.body綁定事件而不是window)

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務、UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          【小程序開發】uniapp引入iconfont圖標及使用方式

          前端達人

          第一步:打開iconfont官網新建項目并添加自己所需要的圖標

          這里是iconfont的網址鏈接: iconfon官網
          在這里插入圖片描述

          新建項目

          不 要 勾 選 彩 色 , 會 導 致 在 項 目 中 無 法 修 改 字 體 顏 色 及 樣 式 , 本 人 親 測 , 找 了 半 天 解 決 辦 法 最 終 悔 恨 不 已 \textcolor{red} {不要勾選彩色,會導致在項目中無法修改字體顏色及樣式,本人親測,找了半天解決辦法最終悔恨不已},,

          • App下原生導航欄的按鈕如果使用字體圖標,注意檢查字體庫的名字(font-family)是否使用了默認的 iconfont,這個名字是保留字,不能作為外部引入的字體庫的名字,需要調整為自定義的名稱,否則無法顯示
          • 按鈕上顯示的文字。使用字體圖標時 unicode 字符表示必須 ‘\u’ 開頭,如 “\ue123”(注意不能寫成"\e123")。

          選擇自己需要的圖標加入購物車再添加到項目中

          在這里插入圖片描述
          在這里插入圖片描述

          第二步:下載我們所需要的iconfont.css文件并引入到項目中

          在這里插入圖片描述

          下載項目并解壓

          在這里插入圖片描述

          將iconfont.css文件復制放到我們的項目中去,一般放在static靜態文件目錄下

          第三步:修改iconfont.css文件中的內容并全局引用

          在這里插入圖片描述
          在這里插入圖片描述

          需要注意的是,當我們在項目中新添加了圖標后,需要重新復制修改iconfont.css中的內容,要不然新添加的圖標是找不到的

          在這里插入圖片描述

          在移動端引用的時候要在App.vue文件中進行全局注冊,而不是main.js中

          第四步:使用iconfont圖標進行開發

          在開發中我們常用的有兩種方式,這兩種方式以及注意事項我在以下內容都有演示:

          • 在頁面文件中直接使用標簽
          • 使用APPplus原生的自定義導航欄iconfont右側自定義圖標

          1.在頁面文件中直接使用標簽

          在這里插入圖片描述

          兩種方式代碼的獲取方式如下圖所示:

          • 使用uniCode碼
          • Font Class 名稱

          在這里插入圖片描述

          在這里插入圖片描述

          2.使用APPplus原生的自定義導航欄iconfont右側自定義圖標

          使用iconfont圖標的文件內容(忽略css樣式):
          在這里插入圖片描述
          需要配合static目錄下的iconfont.tff文件,這個文件在我們下載到本地的時候那個目錄中,與iconfont.css在一個目錄中:
          在這里插入圖片描述
          pages.json文件中配置iconfont圖標:
          在這里插入圖片描述

          這三步完成,我們配置自定義原生導航欄的自定義圖標就完成啦!

          五:需要注意的點寫在這里:

          1. iconfont官網創建項目的時候,不要勾選彩 色 \textcolor{red} {彩色} 那個多選框,否則使用的時候不能更改顏色
          2. 如果項目重新添加了新的圖標,需要重新生成在線鏈接,更新iconfont.css文件
          3. 自定義原生導航欄使用iconfont圖標時,必須配合iconfont.ttf文件使用


          作者:彩云sky
          來源:人人都是產品經理
          著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          web3:區塊鏈常見的幾大共識機制及優缺點

          前端達人

          什么是共識?

          我們所說的共識,是指達成了廣泛的一致。 比如,一群人去吃晚飯, 如果他們對于提議“吃某火鍋”沒有任何異議,那么就可以說共識達成了。 如果存在異議,那么他們就必須通過某種方法決定吃什么。 在極端情況下,這群人就會分開。


          什么是共識機制?

          區塊鏈要成為一個難以攻破的、公開的、不可篡改數據記錄的去中心化誠實可信系統,需要在盡可能短的時間內做到分布式數據記錄的安全、明確及不可逆,提供一個最堅實且去中心化的系統。共識機制在區塊鏈中成為了重要的因素之一。

          區塊鏈分布式記賬的方式使得每個人手上都有一本完整的賬本,全網共有。但是隨著節點的不斷增多,數據越多,賬本也越安全,難以摧毀。除此之外,任意一個或者部分節點的賬本被篡改,都不可能被全網認同,除非你能控制51%的節點,即51%攻擊,但是這耗能巨大,幾乎是不可能的。同時隨著節點不斷增加,誰來記賬,如何選擇合適的人來記賬成為一個問題,而制定一個記賬人的選擇方式以及規定,讓大家來遵守這個規定,達成共識,這就是區塊鏈里面的共識機制。

          共識機制是區塊鏈節點就區塊信息達成全網一致共識的機制,說得更直白一些就是要解決所謂去中心化的信任問題,因為每個節點之間默認是不認識且不可靠的,同時每個節點都不能知道其他節點是否宕機或者背叛的情況下,盡可能的保證記錄信息的準確性以及安全性。同時節點越分散,效率越低,網絡對于信息的滿意度越高,越安全。


          共識機制的目標

          區塊鏈作為一種按時間順序存儲數據的數據結構,可支持不同的共識機制。共識機制是區塊鏈技術的重要組件。區塊鏈共識機制的目標是使所有的誠實節點保存一致的區塊鏈視圖,同時滿足兩個性質:
          1)一致性:所有誠實節點保存的區塊鏈的前綴部分完全相同。
          2)有效性:由某誠實節點發布的信息終將被其他所有誠實節點記錄在自己的區塊鏈中。


          為什么需要共識機制?

          在分布式系統中,各個不同的主機通過異步通信方式組成網絡集群。為了保證每個主機達成一致的狀態共識,就需要在主機之間進行狀態復制。異步系統中,可能會出現各樣的問題,例如主機出現故障無法通信,或者性能下降,而網絡也可能發生擁堵延遲,類似的種種故障有可能會發生錯誤信息在系統內傳播。因此需要在默認不可靠的異步網絡中定義容錯協議,以確保各主機達成安全可靠的狀態共識。所以,利用區塊鏈構造基于互聯網的去中心化賬本,需要解決的首要問題是如何實現不同賬本節點上的賬本數據的一致性和正確性。

          這就需要借鑒已有的在分布式系統中實現狀態共識的算法,確定網絡中選擇記賬節點的機制,以及如何保障賬本數據在全網中形成正確、一致的共識。


          如何評價一個共識機制的優劣:

          1. 安全性:能否有效防止二次支付,私自挖礦
          2. 擴展性:當系統成員和待確認交易數量增加時,所帶來的系統負載和網絡通信量的變化,通常以網絡吞吐量來衡量
          3. 性能效率:每秒可以處理的交易數量
          4. 資源消耗:達成共識過程中,所要消耗的CPU、內存等計算資源

          共識機制分類

          沒有一種共識機制是完美無缺的,各共識機制都有其優缺點,有些共識機制是為解決一些特定的問題而生。

          BTC作為區塊鏈的第一個應用,它的共識機制PoW共識機制曾經一枝獨秀,但是隨著區塊鏈技術的不斷發展,各類不同的共識機制開始不斷涌現,各有千秋,各有擁躉。

          常見的共識就機制包括:POW(工作量證明機制)、POS(權益證明機制)、POW+POS(混合共識機制)、DPOS(股份授權證明)等等,另外還有Pool驗證池、Ripple瑞波共識協議、PBFT(使用拜占庭容錯算法)等等

          PoW( Proof of Work)工作量證明:多勞多得

          在這里插入圖片描述

          最早(也是第一個)被應用的共識機制,最先被BTC采用并且獲取了巨大成功,它支撐了BTC系統長達 10 多年無重大故障使其平穩運行。而且 PoW 構想也符合創始人中本聰最初的設想:人人皆可挖礦、按勞分配、公平公正。

          PoW 屬于按勞分配,多勞多得,就如同大家在BTC系統中一起進行數學運算,最先運算出的才能獲得獎勵。是一種衡量計算機工作量的共識機制。BTC使用的就是工作量證明機制。

          工作量證明主要通過哈希計算找出合理數據的步驟來完成:將區塊頭數據帶入哈希函數計算公式,不斷調整區塊頭數據中的隨機數,直到計算出滿足特定標準的哈希值,工作量證明就會完成。

          簡單來說就是多勞多得,誰的算力強,計算得就更快,獲得記賬權的概率就越高,算力競爭的勝者將獲得相應區塊記賬權和BTC獎勵。 因此,礦機芯片的算力越高,挖礦的時間更長,就可以獲得更多的數字貨幣。進行運算獲得獎勵的過程稱之為挖礦,參與挖礦的人們稱之為礦工。這種證明方式決定了其驗證過程需要大量的數據計算,而其他節點卻很容易驗證計算結果是否正確,因此 區塊鏈系統無法被惡意節點所欺騙。但是這種證明方式需要消耗大量能源(電力及計算硬件損耗),很不 環保。并且在理論上,如果集合了全網51%的算力即可對區塊鏈網絡進行有效攻擊,因此許多基于比特幣 代碼產生的、市值較小的山寨幣很容易遭受攻擊。

          代表token:BTC、BCH、LTC等。

          優點

          • 公平公正:去中心化程度高,人人都可以參與獲得記賬權;
          • 安全系數高:全網算力越高,其安全程度也越高,如破壞該系統需要投入巨大成本;
          • 算法簡單,容易實現

          缺點

          • 資源浪費:因每一筆交易都需要通過多數礦工的確認,在這些礦工進行運算的過程中消耗大量的電力資源等。
          • 效率低下:區塊的確認時間難以縮短;容易產生分叉,需要等待多個確認。
          • 算力集中:根據往年數據顯示,在資本大量進入的情況下,過去一年礦池算力份額排名前五位的礦池占據了BTC總算力份額的 65%,馬太效應逐漸顯現,而算力過度集中還存在著 51% 攻擊的風險。
          • 永遠沒有最終性,需要檢查點機制來彌補最終性。

          PoS(Proof of Stake)股權證明算法:持有越多,獲得越多

          在這里插入圖片描述

          因 PoW 存在的問題,PoS 在主流算法一路暢通的“殺了出來”,成為了最具有挑戰者。近幾年,基于 PoS共識打造的區塊鏈項目越來越多,如目前市值保持第二的ETH也加入了 PoS?!癝taking經濟”在 2019年成為了熱門詞語,同時也被交易所和錢包大力追捧。

          POS機制采用類似股權證明與投票的機制,選出記帳人,由它來創建區塊。持有股權愈多則有較大的特權,且需負擔更多的責任來產生區塊,同時也獲得更多收益的權力。 POS 機制中一般用幣齡來計算記賬權,每個幣持有一天算一個幣齡,比如 持有 100 個幣,總共持有了 30 天,那么此時的幣齡就為 3000。在 POS機制下,如果記賬人發現一個 POS 區塊, 他的幣齡就會被清空為 0,每被清空 365 幣齡,將會從區塊中獲得 0.05 個幣的利息(可理解為年利率 5%)。

          PoS權益證明同樣需要通過計算找出合理的哈希值來完成。 但不同的是權益證明機制通過節點持有加密貨幣的時間和數量來判斷節點的權益大小。根據權益大小不同,用戶之間看到的計算目標值也不同。權益大的節點,獲得目標值更加簡單,更容易獲得下一個區塊的記賬權。 這種方式不需要每個節點都進行大量的運算,節省了電力能源。同時全網51%的算力攻擊在權益證明機制下是無效的,因為發起這種攻擊反而會損害自身的利益。但是可能會出現幣種持有數量大的節點權力過 大,對區塊鏈記賬享有絕對支配權的情況,容易引發信任問題。

          在 PoS 機制中,是不需要消耗電力來進行運算,而是通過抵押 token 來獲得打包區塊的權利。當一筆交易發生時,系統會對打包區塊和驗證區塊的節點來進行獎勵,獎勵則是增發或者解鎖的 token。

          代表token:ADA、ONT、ATOM等。

          優點

          • 不浪費資源、效率高:因其不需要拼算力挖礦,同時縮短了共識達成的時間,轉賬效率提高了;
          • 弱化了中心礦池規模經濟的需求:算力集中壟斷的情形也得到了緩解,個體競爭力差別相對減??;

          缺點

          • 被動形成中心化:因去中心化程度,容易出現強者恒強的情況,會導致富者越富,資源越來越集中的情況。
          • 安全隱患:PoS機制實現較為復雜,容易產生安全漏洞。
          • 無權益問題(Nothing at Stake):用戶在PoS中可以同時在兩個分叉上面下注;無論哪一個分叉后面被公認為主鏈,該用戶都可以獲得獎勵而沒有機會成本的損失。這樣也在事實上會干擾共識的形成。
          • 還是需要挖礦,本質上沒有解決商業應用的痛點。

          DPOS(Delegated Proof-of-Stake)股份授權證明

          在這里插入圖片描述

          DPoS 機制是在 PoS 的基礎上進行了改良,舉例來說就是大家公認的投出選票,選舉出一定數量的代表,讓這些代表進行驗證和記賬等,可以理解為PoS 的升級版。與PoS的主要區別在于持幣者投出一定數量的節點,代理他們進行驗證和記賬。其合規監管、性能、資源消耗和容錯性與PoS相似。

          DPoS的工作原理為:每個股東按其持股比例擁有影響力,51%股東投票的結果將是不可逆且有約束力的。其挑戰是通過及時而高效的方法達到51%批準。為達到這個目標,每個股東可以將其投票權授予一名代表。獲票數最多的前100位代表按既定時間表輪流產生區塊。每名代表分配到一個時間段來生產區塊。所有的代表將收到等同于一個平均水平的區塊所含交易費的10%作為報酬。如果一個平均水平的區塊含有100股作為交易費,一名代表將獲得1股作為報酬。DPoS的投票模式可以每30秒產生一個新區塊。

          簡單點說:DPoS 委托權益證明通過由持幣人投票選舉出一定數量的代表來達成共識。 每個持幣人的投票所占的比重 與他持有的幣種數量有關,持有的越多,所占的比重越大。被選出的代表可擁有記賬權,輪流進行記賬;未能很好履行職責的代表還會被投票除名。這一任期結束后,新的代表會再次通過投票產生。

          代表token:EOS、TRX等。

          優點

          • 比 PoS 機制擁有更高的效率和性能:相比于 PoS 機制,DPoS 大幅縮小了參與驗證和記賬的節點數量,可以達到秒級的共識驗證。

          缺點

          • 整個共識機制還是依賴于token,很多商業應用是不需要代幣存在的。
          • 去中心化程度低:相比較于只能說是弱中心化;
          • 安全問題嚴重:類 PoS 機制的通病,相信大家都看到過報道,如被黑客攻擊等等。

          PoC(Proof of Capacity)容量證明機制

          在這里插入圖片描述

          PoC 機制早在 2014年存在了,但只是一直處于“落魄階段”,簡單說就是沒火,無人問津。2019年隨著POC一大公鏈Yottachain的崛起,越來越多的礦工加入了POC硬盤挖礦這個行業大軍了。它是POW共識機制的一種,以硬盤作為共識參與者,它的特點是犧牲性能獲得安全可信,相對POW減少了非常多的安全和信任成本,更低成本解決了全局信任和安全,幾乎不耗電力資源,并且可共享和復用的信任生態。

          PoC 機制是通過普通硬盤挖礦的共識機制。簡單來說就是利用計算機硬盤中的閑置空間來進行存儲進行挖礦獲取收益,硬盤空間越大,存儲的內容越多獲得的收益就越大。 它更多地關注內存而不是處理能力。 從某種意義上說,這是對PoW的改進,即使在挖掘開始之前,容量證明也要求節點將預先計算的哈希值存儲在其硬盤驅動器和其他內存單元上,這個過程稱為繪圖,繪圖使容量證明成為比工作證明更快的機制。這種方法的另一個優點是它可以節省大量能源,這與工作量證明機制不同。更不用說,硬盤存儲更多哈希值的任何技術改進也將為不在區塊鏈中的人改進技術,這與許多制造商制造的專用芯片不同,后者除了采礦之外什么都不做。

          IPFS 也類似,但不同的是 IPFS 衍生的區塊鏈項目(激勵層Filecoin)是一種去中心化存儲服務的 Marketplace(撮合交易的市場),它的重點在于如何在系統參與者互不信任的條件下,實現存儲和檢索工作的量化;PoC 是一種底層共識機制,與 PoW、PoS一樣都是去中心化網絡達成一致性狀態的算法。由此來看,兩者是完全不同的概念,唯一的共同點就是都可以使用硬盤向網絡貢獻價值來換取收益。

          代表token:BTT、BHD等。

          優點

          • 挖礦門檻較低:只要有硬盤就可以進行挖礦,大大降低了挖礦門檻;PoC的礦機耗電量低、噪音小、成本低,適合家庭挖礦和人人挖礦。
          • 去中心化程度較高:抵押機制提高了算力集中化的門檻,即便有超級礦工出現,普通散戶也可以繼續獲得收益。
          • 能源消耗低,節能:相比于PoW,POC挖礦將算力替換成硬盤空間,在很大程度的杜絕了POW挖礦造成的資源浪費以及對環境不友好等問題,同時降低了挖礦成本,讓礦工從挖礦中賺取更多的利潤。
          • 反壟斷:用硬盤容量替代了算力,天然具有抗ASIC的屬性

          缺點

          • 未來發展的局限性可能較大
          • 可能會有政策性風險
          • PoC并沒有實現真正的平等

          DAG(Directed acyclic graph)有向無環圖:無區塊鏈概念

          在這里插入圖片描述

          有向無環圖是計算機科學中眾所周知的數據結構。事實上,區塊鏈也是DAG的一個例子,因為它有一個明確的方向,沒有任何循環,并且是一個圖。1OTA使用的Tangle也是DAG共識機制的一種形式。在這種機制中,每個塊必須有兩個父塊。所以,為了通過DAG共識機制完成一筆交易,用戶需要驗證自己之前的兩筆交易。這種機制的最大優勢是它可以減少延遲和交易費用。然而,這種共識模型對提高可擴展性幾乎沒有任何作用,而且極易受到攻擊,因為任何攻擊只需要34%的哈希算力就可以破壞系統。

          DAG最初出現就是為了解決區塊鏈的效率問題。其通過改變區塊的鏈式存儲結構,通過DAG的拓撲結構來存儲區塊。在區塊打包時間不變的情況下,網絡中可以并行的打包N個區塊,網絡中的交易就可以容納N倍。

          之后DAG發展成為脫離區塊鏈,提出了blockless無區塊的概念。新交易發起時,只需要選擇網絡中已經存在的并且比較新的交易作為鏈接確認,這一做法解決了網絡寬度問題,大大加快了交易速度。

          代表token:IOTA、byteball等。
          前段時間國內首個基于DAG的物聯網區塊鏈項目ITC萬物鏈也取得了不小的漲幅。

          優點

          • 交易速度快;
          • 無需挖礦;
          • 極低的手續費

          缺點

          • 網絡規模不大,導致極易成為中心化;
          • 安全性低于PoW機制

          PBFT(Practical Byzantine Fault Tolerance)實用拜占庭容錯:分布式一致性算法

          實用拜占庭容錯在保證活性和安全性(liveness & safety)的前提下提供了(n-1)/3的容錯性。
          在分布式計算上,不同的計算機透過訊息交換,嘗試達成共識;但有時候,系統上協調計算機(Coordinator / Commander)或成員計算機 (Member /Lieutanent)可能因系統錯誤并交換錯的訊息,導致影響最終的系統一致性。拜占庭將軍問題就根據錯誤計算機的數量,尋找可能的解決辦法,這無法找到一個絕對的答案,但只可以用來驗證一個機制的有效程度。而拜占庭問題的可能解決方法為:在 N ≥ 3F + 1 的情況下一致性是可能解決。其中,N為計算機總數,F為有問題計算機總數。信息在計算機間互相交換后,各計算機列出所有得到的信息,以大多數的結果作為解決辦法。

          優點

          • 系統運轉可以脫離幣的存在,pbft算法共識各節點由業務的參與方或者監管方組成,安全性與穩定性由業務相關方保證。
          • 共識的時延大約在2~5秒鐘,基本達到商用實時處理的要求。
          • 共識效率高,可滿足高頻交易量的需求。

          缺點

          • 當有1/3或以上記賬人停止工作后,系統將無法提供服務;
          • 當有1/3或以上記賬人聯合作惡,且其它所有的記賬人被恰好分割為兩個網絡孤島時,惡意記賬人可以使系統出現分叉,但是會留下密碼學證據

          實用拜占庭容錯主要應用于央行的數字貨幣以及布萌區塊鏈。


          dBFT(delegated BFT)授權拜占庭容錯算法

          小蟻采用的dBFT機制,是由權益來選出記賬人,然后記賬人之間通過拜占庭容錯算法來達成共識。dBFT和PBFT的關系類似于PoS和DPoS的關系。

          dBFT在PBFT基礎上進行了以下改進:

          1. 將C/S架構的請求響應模式,改進為適合P2P網絡的對等節點模式;
          2. 將靜態的共識參與節點改進為可動態進入、退出的動態共識參與節點;
          3. 為共識參與節點的產生設計了一套基于持有權益比例的投票機制,通過投票決定共識參與節點(記賬節點);
          4. 在區塊鏈中引入數字證書,解決了投票中對記賬節點真實身份的認證問題。

          優點

          • 專業化的記賬人;
          • 可以容忍任何類型的錯誤;
          • 記賬由多人協同完成,每一個區塊都有最終性,不會分叉;
          • 算法的可靠性有嚴格的數學證明;

          缺點

          • 當有1/3或以上記賬人停止工作后,系統將無法提供服務;
          • 當有1/3或以上記賬人聯合作惡,且其它所有的記賬人被恰好分割為兩個網絡孤島時,惡意記賬人可以使系統出現分叉,但是會留下密碼學證據;

          以上總結來說,dBFT機制最核心的一點,就是最大限度地確保系統的最終性,使區塊鏈能夠適用于真正的金融應用場景。


          Pool驗證池——私有鏈專用

          基于傳統的分布式一致性技術,加上數據驗證機制;之前曾是行業鏈大范圍在使用的共識機制,但是隨著私有鏈項目的逐漸減少漸漸開始勢微。

          優點

          不需要token也可以工作,在成熟的分布式一致性算法(Pasox、Raft)基礎上,實現秒級共識驗證。

          缺點

          去中心化程度不如bictoin;更適合多方參與的多中心商業模式。

          參考

          拜占庭將軍問題

          拜占庭將軍問題是一個協議問題,拜占庭帝國軍隊的將軍們必須全體一致的決定是否攻擊某一支敵軍。問題是這些將軍在地理上是分隔開來的,并且將軍中存在叛徒。叛徒可以任意行動以達到以下目標:欺騙某些將軍采取進攻行動;促成一個不是所有將軍都同意的決定,如當將軍們不希望進攻時促成進攻行動;或者迷惑某些將軍,使他們無法做出決定。如果叛徒達到了這些目的之一,則任何攻擊行動的結果都是注定要失敗的,只有完全達成一致的努力才能獲得勝利。

          這一問題是一種對現實世界的模型化,尤指網絡當中由于軟硬件錯誤、網絡阻塞及惡意攻擊導致的各種未知行為。
          顯然,在此處默認了將軍們在達成一致的過程中正確的傳遞出了自己的決定,也就是說叛徒只存在于將軍當中,不存在于傳令兵當中。故要讓拜占庭將軍問題有解,必須要具備一個重要前提,即信道必須是安全可靠的。關于信道可靠問題,會引出兩軍問題。兩軍問題的結論是,在一個不可靠的通信鏈路上試圖通過通信以達成一致是基本不可能或者十分困難的。

          拜占庭容錯

          拜占庭將軍問題提出后,有很多的算法被提出用于解決這個問題。這類算法統稱拜占庭容錯算法(BFT: Byzantine Fault Tolerance)。簡略來說,拜占庭容錯(BFT)不是某一個具體算法,而是能夠抵抗拜占庭將軍問題導致的一系列失利的系統特點。 這意味著即使某些節點出現缺點或惡意行為,拜占庭容錯系統也能夠繼續運轉。本質上來說,拜占庭容錯方案就是少數服從多數。

          拜占庭將軍問題的原始論文給出了一些解決思路,但其更注重理論上的可行性。算法效率不高,算法復雜度為指數級,且文中明確指出時間成本及消息傳遞數量很大。因此不具備太大的實用價值。

          拜占庭容錯系統需要達成如下兩個指標
          ● 安全性:任何已經完成的請求都不會被更改,它可以在以后請求看到。在區塊鏈系統中,可以理解為,已經生成的賬本不可篡改,并且可以被節點隨時查看。
          ● 活性:可以接受并且執行非拜占庭客戶端的請求,不會被任何因素影響而導致非拜占庭客戶端的請求不能執行。在區塊鏈系統中,可以理解為,系統需要持續生成區塊,為用戶記賬,這主要靠挖礦的激勵機制來保證。

          拜占庭系統目前普遍采用的假設條件包括:
          ● 拜占庭節點的行為可以是任意的,拜占庭節點之間可以共謀;
          ● 節點之間的錯誤是不相關的;
          ● 節點之間通過異步網絡連接,網絡中的消息可能丟失、亂序、延時到達;
          ● 服務器之間傳遞的信息,第三方可以知曉 ,但是不能竄改、偽造信息的內容和驗證信息的完整性;

          科普 | 什么是共識機制?

          詳解區塊鏈中常見的八大共識機制!

          區塊鏈的幾大共識機制及優缺點




          作者:彩云sky
          來源:人人都是產品經理
          著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請加藍小助,微信號:ben_lanlan,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系01063334945。


          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務、UI設計公司、界面設計公司、UI設計服務公司、數據可視化設計公司、UI交互設計公司、高端網站設計公司、UI咨詢、用戶體驗公司、軟件界面設計公司

          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合