<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Vue實現雙向綁定的原理以及響應式數據的方法

        來源:懂視網 責編:小采 時間:2020-11-27 22:12:11
        文檔

        Vue實現雙向綁定的原理以及響應式數據的方法

        Vue實現雙向綁定的原理以及響應式數據的方法:一、vue中的響應式屬性 Vue中的數據實現響應式綁定 1、對象實現響應式: 是在初始化的時候利用definePrototype的定義set和get過濾器,在進行組件模板編譯時實現water的監聽搜集依賴項,當數據發生變化時在set中通過調用dep.notify進行發布通知,實
        推薦度:
        導讀Vue實現雙向綁定的原理以及響應式數據的方法:一、vue中的響應式屬性 Vue中的數據實現響應式綁定 1、對象實現響應式: 是在初始化的時候利用definePrototype的定義set和get過濾器,在進行組件模板編譯時實現water的監聽搜集依賴項,當數據發生變化時在set中通過調用dep.notify進行發布通知,實

        一、vue中的響應式屬性

        Vue中的數據實現響應式綁定

        1、對象實現響應式:

        是在初始化的時候利用definePrototype的定義set和get過濾器,在進行組件模板編譯時實現water的監聽搜集依賴項,當數據發生變化時在set中通過調用dep.notify進行發布通知,實現視圖的更新。

        2、數組實現響應式:

        對于數組則是通過繼承重寫數組的方法splice、pop、push、shift、unshift、sort、reverse、等可以修改原數組的方式實現響應式的,但是通過length以及直接利用item[index]方式修改數組是不能實現響應式的改變dom(這種兩種方式涉及到數組的內部實現)。在數據更新后為了避免過于頻繁的進行dom的操作,在vue中會將更新的dom進行批量操作,而不是直接有數據更新就刷新dom,vue將需要更新的dom壓入異步隊列記性批量操作,提高性能。

        下面具體的實現,實現原理大致如下:

            

        對象中實現雙向數據綁定,可以直接在瀏覽器查看效果:

        <!DOCTYPE html>
        <html lang="en">
        <head>
         <meta charset="UTF-8">
         <title>Two-way data-binding</title>
        </head>
        <body>
         
         <div id="app">
         <input type="text" v-model="text">
         {{ text }}
         </div>
        
         <script>
         function observe (obj, vm) {
         Object.keys(obj).forEach(function (key) {
         defineReactive(vm, key, obj[key]);
         });
         }
        
         function defineReactive (obj, key, val) {
        
         var dep = new Dep();
        
         Object.defineProperty(obj, key, {
         get: function () {
         // 添加訂閱者watcher到主題對象Dep
         if (Dep.target) dep.addSub(Dep.target);
         return val
         },
         set: function (newVal) {
         if (newVal === val) return
         val = newVal;
         // 作為發布者發出通知
         dep.notify();
         }
         });
         }
        
         function nodeToFragment (node, vm) {
         var flag = document.createDocumentFragment();
         var child;
         
         while (child = node.firstChild) {
         compile(child, vm);
         flag.appendChild(child); // 將子節點劫持到文檔片段中
         }
        
         return flag;
         }
        
         function compile (node, vm) {
         var reg = /\{\{(.*)\}\}/;
         // 節點類型為元素
         if (node.nodeType === 1) {
         var attr = node.attributes;
         // 解析屬性
         for (var i = 0; i < attr.length; i++) {
         if (attr[i].nodeName == 'v-model') {
         var name = attr[i].nodeValue; // 獲取v-model綁定的屬性名
         node.addEventListener('input', function (e) {
         // 給相應的data屬性賦值,進而觸發該屬性的set方法
         vm[name] = e.target.value;
         });
         node.value = vm[name]; // 將data的值賦給該node
         node.removeAttribute('v-model');
         }
         };
        
         new Watcher(vm, node, name, 'input');
         }
         // 節點類型為text
         if (node.nodeType === 3) {
         if (reg.test(node.nodeValue)) {
         var name = RegExp.$1; // 獲取匹配到的字符串
         name = name.trim();
        
         new Watcher(vm, node, name, 'text');
         }
         }
         }
        
         function Watcher (vm, node, name, nodeType) {
         Dep.target = this;
         this.name = name;
         this.node = node;
         this.vm = vm;
         this.nodeType = nodeType;
         this.update();
         Dep.target = null;
         }
        
         Watcher.prototype = {
         update: function () {
         this.get();
         if (this.nodeType == 'text') {
         this.node.nodeValue = this.value;
         }
         if (this.nodeType == 'input') {
         this.node.value = this.value;
         }
         },
         // 獲取data中的屬性值
         get: function () {
         this.value = this.vm[this.name]; // 觸發相應屬性的get
         }
         }
        
         function Dep () {
         this.subs = []
         }
        
         Dep.prototype = {
         addSub: function(sub) {
         this.subs.push(sub);
         },
        
         notify: function() {
         this.subs.forEach(function(sub) {
         sub.update();
         });
         }
         };
        
         function Vue (options) {
         this.data = options.data;
         var data = this.data;
        
         observe(data, this);
        
         var id = options.el;
         var dom = nodeToFragment(document.getElementById(id), this);
        
         // 編譯完成后,將dom返回到app中
         document.getElementById(id).appendChild(dom); 
         }
        
         var vm = new Vue({
         el: 'app',
         data: {
         text: 'hello world'
         }
         });
        
         </script>
        
        </body>
        </html>
        
        

        在vue的data中定義的屬性才具有響應式的效果,通過vue.name或者this.name形式定義的全局變量雖然可以在template中使用,但是其不是響應式的。同時在data中定義的對象obj,如果后面給對象定義新的屬性也不是響應式的,除非通過vue提供的方法set設置,具體如下:

        new vue({
        
         data(){
        
         return {
        
         obj:{}
        
         }
        
         },
        
         methods:{
        
         this.obj.name="hs"http://非響應屬性
        
         this.$set(this.obj,'name','hs')//name屬性將會是響應式的
        
         }
        
        }) 
        
        

        如果data中定義的有數組元素同時在computed中也要注意具體如下面介紹。

        二、computed定義的計算屬性

        1、在vue中$option.data中定義的數據是都是響應式的,在初始化生命周期的時候就已經實現了數據雙向綁定,通常在view中只是用一個表達式語句,當綁定時的邏輯比較復雜是可以通過計算屬性的方式實現。但是在computed中定義的屬性只具有get方法,所以當在程序中改變屬性的時候并不能實現視圖的動態響應。可以通過顯示的定義set的方式實現視圖的刷新。

        <div v-on:click="con">{{model1}}</div> 
        

        JS代碼

        const app = new Vue({
        
         data:function () {
         return {
         model:'hello',
         name:'world',
        
         }
         },
         computed:{
         model1:
         {
         get: function(){
         return this.model;
         },set:function (val) {
         return this.model=val;
         }
         }
        
         },
         methods:{
         con:function () {
        
         this.model1="hello world"http://動態修改model1屬性時,視圖也會跟著跟新
        
         console.log(this.model1);
         }
         },
         /* watch:{
         'model1':function (val) {
         console.log(val)
         }
         }*/
         }).$mount('#app')
        
        

        2、如果在computed中定義的屬性依賴于data中定義的屬性,當data中的屬性動態變化時,視圖中綁定的computed的值也會跟著變化

        const app = new Vue({
         /* router:router,*/
         data:function () {
         return {
         model:'hello',
         name:'world',
        
         }
         },
         computed:{
         model1:
         {
         get: function(){
         return a;
         },set:function (val) {
         a=val;
         }
         }
        
         },
         methods:{
         con:function () {
        
         this.model1="hello world"
        
         console.log(this.model1);
         }
         },
         /* watch:{
         'model1':function (val) {
         console.log(val)
         }
         }*/
         }).$mount('#app')

        通過以上兩種方式實現的computed的動態雙向綁定實質是通過中間的層data的屬性,computed中依賴的屬性如果不是data中的屬性則也不能實現動態的綁定 ,即當上面的get,set中的this.model換成一個全局的屬性時,也不能實現動態的更新。所以實質上在vue中最為原始的響應式數據實際是在data中定義的,如果computed中定義的屬性依賴于data中的屬性時,其實質是其依賴data中的屬性在訪問時觸發data中的getter方法,從而會注冊監聽器,所以當依賴屬性變化時,computed中的屬性也會跟著變化。但是在computed中定義的不具有依賴項的屬性是直接掛在在vue實例上的屬性其是不具有響應式的特點的。

        3、watch監聽data中屬性的變化,可以實現和computed的同樣的效果,當時當監聽的屬性依賴多個屬性時,利用computed更為方便,如下:

        (1)使用watch監聽

        <div id="demo">{{fullName}}</div>
         
        var vm = new Vue({
         el: '#demo',
         data: {
         firstName: 'Foo',
         lastName: 'Bar',
         fullName: 'Foo Bar'
         }
        })
         
        vm.$watch('firstName', function (val) {
         this.fullName = val + ' ' + this.lastName
        })
         
        vm.$watch('lastName', function (val) {
         this.fullName = this.firstName + ' ' + val
        }
        
        

        (2)利用computed監聽,更為簡潔,同時computed會將結果進行緩存,當結果沒有發生變化時,不會觸發相應回調

        var vm = new Vue({
         data: {
         firstName: 'Foo',
         lastName: 'Bar'
         },
         computed: {
         fullName: function () {
         return this.firstName + ' ' + this.lastName
         }
         }
        })
        
        

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Vue實現雙向綁定的原理以及響應式數據的方法

        Vue實現雙向綁定的原理以及響應式數據的方法:一、vue中的響應式屬性 Vue中的數據實現響應式綁定 1、對象實現響應式: 是在初始化的時候利用definePrototype的定義set和get過濾器,在進行組件模板編譯時實現water的監聽搜集依賴項,當數據發生變化時在set中通過調用dep.notify進行發布通知,實
        推薦度:
        標簽: 數據 VUE 實現
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 两个人的视频www免费| 美女啪啪网站又黄又免费| 人体大胆做受免费视频| 国产男女猛烈无遮档免费视频网站| 亚洲手机中文字幕| 日本免费xxxx| 亚洲成人免费网站| 大地资源二在线观看免费高清| 精品亚洲AV无码一区二区| 久久精品女人天堂AV免费观看| 亚洲成年网站在线观看| 天天摸天天操免费播放小视频| 亚洲欧美第一成人网站7777| 国产精品美女自在线观看免费| 国产精品亚洲色婷婷99久久精品| 一本色道久久88亚洲综合 | 国产va免费精品| 国产精品亚洲аv无码播放| 99在线在线视频免费视频观看| 亚洲成人免费网址| 日韩在线免费看网站| 一级全免费视频播放| 亚洲va无码va在线va天堂| 3344永久在线观看视频免费首页| 亚洲va在线va天堂成人| 免费乱码中文字幕网站| 国产性生大片免费观看性| 亚洲视频在线观看网址| 啦啦啦www免费视频| jizz在线免费观看| 亚洲欧洲校园自拍都市| 免费看国产一级片| 久草免费福利视频| 亚洲熟妇无码AV不卡在线播放| 日产国产精品亚洲系列| 久9热免费精品视频在线观看| 男人天堂2018亚洲男人天堂| 亚洲精品无码久久毛片| 人与禽交免费网站视频| 日本免费精品一区二区三区| 91亚洲一区二区在线观看不卡|