创新路
我们一直在努力

vue-入门学习2

文档学习走了一边了,对于基础理解还是不够,虽然在 segmentfault 上了能回答一些简单的问题,对于稍微深入或者讲解清楚时还是需要参考文档或者不知所措,特继续二阶段学习一下。

深入响应式原理

vue实例时传入一个js对象,遍历对象的时候,通过 Object.defineProperty 来把数据描述符转换为存储描述符(get/set)。这个是ES5的特性,也就是为什么vue不支持IE8的原因。

响应的结构图大致又是如何的呢?结合着官方的图示,自己理解一下。

    请输入您的姓名:<input type="text" name="name" oninput="setVal(this)" /> <br />
    你好:<span id="name"></span>
    <script>
        var userinfo = {name: 'unofficial', age: 18},
            nameSpanEle = document.getElementById('name'),
            nameInputEle = document.getElementsByTagName('input')[0];

        function def(key, value) {
            Object.defineProperty(userinfo, key, {
                get: function() {
                    return value;
                },
                set: function(val) {
                    if(key === 'name') {
                        initVal(val);
                        getVal(val);
                    }
                    value = val;
                }
            })
        }

        for(var key in userinfo) {
            def(key, userinfo[key]);
        }

        function initVal(val) {
            nameInputEle.value = val;
        }

        function setVal(e) {
            userinfo.name = e.value;
        }

        function getVal(val) {
            nameSpanEle.innerText = val;
        }
    </script>

如何实现追踪数据的变化,在value变化的时候更新页面的数据。跟着文档看了一下MDN上的 Object.observe ,但是都不支持这个,vuejs实现了一个Observe,没有细看源码(主要是看不懂),也就假装在set的时候如果key是name就更新一下数据,这里其实也是有问题的。应该就是官方的图示中的如果Observe到数据变化了,就通知watcher,页面的数据不是***新的啦,你现在去重新编译一下模板。
如果只是单纯的通过输入来更新,直接通过input时获取值显示值就好。

    <script>
        var userinfo = {name: 'unofficial'},
            nameSpanEle = document.getElementById('name'),
            nameInputEle = document.getElementsByTagName('input')[0];

        function setVal(e) {
            userinfo.name = e.value;
            getVal(e.value);
        }

        function getVal(val) {
            nameSpanEle.innerText = val;
        }
    </script>

这里还有一点差别,对于vue是以数据变化后去重新编译一下模板,这个不需要去操作DOM,而上述例子,还是需要通过选择器选择需要数据变化的DOM,然后再赋值操作。

变化的数据

实例化外部可以通过Vue.set(Object, key, value)或者是vm.$set(Object, key, value)来更新数据,内部可以使用this.$set(Object, key, value)。

    <div id="app" v-cloak>
        <input type="text" v-model="profile.name">
        <p>{{profile.name}}</p>
        <p>{{profile.age}}</p>
    </div>
    <script src="//cdn.bootcss.com/vue/2.1.4/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                profile: {
                    name: 'unofficial'
                }

            }
        })
        // Vue.set(vm.profile, 'age', 18);
        vm.$set(vm.profile, 'age', 15);
    </script>

上述例子中学习两点:
– 如果Object是profile,即 vm.$data.profile,因为Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.profile 等价于访问 vm.$data.profile。
– vm.$set 是全局 Vue.set 的别名

异步更新队列

对于数据不是立即更新这点的理解,观察到数据变化后,Vue会创建一个队列,将同一事件循环内的数据变化都缓存起来。如果一个watcher被多次触发,只会推入一次到队列中,然后,在接下来的事件循环中,Vue 刷新队列并仅执行必要的 DOM 更新。

    <div id="app" v-cloak>
        <input type="text" v-model="profile.name">
        <p>{{profile.name}}</p>
        <p>{{profile.age}}</p>
    </div>
    <script src="//cdn.bootcss.com/vue/2.1.4/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                profile: {
                    name: 'unofficial'
                }

            }
        })
        // Vue.set(vm.profile, 'age', 18);
        vm.$set(vm.profile, 'age', 15);
        console.info('%O', vm.$el); // 如果不使用debugger,输出的文档对象可以看出textContent是unofficial 15;使用debugger调试会中止程序,可以看到textContent是unofficial
        console.log(vm.$el.textContent, 1); // unofficial
        //debugger;
        vm.profile.name = '张三';
        vm.$nextTick(function() {
            console.log(vm.$el.textContent, 3);
        })
        //console.log(vm.$el);
        //debugger;
        console.log(vm.$el.textContent, 2);
        //debugger;
    </script>

总结

知识按照文档大致理解了一下,其中还是有一些疑问  

  • 为什么不直接使用赋值语句    // 有差别吗?
       vm.profile.name = '张三';
       vm.$set(vm.profile, 'name', '张三');

  • console.log对于执行结果的输出是***后结果  vm.$set(vm.profile, 'name', 'abc');
     console.log(vm.$el, vm.$el.textContent);

     解答:对于这个问题,我在 segmentfault 找到了 答案。参照提示 value below was evaluated just now

未经允许不得转载:天府数据港官方信息博客 » vue-入门学习2

客官点个赞呗! (0)
分享到:

评论 抢沙发

评论前必须登录!

天府云博 - 做有态度的开发&运维&设计学习分享平台!

联系我们百度云主机