zoukankan      html  css  js  c++  java
  • 自己写的一个Vue

    下面这里是我自己写的一个小型的vue,原理就是proxy:

    //Proxy天生没有prototype,因此要加上,不然extends会报错
    Proxy.prototype = Proxy.prototype || Object.prototype
    
    class myVue extends Proxy {
        constructor(options) {
            let data = options.data || {}
    
            super(data, {
                get(target, name, proxy) {
                    if(name in target) {
                        return target[name]
                    } else {
                        throw new Error(`不存在data'${name}'`)
                    }
                },
                set(target, name, value, proxy) {
                    target[name] = value
                    _container.render()
                }
            })
            // 不能够在constructor里面设置data的值,因此公共变量只能在constructor里面定义,通过函数调用传递
            // this.$el = document.querySelector(options.el)
            
            //data被类本身代理,而其他options经过初步处理后我们保存在一个变量对象_container中
            let _container = {}
            window.onload = function() {
                _container.data = data
                _container.el = document.querySelector(options.el)
                _container.oldEl = document.querySelector(options.el).cloneNode(true)
                _container.methods = options.methods || {}
                //特殊地我们需要一个重新渲染el的内部方法也要存在_container里面
                //绑定_container本身是为了render函数能够使用存在_container里面的options的内容
                _container.render = render.bind(_container)
                _container.render()
            }
        }
        //get只能get到data对象里面的值,所以在内部定义的函数也没办法用
        // zzz(){
        //     alert(123)
        // }
    }
    
    function render() {
        let _computer = (e) => {
            let val = ''
            with(this.data){
                val = eval(e)
            }
            return val
        }
    
        //先把dom上的替换成“备份”
        this.el.parentNode.replaceChild(this.oldEl, this.el);
        //"备份"切换到this.el上等待被渲染
        this.el = this.oldEl
        //再复制一份留“备份”
        this.oldEl = this.oldEl.cloneNode(true)
    
        //处理花括号
        this.el.innerHTML = this.el.innerHTML.replace(/{{[^{}]+}}/, (str) =>{
            let e = str.substring(2,str.length-2)
            return _computer(e)
        })
    
        //处理:属性
        let nodes = this.el.getElementsByTagName('*')
        Array.from(nodes).forEach(node => {
            Array.from(node.attributes).forEach(attr => {
                if(attr.nodeName.startsWith(':')){
                    node.setAttribute(attr.nodeName.substring(1),_computer(attr.value)) 
                    node.removeAttribute(attr.nodeName) 
                } else if (attr.nodeName.startsWith('@')) {
                    if(!this.methods[attr.value]) {
                        throw new Error(`methods里面没有方法'${attr.value}'`)
                    }
                    node.addEventListener(attr.nodeName.substring(1),function(){
                        this.methods[attr.value]()
                    }.bind(this),false) 
                    node.removeAttribute(attr.nodeName)
                }
            })
        })
    }

    对应调用的HTML:

    <!DOCTYPE html>
    <html>
    <head>
        <title>myVue</title>
        <script src="my-vue.js"></script>
        <script>
            let vm = new myVue({
                el: '#app',
                data: {
                    aaa: 123,
                    bbb: '你好啊,张啊咩'
                },
                methods:{
                    sayHello() {
                        alert('hello')
                    }
                }
            })
            console.log(vm.aaa)
        </script>
    </head>
    <body>
        <div id="app">
            {{aaa}}
            <span :title="bbb" @click="sayHello">
                hahaha
            </span>
        </div>
    </body>
    </html>
  • 相关阅读:
    jquery选择器详解
    git discard when composer update
    ASCII码、HEX、字符、BCD 等等 基础知识思考
    中文汉字占二个字节还是三个字节长度
    php二分查找的两种实现方法
    windows下运行多个版本node.js
    NodeJS
    Error in library(qcc) : there is no package called 'qcc'
    jquery网络引用地址(收藏)
    实现二分查找
  • 原文地址:https://www.cnblogs.com/amiezhang/p/8433461.html
Copyright © 2011-2022 走看看