当前位置 : 主页 > 网络编程 > JavaScript >

Vue3 reactive响应式赋值页面不渲染的解决

来源:互联网 收集:自由互联 发布时间:2023-02-08
目录 Vue3 reactive响应式赋值页面不渲染 问题描述 1.因数据结构而导致的未渲染解决方法 2.因页面节点未加载导致页面未渲染解决方法 3.因未指到具体点未渲染解决方法 Vue3 响应式原理
目录
  • Vue3 reactive响应式赋值页面不渲染
    • 问题描述
    • 1.因数据结构而导致的未渲染解决方法
    • 2.因页面节点未加载导致页面未渲染解决方法
    • 3.因未指到具体点未渲染解决方法
  • Vue3 响应式原理-reactive
    • Reactivity模块基本使用
    • 编写reactive函数

Vue3 reactive响应式赋值页面不渲染

问题描述

//声明变量
let data = reactive([])
http().then(res=>{
  data = res.data
  console.log(data)
})
//data数据更新,页面没有渲染

1.因数据结构而导致的未渲染解决方法

依旧是reactive,可以在外面包一层

//声明
let state = reactive({
  data:[]
})
//赋值
state.data= res.data

改为ref赋值

//声明
let data = ref([])
//赋值
data.value = res.data

2.因页面节点未加载导致页面未渲染解决方法

import {nextTick} from 'vue'
const func = async ()=>{
    await nextTick()
    state.data= res.data
}

3.因未指到具体点未渲染解决方法

const state = reactive({
    data:[{
        name:'tom',
        age:3
    },...]
})
const func = async ()=>{
    //state.data.forEach(item=>{
    //    item.age = 4//未生效
    //})
    state.data.forEach((item,index)=>{
        state.data[index].age = 4
    })
}

Vue3 响应式原理-reactive

Reactivity模块基本使用

<div id="app"></div>
<script src="./reactivity.global.js"></script>
<script>
    const { reactive, effect, shallowReactive, shallowReadonly, readonly } = VueReactivity;
    // let state = reactive({ name: 'jw', age: 30 });
    // const state = shallowReactive({ name: 'jw', age: 30 })
    // const state = readonly({ name: 'jw', age: 30 })
    const state = reactive({ name: 'jw', age: 30})
    effect(() => { // 副作用函数 (effect执行渲染了页面)
        app.innerHTML = state.name + '今年' + state.age + '岁了'
    });
    setTimeout(() => {
        state.age++;
    }, 1000)
</script>

reactive方法会将对象变成proxy对象, effect中使用reactive对象时会进行依赖收集,稍后属性变化时会重新执行effect函数。

编写reactive函数

const reactiveMap = new WeakMap(); // 缓存列表
const mutableHandlers: ProxyHandler<object> = {
    get(target, key, receiver) {
        // 等会谁来取值就做依赖收集
        const res = Reflect.get(target, key, receiver);
        return res;
    },
    set(target, key, value, receiver) {
        // 等会赋值的时候可以重新触发effect执行
        const result = Reflect.set(target, key, value, receiver);
        return result;
    }
}
function createReactiveObject(target: object, isReadonly: boolean) {
    if (!isObject(target)) {
        return target
    }
    const exisitingProxy = reactiveMap.get(target); // 如果已经代理过则直接返回代理后的对象 
    if (exisitingProxy) {
        return exisitingProxy;
    }
    const proxy = new Proxy(target, mutableHandlers); // 对对象进行代理
    reactiveMap.set(target,proxy)
    return proxy;
}

这里必须要使用Reflect进行操作,保证this指向永远指向代理对象

let school = {
    name:'zf',
    get num(){
        return this.name;
    }
}
let p = new Proxy(school,{
    get(target, key,receiver){
        console.log(key);
        // return Reflect.get(target,key,receiver)
        return target[key]
    }
})
p.num

将对象使用proxy进行代理,如果对象已经被代理过,再次重复代理则返回上次代理结果。 那么,如果将一个代理对象传入呢?

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易盾网络。 

上一篇:解决element ui cascader 动态加载回显问题
下一篇:没有了
网友评论