vue实现?

153 阅读1分钟
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="text" v-text="text"></div>
    <div class="html" v-text="html"></div>    
    <script>
        function Vue (options) {
            let data = options.data
            let computed = options.computed
            initData(this, data)
            initComputed(this, computed)
        }

        function initData (vm, data) {
            // Object.keys() js方法返回对象的属性名
            let keys = Object.keys(data)
            keys.forEach(key => {
                observer(vm, key, data[key])
            })
        }
        function Dep () {
            this.subs = []
        }
        Dep.target = null
        function observer (vm, key, value) {
            let dep = new Dep()
            let initVal = value
            // Object.defineProperty(obj, prop, descriptor)直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象
            // obj 需要定义属性的对象。
            // prop 需被定义或修改的属性名。
            // descriptor 需被定义或修改的属性的描述符。
            Object.defineProperty(vm, key, {
                get () {
                    debugger
                    if (Dep.target) {
                        dep.subs.push(Dep.target)
                    }
                    return initVal
                },
                set (val) {
                    debugger
                    initVal = val
                    for(let key in dep.subs) {
                        dep.subs[key].call(vm)
                    }
                }
            })
        }
        function initComputed (vm, computeds) {
            let keys = Object.keys(computeds)
            keys.forEach(key => {
                watcher(vm, computeds[key])
            })
        }
        function watcher (vm, fun) {
            Dep.target = fun
            fun.call(vm)
            Dep.target = null
        }

        let vm = new Vue({
            data: {
                text: 123,
                html: '<a href="http://www.baidu.com">456</a>'
            },
            // 应该是watcher的功能 不代表计算属性
            computed: {
                text () {
                    // debugger
                    document.querySelector('.text').innerText = this.text
                },
                html () {
                    document.querySelector('.html').innerHTML = this.html                    
                }
            }
        })
    </script>
</body>
</html>