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特性
-->

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

相关文章推荐

CSS脱离文档流

脱离文档流 也就是将元素从普通的布局排版中拿走,其他盒子在定位的时候,会当做脱离文档流的元素不存在而进行定位。需要注意的是,使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然...

Git基本操作

本人到公司所接触的git操作(都是一些基础的小白操作)

JavaScript实现简单的双向数据绑定(Ember、Angular、Vue)

什么是双向数据绑定呢? 简单的说 就是UI视图与数据绑定在了一块 也就是数据和视图是同步改变的 双向数据绑定最常见的应用场景就是表单 (应用场景还是很有限的)现在我们要实现这样一个简单的数据...

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

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

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

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

vue实现双向绑定的原理Object.defineProperty

vue.js利用Object.defineProperty实现双向绑定 Object.defineProperty这个方法了不起啊,vue.js是通过它实现双向绑定的。。而且Object.o...

Vue:实现双向数据绑定

参考剖析Vue原理&实现双向绑定MVVM javascript实现数据双向绑定的三种方式Vue实现双向数据绑定的方式Vue是如何实现双向数据绑定的呢?答案是前端数据劫持。其通过Object.defi...

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

vue双向绑定原理的简单实现:数据劫持+订阅发布模式

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

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

vue源码解析之--数据双向绑定

在短时间内迅速使用vue构建了两个demo,一个eleme外卖平台webapp,还有一个是新闻网站。除了练习项目,也阅读了很多文章,收获颇多,成长很快。总结一下: vue简单,轻量,易上手,API...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VUE双向绑定实现
举报原因:
原因补充:

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