简单实现Vue中的插值替换(二)

81 篇文章 7 订阅

简单实现Vue中的插值替换(二)

传送门简单实现Vue中的插值替换(一)

在上一篇博客中,我们简简单单的梳理了一下,如何把一个插值表达式替换成对象里面真正的数据,但是呢,美中不足的地方也有很多,这次呢,我们从两个方面入手,简简单单的完善之前的代码。

方面一:仿造Vue的数据源

方面二:代码结构上仿造Vue


简单的聊一下方面一:

首先我们知道,我们在Vue中写数据源一般是这么写的:

    let app = new Vue({
        el: '#root',
        data: {
            name: 'Jim',
            message: 'Hello!'
        }
    });

稍微一分析,我们的脑海里出现第一个念头,这个Vue肯定是一个类,因为使用了关键字new,所以代码应该是这样的:

class Vue {
    constructor(option){
        // 这里的 option 就包含了传进来的 el 和 data
        console.log(option);
    }
}

但是呢,嘿嘿,我们也可以不是 ,我们还可以写成一个函数,嘻嘻,比如这样:

function Vue(options) {
    // 这里的 option 就包含了传进来的 el 和 data
    console.log(option);
}

接下来,我就以这第二种方法函数的为例来进行接下来的阐述。


简单的聊一下方面二:

了解Vue的都知道,Vue进行插值表达式替换的,我们简略的概括成三个步骤:

  1. 拿到或者创建DOM——render
  2. 编译DOM——complier
  3. 更新DOM——update

当然,我们在这里并不细扣,可能有些函数里面并不会干什么活,也不讨论什么虚拟DOM什么的【虚拟dom我下一篇博客会讲】

这里只是简单的模仿一下,由此,我们脑海里,就有了一个大概的关于简单实现Vue插值替换的代码结构:

// 数据源
let app = new Vue({
    el: '#root',
    data:{
        name: 'Jim',
        message: 'Hello!'
    }
});

function Vue(option){
    // 这里存储获取到的 el 和 data
    
    // 然后调用一下render函数拿到dom,当然也可以在这个Vue函数里拿,都可以
    this.render(); // 这里我们可以通过this调用,是因为我会把render函数、complier函数、update函数、挂载到Vue的原型上。
}

Vue.prototype.render = function(){} // dom

Vue.prototype.complier = function(){} // 编译

Vue.prototype.update = function(){} // 更新

所以剩下来的就是填充一下代码了。


完整代码展示:【注意看注释】

// 定义HTML模板
<body>
    <div id="root">
        <p>{{name}}{{message}}</p>
    </div>
</body>

<script>
    // 定义一个Vue构造函数
    function Vue(options) {
        // 获取new时传进来的数据,【Vue源码中一般带 _ 下划线的都是私有的】
        this._data = options.data;
        this._el = options.el;

        // 通过el获取到dom模板
        this._templateDom = document.querySelector(this._el);
        this._parent = this._templateDom.parentNode;// 同时也存储一下父节点,方便后续的替换

        // 调用渲染函数
        this.render();
    }

    Vue.prototype.render = function () {
        this.complier(); // 调用一下编译函数
    }

    // 编译,将模板与数据结合,得到真正的dom元素
    Vue.prototype.complier = function(){
        let realHTMLDom = this._templateDom.cloneNode(true); // 拷贝DOM
        // 替换dom中的插值表达式
        complier(realHTMLDom, this._data);
        // 将编译后的dom传给更新函数
        this.update(realHTMLDom);

    }

    // 将我们在 上一篇博客中的 代码搞过来,可以直接用。【不会的可以通过上面的传送门去看一下】
    let regx = /\{\{(.+?)\}\}/g; // 正则表达式匹配双花括号
    // 定义编译函数,用来处理dom元素
    function complier(template, data) {
        // 获取子节点
        let childNodes = template.childNodes;
        // 遍历子节点
        for (let i = 0; i < childNodes.length; i++) {
            // 根据子节点类型,来确定此节点是文本节点,还是元素节点[3代表文本节点,1代表元素节点]
            let type = childNodes[i].nodeType;
            if (type === 3) {
                // 获取文本节点的值
                let txt = childNodes[i].nodeValue;
                // 利用replace,结合正则表达式,来对插值进行替换
                txt = txt.replace(regx, function (_, g) {
                    let key = g.trim();
                    let value = data[key];
                    return value;
                });
                childNodes[i].nodeValue = txt;
            } else if (type === 1) {
                // 如果是元素节点 递归调用
                complier(childNodes[i], data);
            }
        }
    }

    // 将dom渲染到页面中【就是替换一下dom】
    Vue.prototype.update = function(real){
        this._parent.replaceChild(real, document.querySelector(this._el));
    }

    // 数据源
    let app = new Vue({
        el: '#root',
        data: {
            name: 'Jim',
            message: 'Hello!'
        }
    })
</script>

这样是不是看起来就有了那么一点点Vue的意思了呢,嘻嘻。

下一篇,我们解决一个插值问题,多级对象的访问。

传送门:简单实现Vue中的插值替换(三)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值