认识ref shallowRef triggerRef
- 用法
<template>
<div>{{mycount}}
<button @click="changeMyCount">111</button>
</div>
</template>
<script>
import { ref,shallowRef,triggerRef } from "vue";
export default {
name: "ref",
setup(){
// ref 分为两种情况 ref(2) ref({datas:2}) 这两种情况是不一样的
const mycount = ref(2);
//shallowRef 创建的值 是只做第一层的响应,就是像vue2 中的数据响应,对于对象内的变动,是不是响应的
// triggerRef 强制刷新视图
const changeMyCount = ()=>{
mycount.value.kk = mycount.value.kk + 2 ;
dd.value.age = dd.value.age + 4 ;
triggerRef(dd)
}
return {
mycount,
changeMyCount,
}
}
}
</script>
<style>
.a {
background: red;
}
</style>
- 尝试阅读源码,下载cdn文件去查看。《我之前的地址》
// 1
function ref(value) {
console.log(1,value)
return createRef(value, false);
}
// 2
function createRef(rawValue, shallow) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
//3
class RefImpl {
constructor(value, _shallow) {
this._shallow = _shallow;// 浅监听
this.dep = undefined;
this.__v_isRef = true; // 对应了上面 isRef(rawValue)
// 原始value
this._rawValue = _shallow ? value : toRaw(value);
// 实际用到的value
this._value = _shallow ? value : toReactive(value);
}
get value() {
trackRefValue(this);
return this._value;
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = this._shallow ? newVal : toReactive(newVal);
triggerRefValue(this, newVal);
}
}
}
接下来来看下get 里面都干了啥
// dep 跟 reactive 响应有关系, 可以先不管。目前只需要判断dep是否为undefined
const createDep = (effects) => {
const dep = new Set(effects);
dep.w = 0;
dep.n = 0;
return dep;
};
//
let shouldTrack = true;
let activeEffect;
function isTracking() {
return shouldTrack && activeEffect !== undefined;
}
//
function trackRefValue(ref) {
if (isTracking()) {
ref = toRaw(ref);
if (!ref.dep) {
ref.dep = createDep();
}
{
// 响应监听value的变化,先不深究这个方法。
trackEffects(ref.dep, {
target: ref,
type: "get" /* GET */,
key: 'value'
});
}
}
}
现在再来看下set 方法
// reactive === import {reactive} from 'vue'
const toReactive = (value) => isObject(value) ? reactive(value) : value;
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal);
// 值是否变动
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
// set 值之后。避免value变为对象失去监听
this._value = this._shallow ? newVal : toReactive(newVal);
// 触发器 触发 调度器 ,产生页面更新
triggerRefValue(this, newVal);
}
}
所以现在敲重点 记笔记。 ref 数据响应式分为两种。一种是对象类型,另外一种是非对象类型。处理方式是不一样的,不是全部proxy 一把梭哈。对于非对象类型还是采用原有的Object.defineProperty 监听方式, 对于传入的对象则是采用 proxy 监听。 然你后在 proxy 去 触发调度器,然后刷新到视图。