VUE双向绑定实现

来源:互联网 发布:三亚旅游攻略 知乎 编辑:程序博客网 时间:2024/04/27 03:50
<!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>    <div id="app">        <input type="text" v-model="text" /> {{ text }}    </div>    <script>        function Vue(obj) {            this.id = obj.el,                this.data = obj.data            listenData(this.data, this)            var flag = nodeToFragment(document.getElementById(this.id), this)            document.getElementById(this.id).appendChild(flag)        }        function listenData(data, vue) {            Object.keys(data).forEach(function (key) {                var dep = new Dep()                Object.defineProperty(vue, key, {                    set(value) {                        if (!(vue.data[key] == value)) {                            vue.data[key] = value                            console.log(vue.data[key])                            dep.notify()                        }                    },                    get() {                        if (Dep.newSubScribers) dep.addSubScribers(Dep.newSubScribers)                        return vue.data[key]                    }                })            })        }        function Dep() {            this.subScribers = []        }        Dep.prototype = {            addSubScribers(sub) {                this.subScribers.push(sub)            },            notify() {                this.subScribers.forEach(function (sub) {                    sub.updata()                })            }        }        function nodeToFragment(node, vue) {            var flag = document.createDocumentFragment()            while (node.firstChild) {                compile(node.firstChild, vue)                flag.appendChild(node.firstChild)            }            return flag        }        function compile(node, vue) {            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                        node.addEventListener('input', function (e) {                            vue[name] = e.target.value                        })                        node.removeAttribute('v-model')                        new Watcher(node, name, vue)                    }                }            }            if (node.nodeType === 3) {                if (reg.test(node.nodeValue)) {                    var name = RegExp.$1                    name = name.trim()                    node.nodeValue = vue[name]                    new Watcher(node, name, vue)                }            }        }        function Watcher(node, name, vue) {            Dep.newSubScribers = this            this.node = node            this.name = name            this.vue = vue            this.value = vue[name]            Dep.newSubScribers = null        }        Watcher.prototype = {            updata() {                if (this.node.nodeType === 1) {                    this.node.value = this.vue[this.name]                }                if (this.node.nodeType === 3) {                    this.node.nodeValue = this.vue[this.name]                }            }        }        var vue = new Vue({            el: 'app',            data: {                text: 'hello world'            }        })    </script></body></html><!-- http://transcoder.baiducontent.com/from=1012852y/bd_page_type=1/ssid=0/uid=0/pu=usm%401%2Csz%40320_1004%2Cta%40iphone_2_6.0_11_9.1/baiduid=7FFB1B3B6229E8E723991DE796900A1B/w=0_10_/t=iphone/l=3/tc?ref=www_iphone&lid=13311096275631538808&order=1&fm=alop&h5ad=1&srd=1&dict=32&tj=www_normal_1_0_10_title&vit=osres&m=8&cltj=cloud_title&asres=1&nt=wnor&title=Vue.js%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86-kidney-%E5%8D%9A%E5%AE%A2%E5%9B%AD&w_qd=IlPT2AEptyoA_yijCULhngvYOjMmtXdTo6lb&sec=23604&di=004609dd99d90bdd&bdenc=1&tch=124.0.67.295.0.0&nsrc=IlPT2AEptyoA_yixCFOxXnANedT62v3IEQGG_ytK1DK6mlrte4viZQRAWTbrLnq4ZpPPtCPQpxcFxXKi0GEskNYWgLdnpS-bll_aurmqs1CLHaB_s255J2DUVzMr64rFiO2ewAoy0Adf&eqid=b8ba8389980b00001000000659a6a966&wd=&clk_info=%7B%22srcid%22%3A%221599%22%2C%22tplname%22%3A%22www_normal%22%2C%22t%22%3A1504094568858%2C%22sig%22%3A%222004%22%2C%22xpath%22%3A%22div-div-div-a-div-img%22%7D //Object.keys() 方法会返回一个由给定对象的所有可枚举自身属性的属性名组成的数组,//数组中属性名的排列顺序和使用for-in循环遍历该对象时返回的顺序一致//(两者的主要区别是 for-in 还会遍历出一个对象从其原型链上继承到的可枚举属性)。var flag = document.createDocumentFragment()// DocumentFragment(文档片段)可以看作节点容器,它可以包含多个子节点// 当我们将它插入到 DOM 中时,只有它的子节点会插入目标节点,所以把它看作一组节点的容器。flag.appendChild(child) //child在dom树消失 变为DocumentFragment内部节点document.getElementById(id).appendChild(flag) //把DocumentFragment加进dom树,此时DocumentFragment容器为空,即内部节点移动到dom树,此为DocumentFragment特性-->

思路是别人的,代码是自己打的,大家可以去看原文,原文有详细解释

原创粉丝点击