vue-next

vue-next项目地址

git地址:链接

git clone [email protected]:vuejs/vue-next.git
npm install
npm run dev // 生成一个未压缩的状态vue文件

vue-next_第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>
    <script src="./vue.global.js"></script>
</head>
<body>
    <div id="app">

    </div>
    <script>
        const { createApp,reactive,computed,effect } = Vue;
        
        const YpComponent = {
            template:`
            
            `,
            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


<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>Documenttitle>
    <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 = `

${obj.name}版本${obj.age} double:${double.value}

`
}) 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()
         }
    }
}

你可能感兴趣的:(Vue)