亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

vue雙向數據綁定知識點總結

2019-11-19 14:00:59
字體:
來源:轉載
供稿:網友

1.原理

vue的雙向數據綁定的原理相信大家都十分了解;主要是通過ES5的Object對象的defineProperty屬性;重寫data的set和get函數來實現的

所以接下來不使用ES6進行實際的代碼開發;過程中如果函數使用父級this的情況;還是使用顯示緩存中間變量和閉包來處理;原因是箭頭函數沒有獨立的執行上下文this;所以箭頭函數內部出現this對象會直接訪問父級;所以也能看出箭頭函數是無法完全替代function的使用場景的;比如我們需要獨立的this或者argument的時候

1.2 defineProperty是什么

語法:

Object.defineProperty(obj, prop, descriptor)

參數:

obj:必要的目標對象

prop:必要的需要定義或者修改的屬性名

descriptor:必要的目標屬性全部擁有的屬性

返回值:

返回傳入的第一個函數;即第一個參數obj

該方法允許精確的添加或者修改對象的屬性;通過賦值來添加的普通屬性會創建在屬性枚舉期間顯示(fon...in;object.key);這些添加的值可以被改變也可以刪除;也可以給這個屬性設置一些特性;比如是否只讀不可寫;目前提供兩種形式:數據描述(set;get;value;writable;enumerable;confingurable)和存取器描述(set;get)

數據描述

當修改或者定義對象的某個屬性的時候;給這個屬性添加一些特性

var obj = { name:'xiangha'}// 對象已有的屬性添加特性描述Object.defineProperty(obj,'name',{ configurable:true | false, // 如果是false則不可以刪除 enumerable:true | false, // 如果為false則在枚舉時候會忽略 value:'任意類型的值,默認undefined' writable:true | false // 如果為false則不可采用數據運算符進行賦值});但是存在一個交叉;如果wrirable為true;而configurable為false的時候;所以需要枚舉處理enumerable為false--- 我是一個writable栗子 ---var obj = {};Object.defineProperty(obj,'val',{ value:'xiangha', writable:false, // false enumerable:true, configurable:true});obj.val = '書記'; // 這個時候是更改不了a的--- 我是一個configurable栗子 ---var obj = {};Object.defineProperty(obj,'val',{ value:'xiangha', writable:true, // true enumerable:true, configurable:false // false});obj.val = '書記'; // 這個時候是val發生了改變delete obj.val 會返回false;并且val沒有刪除--- 我是一個enumerable栗子 --- var obj = {};Object.defineProperty(obj,'val',{ value:'xiangha', writable:true, enumerable:false, // false configurable:true});for(var i in obj){ console.log(obj[i]) // 沒有具體值}綜上:對于我們有影響主要是configurable控制是否可以刪除;writable控制是否可以修改賦值;enumerable是否可以枚舉

所以說一旦使用Object.defineProperty()給對象添加屬性;那么如果不設置屬性的特性;則默認值都為false

var obj = {}; Object.defineProperty(obj,'name',{}); // 定義了心屬性name后;這個屬性的特性的值都為false;這就導致name這個是不能重寫不能枚舉不能再次設置特性的obj.name = '書記'; console.log(obj.name); // undefinedfor(var i in obj){ console.log(obj[i])}

總結特性:

  • value:設置屬性的值
  • writable ['raɪtəbl] :值是否可以重寫
  • enumerable [ɪ'nju:mərəbəl]:目標屬性是否可以被枚舉
  • configurable [kən'fɪgərəbl]:目標屬性是否可以被刪除是否可以再次修改特性

存取器描述

var obj = {};Object.defineProperty(obj,'name',{ get:function(){} | undefined, set:function(){} | undefined, configuracble:true | false, enumerable:true | false})注意:當前使用了setter和getter方法;不允許使用writable和value兩個屬性

gettet&& setter

當設置獲取對象的某個屬性的時候;可以提供getter和setter方法

var obj = {};var value = 'xiangha';Object.defineProperty(obj,'name',{ get:function(){  // 獲取值觸發  return value }, set:function(val){  // 設置值的時候觸發;設置的新值通過參數val拿到  value = val; }});console.log(obj.name); // xianghaobj.name = '書記';console,.log(obj.name); // 書記

get和set不是必須成對出現對;任寫一個就行;如果不設置set和get方法;則為undefined

哈哈;前戲終于鋪墊完成了

補充:如果使用vue開發項目;嘗試去打印data對象的時候;會發現data內的每一個屬性都有get和set屬性方法;這里說明一下vue和angular的雙向數據綁定不同

angular是用臟數據檢測;Model發生改變的時候;會檢測所有視圖是否綁定了相關的數據;再更新視圖

vue是使用的發布訂閱模式;點對點的綁定數據

2.實現

<div id="app"> <form>  <input type="text" v-model="number">  <button type="button" v-click="increment">增加</button> </form> <h3 v-bind="number"></h3> </div>

頁面很簡單;包含:

  1. 一個input,使用v-model指令
  2. 一個button,使用v-click指令
  3. 一個h3,使用v-bind指令。

我們最后也會類似vue對方式來實現雙向數據綁定

var app = new xhVue({  el:'#app',  data: {  number: 0  },  methods: {  increment: function() {   this.number ++;  },  } })

2.1 定義

首先我們需要定義一個xhVue的構造函數

function xhVue(options){ }

2.2 添加

為了初始化這個構造函數;給其添加一個_init屬性

function xhVue(options){ this._init(options);}xhVue.prototype._init = function(options){ this.$options = options; // options為使用時傳入的結構體;包括el,data,methods等 this.$el = document.querySelector(options.el); // el就是#app,this.$el是id為app的Element元素 this.$data = options.data; // this.$data = {number:0} this.$methods = options.methods; // increment}

2.3 改造升級

改造_init函數;并且實現_xhob函數;對data進行處理;重寫set和get函數

xhVue.prototype._xhob = function(obj){ // obj = {number:0} var value; for(key in obj){  if(obj.hasOwnProperty(ket)){   value = obj[key];   if(typeof value === 'object'){    this._xhob(value);   }   Object.defineProperty(this.$data,key,{    enumerable:true,    configurable:true,    get:function(){     return value;    },    set:function(newVal){     if(value !== newVal){      value = newVal;     }    }   })  } }}xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._xhob(this.$data);}

2.4 xhWatcher

指令類watcher;用來綁定更新函數;實現對DOM更新

function xhWatcher(name,el,vm,exp,attr){ this.name = name; // 指令名稱;對于文本節點;例如text this.el = el; // 指令對應DOM元素 this.vm = vm; // 指令所屬vue實例 this.exp = exp; // 指令對應的值;例如number this.attr = attr; // 綁定的屬性值;例如innerHTML this.update();}xhWatcher.prototype.update = function(){ this.el[this.attr] = this.vm.$data[this.exp]; // 例如h3的innerHTML = this.data.number;當numner改變則會觸發本update方法;保證對應的DOM實時更新}

2.5 完善_init和_xhob

繼續完善_init和_xhob函數

// 給init的時候增加一個對象來存儲model和view的映射關系;也就是我們前面定義的xhWatcher的實例;當model發生變化時;我們會觸發其中的指令另其更新;保證了view也同時更新xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods;  this._binding = {}; // _binding this._xhob(this.$data);}// 通過init出來的_bindingxhVue.prototype._xhob = function(obj){ // obj = {number:0} var value; for(key in obj){  if(obj.hasOwnProperty(ket)){   this._binding[key] = {    // _binding = {number:_directives:[]}    _directives = []   }   value = obj[key];   if(typeof value === 'object'){    this._xhob(value);   }   var binding = this._binding[key];   Object.defineProperty(this.$data,key,{    enumerable:true,    configurable:true,    get:function(){     return value;    },    set:function(newVal){     if(value !== newVal){      value = newVal;      // 當number改變時;觸發_binding[number]._directives中已綁定的xhWatcher更新      binding._directives.forEach(function(item){       item.update();       });     }    }   })  } }}

2.6 解析指令

怎么才能將view與model綁定;我們定義一個_xhcomplie函數來解析我們的指令(v-bind;v-model;v-clickde)并這這個過程中對view和model進行綁定

xhVue.prototype._xhcompile = function (root) { // root是id為app的element的元素;也就是根元素 var _this = this; var nodes = root.children; for (var i = 0,len = nodes.length; i < len; i++) {  var node = nodes[i];  if (node.children.length) {   // 所有元素進行處理   this._xhcompile(node)  };  // 如果有v-click屬性;我們監聽他的click事件;觸發increment事件,即number++  if (node.hasAttribute('v-click')) {   node.onclick = (function () {    var attrVal = nodes[i].getAttribute('v-click');    // bind讓data的作用域與methods函數的作用域保持一致    return _this.$method[attrVal].bind(_this.$data);   })();  };  // 如果有v-model屬性;并且元素是input或者textrea;我們監聽他的input事件  if (node.hasAttribute('v-model') && (node.tagName = 'INPUT' || node.tagName == 'TEXTAREA')) {   node.addEventListener('input', (function (key) {    var attrVal = node.getAttribute('v-model');    _this._binding[attrVal]._directives.push(new xhWatcher(     'input',      node,      _this,     attrVal,      'value'    ));    return function () {     // 讓number的值和node的value保持一致;就實現了雙向數據綁定     _this.$data[attrVal] = nodes[key].value    }   })(i));  };  // 如果有v-bind屬性;我們要讓node的值實時更新為data中number的值  if (node.hasAttribute('v-bind')) {   var attrVal = node.getAttribute('v-bind');   _this._binding[attrVal]._directives.push(new xhWatcher(    'text',     node,     _this,    attrVal,    'innerHTML'   ))  } }}

并且將解析函數也加到_init函數中

xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods;  this._binding = {}; // _binding this._xhob(this.$data); this._xhcompile(this.$el);}

最后

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title></head><body> <div id="app">  <form>   <input type="text" v-model="number">   <button type="button" v-click="increment">增加</button>  </form>  <h3 v-bind="number"></h3> </div></body><script> function xhVue(options) {  this._init(options); } xhVue.prototype._init = function (options) {  this.$options = options;  this.$el = document.querySelector(options.el);  this.$data = options.data;  this.$method = options.methods;  this._binding = {}; // _binding  this._xhob(this.$data);  this._xhcompile(this.$el); } xhVue.prototype._xhob = function (obj) {  var value;  for (key in obj) {   if (obj.hasOwnProperty(key)) {    this._binding[key] = {     _directives: []    }    value = obj[key];    if (typeof value === 'object') {     this._xhob(value);    }    var binding = this._binding[key];    Object.defineProperty(this.$data, key, {     enumerable: true,     configurable: true,     get: function () {      console.log(`get${value}`)      return value;     },     set: function (newVal) {      if (value !== newVal) {       value = newVal;       console.log(`set${newVal}`)       // 當number改變時;觸發_binding[number]._directives中已綁定的xhWatcher更新       binding._directives.forEach(function (item) {        item.update();       });      }     }    })   }  } } xhVue.prototype._xhcompile = function (root) {  // root是id為app的element的元素;也就是根元素  var _this = this;  var nodes = root.children;  for (var i = 0, len = nodes.length; i < len; i++) {   var node = nodes[i];   if (node.children.length) {    // 所有元素進行處理    this._xhcompile(node)   };   // 如果有v-click屬性;我們監聽他的click事件;觸發increment事件,即number++   if (node.hasAttribute('v-click')) {    node.onclick = (function () {     var attrVal = node.getAttribute('v-click');     console.log(attrVal);     // bind讓data的作用域與method函數的作用域保持一致     return _this.$method[attrVal].bind(_this.$data);    })();   };   // 如果有v-model屬性;并且元素是input或者textrea;我們監聽他的input事件   if (node.hasAttribute('v-model') && (node.tagName = 'INPUT' || node.tagName == 'TEXTAREA')) {    node.addEventListener('input', (function (key) {     var attrVal = node.getAttribute('v-model');     _this._binding[attrVal]._directives.push(new xhWatcher(      'input',      node,      _this,      attrVal,      'value'     ));     return function () {      // 讓number的值和node的value保持一致;就實現了雙向數據綁定      _this.$data[attrVal] = nodes[key].value     }    })(i));   };   // 如果有v-bind屬性;我們要讓node的值實時更新為data中number的值   if (node.hasAttribute('v-bind')) {    var attrVal = node.getAttribute('v-bind');    _this._binding[attrVal]._directives.push(new xhWatcher(     'text',     node,     _this,     attrVal,     'innerHTML'    ))   }  } } function xhWatcher(name, el, vm, exp, attr) {  this.name = name; // 指令名稱;對于文本節點;例如text  this.el = el; // 指令對應DOM元素  this.vm = vm; // 指令所屬vue實例  this.exp = exp; // 指令對應的值;例如number  this.attr = attr; // 綁定的屬性值;例如innerHTML  this.update(); } xhWatcher.prototype.update = function () {  this.el[this.attr] = this.vm.$data[this.exp];  // 例如h3的innerHTML = this.data.number;當numner改變則會觸發本update方法;保證對應的DOM實時更新 } var app = new xhVue({  el: '#app',  data: {   number: 0  },  methods: {   increment: function () {    this.number++;   }  } });</script></html>

所有的代碼;復制到編輯器就可查看效果了~~

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本国产高清不卡| 久久精品成人一区二区三区| 91亚洲精品一区| 欧美最猛黑人xxxx黑人猛叫黄| 午夜精品久久久久久久白皮肤| 日韩欧美在线免费观看| 国产女精品视频网站免费| 国产在线观看精品| 992tv成人免费影院| 精品福利一区二区| 久久久久久91香蕉国产| 综合国产在线观看| 欧美影院成年免费版| 亚洲国产欧美一区| 国产精品久久久| 青青草国产精品一区二区| 欧美电影电视剧在线观看| 亚洲天堂视频在线观看| 国产亚洲精品一区二区| 97视频色精品| 欧美黑人一区二区三区| 欧美精品www在线观看| 91亚洲精品久久久久久久久久久久| 欧美一级淫片videoshd| 国产欧美精品一区二区三区介绍| 国产精品久久久久久久久久ktv| 国产亚洲精品va在线观看| 久久夜色精品亚洲噜噜国产mv| 日韩一区二区三区在线播放| 亚洲精品98久久久久久中文字幕| 92福利视频午夜1000合集在线观看| 2018中文字幕一区二区三区| 国产91对白在线播放| 国产精品美女在线观看| 午夜精品久久久久久久白皮肤| 日韩欧美一区二区三区久久| 久久成人亚洲精品| 亚洲国产成人精品女人久久久| 亚洲va男人天堂| 国产专区精品视频| 欧洲中文字幕国产精品| 成人黄色av网| 国产精品久久久久久久电影| 久久九九国产精品怡红院| 91精品国产自产91精品| 久久网福利资源网站| 中文字幕精品在线视频| 日韩成人激情视频| 亚洲a级在线观看| 国内外成人免费激情在线视频| 久久精品久久久久久国产 免费| 亚洲欧美激情在线视频| 亚洲新声在线观看| 国产色综合天天综合网| 性欧美激情精品| 国产成人自拍视频在线观看| 国产精品人成电影在线观看| 国产成人在线播放| 久久久免费精品| 欧美亚洲另类制服自拍| 日韩一区二区三区xxxx| 2019中文字幕免费视频| 国产精品久久视频| 青青草成人在线| www.久久久久久.com| 亚洲电影在线看| 亚洲三级黄色在线观看| 成人免费xxxxx在线观看| 亚洲精品91美女久久久久久久| 911国产网站尤物在线观看| 欧美激情一区二区三区久久久| 欧美日韩一区免费| 性色av一区二区三区| 亚洲高清免费观看高清完整版| 亚洲深夜福利网站| 国产亚洲成精品久久| 亚洲片在线资源| 中文字幕欧美日韩va免费视频| 伊人成人开心激情综合网| 亚洲热线99精品视频| 久久久久久久久国产| 亚洲毛茸茸少妇高潮呻吟| 亚洲高清一区二| 久久久中精品2020中文| 欧美在线免费观看| 亚洲视频视频在线| 欧洲永久精品大片ww免费漫画| 日韩电影在线观看免费| 久久伊人精品天天| 在线亚洲午夜片av大片| 国产精品亚洲第一区| 91视频国产高清| 在线午夜精品自拍| 国产美女久久久| 久久久免费精品视频| 久久久中精品2020中文| 日韩电影中文字幕一区| 亚洲自拍中文字幕| 欧美日韩国产激情| 精品人伦一区二区三区蜜桃免费| 欧美成人精品一区二区三区| 国产精品久久久久久久app| 欧美性少妇18aaaa视频| 美日韩精品视频免费看| 在线观看免费高清视频97| 亚洲专区中文字幕| 亚洲欧洲免费视频| 国产主播喷水一区二区| 亚洲aⅴ日韩av电影在线观看| 国产精品久久久久7777婷婷| 亚洲v日韩v综合v精品v| 成人观看高清在线观看免费| 91精品视频在线| 亚洲精品久久久久久久久| 亚洲福利视频专区| 欧美wwwwww| 国产精彩精品视频| 欧美日韩精品在线| 亚洲视频在线观看免费| www国产亚洲精品久久网站| 1769国产精品| 精品视频一区在线视频| 亚洲国产欧美自拍| 欧美日韩一区二区精品| www.xxxx精品| 亚洲精品免费一区二区三区| 欧美在线视频网| 亚洲精品99久久久久| 97涩涩爰在线观看亚洲| 欧美成人精品不卡视频在线观看| 亚洲国产高潮在线观看| 亚洲国产精品资源| 国产成人精品国内自产拍免费看| 欧美另类老女人| 国产精品美腿一区在线看| 久久亚洲精品网站| 日韩精品日韩在线观看| 欧美午夜视频一区二区| 69av在线视频| 亚洲大胆人体在线| 亚洲欧洲日产国产网站| 成人黄色免费看| 欧美国产日本在线| 欧美在线视频在线播放完整版免费观看| 一本一本久久a久久精品综合小说| 欧美大奶子在线| 夜夜嗨av一区二区三区免费区| 91在线中文字幕| 日韩国产精品视频| 欧美成人精品激情在线观看| 日韩电影免费在线观看中文字幕| 欧美激情视频免费观看| 日韩成人中文电影| 91国偷自产一区二区三区的观看方式| 97视频免费看| 亚洲精品视频播放| 成人av色在线观看| 欧美日韩在线另类| 亚洲国产天堂网精品网站| 91中文在线视频| 91亚洲午夜在线| 欧美性理论片在线观看片免费| 午夜精品一区二区三区在线| 在线播放日韩专区|