手写源码系列:vue响应式实现原理!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {{ data }}
    </div>
</body>
</html>
<script>
    //手写vue实现原理 vue
    // vue 数据劫持 +  发布订阅名单
    class Vue{
        //vue 生命周期 created时 将data中的数据挂载到了this上 this上的第一层的所有属性都有$包装
        constructor(options){
            options = options || {} ;
            for(var attr in options){
                this['&'+attr] = options[attr];
            }
            //当data存在并且有数据的时候 将属性通过数据劫持监听起来
            for(var attr in options.data){
                this[attr] = options.data[attr];
                //将每个属性添加到订阅者名单中
                observer.on({
                    attr:attr
                });
                Object.defineProperty(this,'_'+attr,{
                    get(){
                        console.log("我在获取值");
                        return this[attr];
                    },
                    set(newVal){
                        this[attr] = newVal;
                        console.log("我在设置值");
                        //当修改属性指的时候,
                        observer.emit.call(this,attr,newVal);
                        return this[attr];
                    }
                })
            }
            //编译模板
            this.mounted(options.el);
        }
        mounted(el){
            //将差值语法替换为 对象中的数据
            //选择元素
            this.ele = this.chooseEl(el); 
            var reg = new RegExp('{{\\s?data\\s?}}','g');
            this.ele.innerHTML = this.ele.innerHTML.replace(reg,this.msg);   
            //下一次的开始 是上一次的结束
            this.lastTemplate = this.ele.innerHTML;
        }
        againChange(val){
            var ele = this.ele; 
            var reg = new RegExp(''+ this.lastTemplate.trim(),'g');
            ele.innerHTML = ele.innerHTML.replace(reg,val); 
            //下一次的开始 是上一次的结束
            this.lastTemplate = ele.innerHTML;
        }
        chooseEl(el){
            el = document.querySelectorAll(el);
            if(el.length > 1){
                return [].slice.call(el);
            }else if(el.length === 1){
                return el[0];
            }else{
                return null;
            }
        }
    }
    
    //创建发布订阅中名单
    var observer = {
        list:[],
        on(p){
            this.list.push(p);
        },
        emit(attr,newval){
            observer.list.forEach(item => {
                if( item.attr === attr ){
                   this.againChange(newval);
                }
            })
        }
    }
    
    var vue = new Vue({
        el:"#app",
        data:{
            msg:"欢迎来到前端编程世界"
        }
    })
</script>

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值