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

81 篇文章 7 订阅

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

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

这(三)的内容,大家可以当做对(二)的补充,主要就是为了解决,多级对象的访问问题。

OK,咱们正式开始。


首先我们还是来简简单单的说一下这个问题。

咱们定义一个对象,对象的层级是不确定的,就比如:

data = {
    a: {
        b: {
            c: {
                d: '这是要获取的值'
            }
        }
    }
}

既然如此,那如何拿到这些值呢?

在 (二)中我只是简简单单定义了一个一级对象,但是如果你定义的是一个多级对象,比如上面的对象,那你在插值中肯定会写{{a.b.c.d}},你会发现这个插值替换就不行了,因为在进行到这一步时:

// 利用replace,结合正则表达式,来对插值进行替换
txt = txt.replace(regx, function (m, g) {
    let key = g.trim();
    let value = data[key];
    return value;
});

data[key]key值拿到的就是 a.b.c.d ,那很明显,data[a.b.c.d]就是undefined

所以,我们还要继续改进一下。

首先,我们能发现一点,对于一个多级对象,我们在插值表达式中写的 {{a.b.c.d}},其实也就告诉了程序我们的访问路径。

那么,如果能有一个东西,能让程序按照我们写的路径去data中获取值,这就OK了。

OK,兄弟们,这个东西来了:

function getValueByPath(obj,path){ ... }

这个函数就是我们要的,它接收两个参数 :

  1. obj:就是我们定义的对象。
  2. path:访问的路径。

有了这个东西,我们继续往下想:我们平常访问一个 一级对象 怎么访问的?

let obj = {
    a: 1
}

很明显,obj.a就能拿到这个值。

那么 二级对象 呢?

let obj = {
    a: {
        b: 1
    }
}

此时,obj.a拿到的是啥,是对象{b: 1},所以:

let temp = obj.a;

temp.b // 1

这样也是可以拿到最终的值。

那么,多级对象呢?很明显就是重复重复重复上面的操作,直到拿到最终的值。

OK,我们如何能让一个对象,一直一直一直的访问呢?首先我们想到一个类似 一直动,一直动,直到的结束的东西,就是 循环,那么能让循环 一直拿,一直拿的东西,很明显也有一个,就是数组

所以,啰嗦了这么多,我们的最终目的就是要:

  1. 把对象的访问路径变成一个数组
  2. 写一个循环一直拿,直到拿到最终结果。

OK,不啰嗦了,直接上代码:

 // 定义一个多级对象   
let o = {
        a: {
            b: {
                c: {
                    d: '这是要获取的值'
                }
            }
        }
    }

function getValue(obj, path) {
    // 首先通过 split 方法,根据 . 把访问路径解析成一个数组
    let paths = path.split('.'); // [a,b,c,d]
	// 拿到传过来的源对象 obj
    let res = obj;
    let prop;
    // 巧妙的利用 while 循环的特定,一直拿,指导 path.shift() 拿不到值,此时 prop 就会是 undefined 那么 while 循环就会结束
    while(prop=paths.shift()) {
        res = res[prop];
    }
	// 返回结果
    return res;
}

let r = getValue(o, 'a.b.c.d');

console.log(r);

很简单的几行代码,就搞定了多级访问的事情。


那么,我么把这个东西放回到我们插值替换的代码里

function getValue(obj, path) {
    // 首先通过 split 方法,根据 . 把访问路径解析成一个数组
    let paths = path.split('.'); // [a,b,c,d]
	// 拿到传过来的源对象 obj
    let res = obj;
    let prop;
    // 巧妙的利用 while 循环的特定,一直拿,指导 path.shift() 拿不到值,此时 prop 就会是 undefined 那么 while 循环就会结束
    while(prop=paths.shift()) {
        res = res[prop];
    }
	// 返回结果
    return res;
}

// 对下面插值替换的代码进行改造。
// 利用replace,结合正则表达式,来对插值进行替换
txt = txt.replace(regx, function (_, g) {
    // 此时的 key 对于多级对象来说肯定就是一个 路径了,所以我们改一下名字,叫key不合适
    // let key = g.trim();
    let path = g.trim();
    
    // 那么 data[key] 也要改一下了
    //let value = data[key];
    let value = getValue(data, path);
    
    return value;
});

这样,我们的插值替换,就能搞定 多级对象 的访问啦。


OK,最后在说两句:Vue里实现的比咱这高级,类似这样:

let o = {
    a: {
        b: {
            c: {
                d: '123'
            }
        }
    }
}

function createValueByPath(path) {
    let paths = path.split('.'); // [a,b,c,d]

    // 返回一个函数
    return function getValueByPath(obj) {
        let res = obj;
        let prop;
        while (prop = paths.shift()) {
            res = res[prop];
        }

        return res;
    }
}

let getValueByPath = createValueByPath('a.b.c.d');

let value = getValueByPath(o);

console.log(value);

Vue很好的利用了缓存机制,在编译的时候,如果就拿到路径穿进去,那么最后在获取值时,其实就只需要穿进去一个源对象就好了。

这就很好的避免了,每次去找这个对象都得重新解析一遍路径,算是提升了一点点性能吧,毕竟积少成多嘛。

下一篇,我们简单的说一下,虚拟dom怎么搞。

传送门:简单实现Vue中的虚拟dom

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值