vue-next
vue-next项目地址git地址:链接git clone git@github.com:vuejs/vue-next.gitnpm installnpm run dev // 生成一个未压缩的状态vue文件入门小案例<!DOCTYPE html><html lang="en"><head><meta charset="UTF...
   ·  
 vue-next项目地址
git地址:链接
git clone git@github.com:vuejs/vue-next.git
npm install
npm run dev // 生成一个未压缩的状态vue文件

入门小案例
<!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>
    <script src="./vue.global.js"></script>
</head>
<body>
    <div id="app">
    </div>
    <script>
        const { createApp,reactive,computed,effect } = Vue;
        
        const YpComponent = {
            template:`
            <button @click="increment">Count is {{state.count}} double:{{state.double}}</button>
            `,
            setup(){
                const state = reactive({
                    count:0,
                    double:computed(()=>state.count*2)
                })
                effect(()=>{
                    // 副作用 可以监听变化
                    console.log('数字变化了',state.count)
                })
                function increment(){
                    state.count+=1
                }
                return {
                    state,
                    increment
                }
            }
        }
        createApp().mount(YpComponent,'#app')
    </script>
</body>
</html>
自己写一个reactive,computed,effect
<!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>
    <script src="./my-vue.js"></script>
</head>
<body>
    <div id="app"></div>
    <button id="btn">点我</button>
    <script>
        const root = document.querySelector('#app')
        const btn = document.querySelector('#btn')
        const obj = reactive({
            name: "vue",
            age: 6
        })
        let double= computed(()=>obj.age*2)
        effect(() => {
            root.innerHTML = `<h1>${obj.name}版本${obj.age} double:${double.value}</h1>`
        })
        btn.addEventListener('click', () => {
            obj.age += 1
        }, false)
    </script>
</body>
</html>
my-vue.js
let toProxy = new WeakMap() //存储  原始--响应
let toRaw = new WeakMap() //存储  响应--原始
const baseHander = {
    get(target, key) {
        const res = Reflect.get(target, key)
        //收集依赖
        track(target, key)
        // 递归查找
        return typeof res === 'object' ? reactive(res) : res
    },
    set(target, key, val) {
        const info = {
            oldValue: target[key],
            newValue: val
        }
        // if(target.hasOwnProperty(key)){ // 即如果触发的是私有属性,可以直接触发视图更新,length会屏蔽掉
        //     trigger();
        // }
        const res = Reflect.set(target, key, val)
        // 触发更新
        trigger(target, key, info)
        return res
    }
}
function reactive(target) {
    // 查询缓存
    let observed = toProxy.get(target)
    if (observed) {
        return observed;
    }
    if (toRaw.get(target)) {
        return target
    }
    observed = new Proxy(target, baseHander)
    //设置缓存
    toProxy.set(target, observed)
    toRaw.set(observed, target)
    return observed
}
let effectStack = []
let tagetMap = new WeakMap() //存储effect
function trigger(target, key, info) {
    const depsMap = tagetMap.get(target)
    if (depsMap === undefined) {
        return
    }
    const effects = new Set()
    const computedRuners = new Set()
    if (key) {
        let deps = depsMap.get(key)
        deps.forEach((effect) => {
            if(effect.computed){
                computedRuners.add(effect)
            }else{
                effects.add(effect)
            }
        })
    }
    // const run = effect =>effect()
    effects.forEach(effect => effect())
    computedRuners.forEach(effect => effect())
}
function track(target,key) {
    let effect = effectStack[effectStack.length - 1]
    if (effect) {
        let depsMap = tagetMap.get(target)
        if (depsMap === undefined) {
            depsMap = new Map()
            tagetMap.set(target, depsMap)
        }
        let dep = depsMap.get(key)
        if (dep === undefined) {
            dep = new Set()
            depsMap.set(key, dep)
        }
        if (!dep.has(effect)) {
            dep.add(effect)
            effect.deps.push(dep)
        }
    }
}
function effect(fn, options={}) {
    let e = createReactiveEffect(fn, options)
    if(!options.lazy){
        e()
    }
    return e
}
function createReactiveEffect(fn, options) {
    const effect = function effect(...args) {
        return run(effect, fn, args)
    }
    effect.deps = []
    effect.computed = options.computed
    effect.lazy = options.lazy
    return effect
}
function run(effect, fn, args) {
    if (effectStack.indexOf(effect) === -1) {
        try {
            effectStack.push(effect)
            return fn(...args)
        } finally {
            effectStack.pop()
        }
    }
}
function computed(fn) {
    const runner = effect(fn,{computed:true,lazy:true})
    return {
         effect:runner,
         get value(){
             return runner()
         }
    }
}
更多推荐
 
 



所有评论(0)