vue2双向绑定原理,面试题等

1,?前面的字符大写
const str = 'i?? love??? ? word';
const handleStr = (newstr) => {
    // let str = newstr.replace(/\s/g, '');
    let str = newstr.split(' ').join('');
    let len = str.length;
    let result = '';
    for (let index = 0; index < len; index++) {
        const element = str[index];
        let newElement = str[index];
        if (str[index] !== '?' && str[index] !== ' ') {
            if (str[index - 1] === '?') {
                newElement = ' ' + newElement.toUpperCase();
            }
            result += newElement
        }
    }
   
    return result;
}
handleStr(str);
console.log(handleStr(str)); //  i Love Word// 类似的思路
const str2 = 'i?? love??? ? word';
const handleStr2 = (newstr) => {
    let result = '';
    let isFirst = false;
    for (const word of newstr) {
        if (word !== '?' && word !== ' ') {
            result += isFirst ? ` ${word.toUpperCase()}` : word;
            isFirst = false;
        } else if (word === '?') {
            isFirst = true;
        }
    }
    return result;
}
console.log(handleStr2(str2)); //  i Love Word
2,循环生成字符串
// 例子1: '2[a]3[b]4[c]'
// 输出:'aabbbcccc'
// 例子2: '2[ab]3[cd]'
// 输出: 'ababcdcdcd'
// 例子3: '3[a2[cd]]'
// 输出: 'acdcdacdcdacdcd'
// 方法1
const getStr = function (str) {
  let start = 0;
  let end = 0;
  let newStr = "";
  for (let index = 0; index < str.length; index++) {
    const element = str[index];
    if (element === "[") {
      start = index;
    } else {
      if (element === "]") {
        end = index;
        break;
      }
    }
  }
  if (start === 0 && end === 0) {
    return str;
  } else {
    let dataStr = str.slice(start + 1, end);
    let count = str[start - 1];
    let results = "";
    for (let j = 0; j < Number(count); j++) {
      results = results + dataStr;
    }
    newStr = str.replace(str.slice(start - 1, end + 1), results);
    return getStr(newStr);
  }
};
console.log(getStr("2[a]3[b]4[c]"));
console.log(getStr("2[ab]3[cd]")); // 输出:'ababcdcdcd'
console.log(getStr("3[a2[cd]]"));
3,原生实现vue2双向绑定
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue 双向绑定实现</title>
</head>

<body>
    <div>yuzhi</div>
    <script>
        const Observer = function (data) {
            // 循环修改为每个属性添加get set
            for (let key in data) {
                defineReactive(data, key);
            }
        }

        const defineReactive = function (obj, key) {
            // 局部变量dep,用于get set内部调用
            const dep = new Dep();
            debugger
            // 获取当前值
            let val = obj[key];
            Object.defineProperty(obj, key, {
                // 设置当前描述属性为可被循环
                enumerable: true,
                // 设置当前描述属性可被修改
                configurable: true,
                get(val) {
                    // console.log('in get');
                    console.log('in get', val);
                    debugger
                    // 调用依赖收集器中的addSub,用于收集当前属性与Watcher中的依赖关系
                    dep.depend();
                    return val;
                },
                set(newVal) {
                    if (newVal === val) {
                        return;
                    }
                    val = newVal;
                    // 当值发生变更时,通知依赖收集器,更新每个需要更新的Watcher,
                    // 这里每个需要更新通过什么断定?dep.subs
                    dep.notify();
                }
            });
        }

        const observe = function (data) {
            return new Observer(data);
        }

        const Vue = function (options) {
            const self = this;
            // 将data赋值给this._data,源码这部分用的Proxy所以我们用最简单的方式临时实现
            if (options && typeof options.data === 'function') {
                this._data = options.data.apply(this);
            }
            // 挂载函数
            this.mount = function () {
                new Watcher(self, self.render);
            }
            // 渲染函数
            this.render = function () {
                with(self) {
                    _data.text;
                }
            }
            // 监听this._data
            observe(this._data);
        }

        const Watcher = function (vm, fn) {
            const self = this;
            this.vm = vm;
            // 将当前Dep.target指向自己
            Dep.target = this;
            // 向Dep方法添加当前Wathcer
            this.addDep = function (dep) {
                dep.addSub(self);
            }
            // 更新方法,用于触发vm._render
            this.update = function () {
                console.log('in watcher update');
                fn();
            }
            // 这里会首次调用vm._render,从而触发text的get
            // 从而将当前的Wathcer与Dep关联起来
            this.value = fn();
            // 这里清空了Dep.target,为了防止notify触发时,不停的绑定Watcher与Dep,
            // 造成代码死循环
            Dep.target = null;
        }

        const Dep = function () {
            const self = this;
            // 收集目标
            this.target = null;
            // 存储收集器中需要通知的Watcher
            this.subs = [];
            // 当有目标时,绑定Dep与Wathcer的关系
            this.depend = function () {
                if (Dep.target) {
                    // 这里其实可以直接写self.addSub(Dep.target),
                    // 没有这么写因为想还原源码的过程。
                    Dep.target.addDep(self);
                }
            }
            // 为当前收集器添加Watcher
            this.addSub = function (watcher) {
                self.subs.push(watcher);
            }
            // 通知收集器中所的所有Wathcer,调用其update方法
            this.notify = function () {
                for (let i = 0; i < self.subs.length; i += 1) {
                    self.subs[i].update();
                }
            }
        }
        const vue = new Vue({
            data() {
                return {
                    text: 'hello world'
                };
            }
        })
        vue.mount(); // in get vue._data.text='123' ; // in watcher update /n in get
    </script>
</body>

</html>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值