从零单排系列之写一个类vue框架(二)

栏目: 编程语言 · 发布时间: 4年前

内容简介:昨天写了一下节点绑定model的替换,已经如何检测model 的方法今天优化一下,勉强实现一个双向绑定看下昨天的代码

昨天写了一下节点绑定model的替换,已经如何检测model 的方法

今天优化一下,勉强实现一个双向绑定

看下昨天的代码

<script>
    function Vue(obj) {
        var app = document.querySelector(obj.el);
        for(let i in obj.data) {
            this[i] = obj.data[i];
        }
 
        var html = app.childNodes;
        var that = this;
        html.forEach(function(data) {
            if(data.nodeName == '#text') {
                data.data = data.data.replace(/\{\{([\s\S]+)\}\}/g, function(a, b){return that[b]})
            }
        })
    }
</script>
<div id='app'>
    这里是{{title}}
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            title: 'Hello World'
        }
    })
</script>

在实现双向绑定之前,先普及一个set 和 get 的知识。我说点大白话,反正也不是专业的。

一个对象的key在被赋值 value 的时候,被拦截,触发set方法,set的参数就是那个 value

但是这个赋值就会被拦截了,所以需要给一个新的key一个值。然后把value赋值到新的值上面去。 如果强行给之前的key赋值,就会发生无限set 的情况。

稍微加工了一下

<script>
    function Vue(obj) {
        this.app = document.querySelector(obj.el); // 获取函数作用域
        this.data = obj.data; //获取data值
        this.getData(this.data); //设置钩子函数
        this.getWatcher(this.app.childNodes); // 获得包含Model的节点
    }

    Vue.prototype.getData = function(data) {
        for(var i in data) { // 遍历 data 里面的数据
            Object.defineProperty(this, i, { // 在this里面 设置同名key,比如,data里面有title, 那么就去设置一个this.title
                set: function(e) {
                    this.data[i] = e; // 当this.title 被设置 value 的时候,将 this.data.title = value 
                    this.digest(i);  // 更新包含这个model 的 dom
                }.bind(this),
                get: function() {
                    return this.data[i]; // 想获取this.title 的话,就去调取 this.data.title 返回
                }
            })
        }
    }

    Vue.prototype.getWatcher = function(inner) { // 这个代码昨天写过,就是去检测节点中包不包含model
        this.watcher = {};
        var that = this;
         inner.forEach(function(data) {
            if(data.nodeName == '#text') { 
                data.data = data.data.replace(/\{\{([\s\S]+)\}\}/g, function(a, b){
                data.realData = data.data; //自定义一个属性realData,把原始内容保存一下,方便复用 dom.realData = 这里是{{title}}
                 if(!that.watcher[b])
                     that.watcher[b] = [];
                 that.watcher[b].push(data); //把这个节点添加到被监听对象中去 {title:[dom]}
                 return that[b]; // 先把{{title}}替换成 helloworld
             })
            }
        })
    }


    Vue.prototype.digest = function(e) {
        var that = this;
        this.watcher[e].forEach(function(node) {
            node.data = node.realData.replace(/\{\{([\s\S]+)\}\}/g, function(a, b) {return that[b]}); // 把title那个节点改成新的数值
        })
    }
</script>
<div id='app'>
    这里是{{title}}
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            title: 'Hello World'
        }
    })
    setTimeout(function(){app.title = 5;}, 1000)
    setTimeout(function(){app.title = 10;}, 2000)
</script>

代码有些粗劣,但是功能是实现了。

1.首先 先读取 new Vue传入对象时候,data 里面的数据, 然后对其进行遍历,给 实例化对象添加 同名属性, 这个同名属性主要就是用来被监听set,get(双向绑定实现的基本原理)。 也就是 vue.prototype.getData

2.然后呢,去递归dom树(这个以后再写,先简单就一层,不然写的内容会增多很多),然后用正则过滤出里面 {{}}类型的节点,将 这个节点的原始内容(比如{{title}}保存到这个节点的一个自定义属性里,我写的是realData),并将这个节点添加到watcher里面去。 也就是vue.prototype.watcher

3.然后呢,在同名属性被设置的时候呢,就触发钩子函数,将这个同名属性所涉及到的节点的data给更新。 也就是vue.prototype.digest

如果上面的内容没有看的太明白的话,可以参考一下代码注释。。。我下线看看怎么优化代码或者优化思路,晚上或者明天更新。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

风吹江南之互联网金融

风吹江南之互联网金融

陈宇(江南愤青) / 东方出版社 / 2014-6-1 / 55元

随着中国互联网金融浪潮高涨,P2P、众筹、余额宝、微信支付等新生事物层出不穷,加之大数据等时髦概念助阵,简直是乱花渐欲迷人眼,令媒体兴奋,公众狂热。那么,互联网金融真的能“颠覆”传统金融吗?当互联网思维对撞传统金融观念,是互联网金融的一统天下,还是传统金融业的自我革新?究竟是谁动了金融业的奶酪? 本书作者早期试水创立具有互联网金融雏形的网站,后来成为互联网金融的资深投资人,基于其多年在该领域......一起来看看 《风吹江南之互联网金融》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具