VUE双向绑定实现

翻译 2017年09月12日 15:03:22
<!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特性
-->

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

Vue 双向绑定的原理及实现Demo

Vue双向绑定的原理Vue用了一段时间了,一直没有纠结过它的原理,今天看了一篇很不错的文章:Vue.js双向绑定的实现原理,跟着敲了一遍,发现其中有意思的地方还是很多的,一些知识我之前都没有接触过,这...
  • Creabine
  • Creabine
  • 2017年03月01日 23:41
  • 2958

关于vue双向绑定的简单实现

vue双向绑定原理的简单实现:数据劫持+订阅发布模式
  • yolo0927
  • yolo0927
  • 2016年12月21日 18:27
  • 1134

Vue2.x父组件与子组件之间的双向绑定

最近在研究如何写一套基于Vue2.x的UI组件给自己用,提升一点BIG,在制作含有input的组件遇到一个问题:不知怎样才能把子组件中input与调用者(父组件)的数据实现双向绑定,想过使用Vuex,...
  • Mocha_Wang
  • Mocha_Wang
  • 2017年07月28日 10:39
  • 1509

【VUE】.NET实现Tree组件双向绑定数据(2)

写在前面的   在之前的文章中我们已经做好了前期的准备工作,接下来我们需要做的有两步,第一步是将用户组资源表中的数据读取出来,按照资源页面的级别,拼装树,这个过程我们只涉及到查询;第二步就是根据页面上...
  • SugaryoTT
  • SugaryoTT
  • 2017年12月19日 10:28
  • 163

【VUE】.NET实现Tree组件双向绑定数据(3)-资源分配

写在前面的 功能描述 代码 前端 后台 总结写在前面的   经过之前树的拼装,基本上已经可以了解到Iview.js中树组件的格式显示,接下来就是有关于树组件中,expand、checked属性,在实际...
  • SugaryoTT
  • SugaryoTT
  • 2018年01月04日 16:34
  • 207

剖析Vue原理&实现双向绑定MVVM

https://segmentfault.com/a/1190000006599500 文能帮你做什么? 1、了解vue的双向数据绑定原理以及核心代码模块 2、缓解好奇心的同时了...
  • zzy7075
  • zzy7075
  • 2017年03月31日 11:55
  • 521

Vue:实现双向数据绑定

参考剖析Vue原理&实现双向绑定MVVM javascript实现数据双向绑定的三种方式Vue实现双向数据绑定的方式Vue是如何实现双向数据绑定的呢?答案是前端数据劫持。其通过Object.defi...
  • qq_31628337
  • qq_31628337
  • 2017年05月03日 11:19
  • 921

剖析Vue原理&实现双向绑定MVVM

原文地址:https://segmentfault.com/a/1190000006599500 本文能帮你做什么? 1、了解vue的双向数据绑定原理以及核心代码模块 2、缓解好奇心的同...
  • tanga842428
  • tanga842428
  • 2017年02月08日 10:53
  • 3027

Vue.js实现双向数据绑定(表单自动赋值、表单自动取值)

使用Vue.js实现双向表单数据绑定,实现此功能后,前端只需要提供一个JSONObject对象,便可以实现自动填充表单;指定对应的属性名称后,便能够实现自动封装表单种的...
  • lovelongjun
  • lovelongjun
  • 2017年06月17日 11:53
  • 3878

【VUE】.NET实现Tree组件双向绑定数据(1)

写在前面的    由于这个Tree 组件在使用render函数的情况下会变得相对简单一些,但是在后台处理数据的时候依然会碰到相当大的麻烦,索性,我们在后台把树结构拼好,一次性返回给前端页面,这样来的...
  • SugaryoTT
  • SugaryoTT
  • 2017年12月18日 11:52
  • 113
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VUE双向绑定实现
举报原因:
原因补充:

(最多只允许输入30个字)