博客
关于我
ASP.NET三层架构详解
阅读量:800 次
发布时间:2019-03-25

本文共 4202 字,大约阅读时间需要 14 分钟。

Vue 3_Ref响应性实现深度解析

Vue 3 中,针对基础类型和引用类型数据的响应性实现方式存在显著差异。本文将从 Ref 实现原理、代码解析以及实际应用场景等多个方面展开全面探讨。

Ref 的响应性实现机制

Ref 是 Vue 3 提供的一种强式响应式简写语法,其核心实现目标是可以只通过 .value 属性修改业务逻辑,强化开发体验。在实现上,ref 与 _v_isRef 标志位的判断逻辑plays大角色。

代码剖析:RefImpl 类

RefImpl 是 Ref 实现的核心类,主要属性包括 _rawValue 和 _value,分别代表原始值和被包装的值。以下是关键代码段:

class RefImpl {  constructor(_rawValue, _shallow = false) {    this._rawValue = _rawValue;    this._shallow = _shallow; // shallowRef 标志位    this.__v_isRef = true;    this._value = _shallow ? _rawValue : convert(_rawValue);  }    get value() {    track(toRaw(this), 'get', 'value');    return this._value;  }    set value(newVal) {    if (hasChanged(toRaw(newVal), this._rawValue)) {      this._rawValue = newVal;      this._value = this._shallow ? newVal : convert(newVal);      trigger(toRaw(this), 'set', 'value', newVal);    }  }}
  • getvalue 方法:组合了 track 函数,触发响应式更新。
  • setvalue 方法:根据是否浅层模式决定直接赋值或经过 convert 转换。
Ref与Reactive的关系

值得注意的是,基础类型的 Ref 与 Reactive 没必然联系,引用类型的 Ref 则会_embryos_一个 Reactive 实例:

// 基础类型 const refCount = ref(0) // backingValue 直接已一个数值 // 引用类型 const refObject = ref({ value: 0 }) // backingValue 是一个包含 value 属性的对象// 在 value 属性上挂解重新应性 // 其背后为一个 Reactve 实例 {//   value: 0 // }
浅层 Ref 与深层 Ref 的差异

ShallowRef 实现仅对 .value 属性进行响应式追踪,深层结构则完全不响应变化:

// 浅层 Ref const srefCount = shallowRef(0)// 全深层引用类型 const srefObject = shallowRef({ value: 0 })// 嵌套对象 const srefObjectMore = shallowRef({ value: { a: 'jyk' } })
triggerRef 调用示例

当涉及到嵌套对象的响应式修改时,通常需要手动调用 triggerRef:

// 修改嵌套对象的属性 const setObjectProp = () => {  srefObjectMore.value.value.a = new Date().getTime()  triggerRef(srefObjectMore)}// 修改嵌套对象的 .value const setObjectMore = () => {  srefObjectMore.value = {     value: {       a: new Date().getTime()     }   }  triggerRef(srefObjectMore)}

toRef 与 toRefs 的实际应用

toRef 和 toRefs 作为辅助函数,主要用于将 Reactve 实例中的特定属性转为 Ref 类型,同时保持响应式连接。两者均依赖于 ObjectRefImpl 内部实现:

// 单个属性 Ref const refName = toRef(person, 'name')// 多个属性 Ref const personToRefs = toRefs(person)
  • toRef:返回一个 Ref 实例,仅关注目标属性的变化。
  • toRefs:返回一个包含多个 Ref 实例的对象,每个属性都对应目标属性。
toRef 源码分析
function toRef(object, key) {  const objKey = object[key];  return isRef(objKey)    ? objKey    : new ObjectRefImpl(object, key);}// ObjectRefImpl 实现结构class ObjectRefImpl {  constructor(_object, _key) {    this._object = _object;    this._key = _key;    this.__v_isRef = true;  }  get value() {    return this._object[this._key];  }  set value(newVal) {    this._object[this._key] = newVal;  }}
toRefs 源码分析
function toRefs(object) {  if (!isProxy(object)) {    console.warn('pegp');  }  const ret = isArray(object) ? new Array(object.length) : {};  for (const key in object) {    if (hasOwn(object, key)) {      ret[key] = toRef(object, key);    }  }  return ret;}

延迟响应用 case:v-model 应用

延迟响应控制台是一个实际场景,常见于搜索输入等交互:

const useDebouncedRef = (value, delay = 200) => {  let timeout;  return customRef((track, trigger) => ({    get() {      track()      return value;    },    set(newVal) {      clearTimeout(timeout);      timeout = setTimeout(() => {        value = newVal;        trigger();      }, delay);    }  }));}
自定义 Ref 示例
const myComputed = (_get, _set) => {  return customRef((track, trigger) => ({    get() {      track();      if (typeof _get === 'function') {        return _get();      } else {        console.warn('未配置 get 方法')      }    },    set(newVal) {      if (typeof _set === '-function') {        _set(newVal)        trigger();      } else {        console.warn('未配置 set 方法')      }    }  }));}
计算属性实现
// 简单计算属性const myCom = myComputed(() => refCount.value + 1)// 完整计算属性const setRef = () => {  // 直接修改 Ref 的 .value  refCount.value += 1}
Vue 原生计算属性

Vue 原生计算属性实现通过 computed factory函数构建,比 Ref 更强大灵活:

function computed(getterOrOptions) {  let getter;  let setter;  if (isFuncton(getterOrOptions)) {    getter = getterOrOptions;    setter = () => {      console.warn('不可读写')    }  } else {    getter = getterOrOptions.get;    setter = getterOrOptions.set;  }  return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || (!getterOrOptions.set));}

总结

Vue 3 的 Ref 和 Reactve 几乎完全不同 redraw机制。Ref 对简单类型实现原生响应式,而对复杂对象,只有通过引用对象的属性变化才能触发。

在实际应用中, mastering RefAndReactive 的关系规则是核心技能之一。

通过以上理解,我们可以更合理地选择 Ref 与 Reactve 的结合方式,从而充分发挥 Vue.js 的响应式能力。

转载地址:http://wltyk.baihongyu.com/

你可能感兴趣的文章
python中对集合的操作
查看>>
python中将列表转换为元组的时间复杂度,反之亦然
查看>>
Python中布尔表达式的求值
查看>>
python中很常用的10个内置函数整理(初学必备)
查看>>
python中打印二维列表数据
查看>>
python中打散数组shuffle
查看>>
Python中执行外部命令
查看>>
Python中拼接numpy数组-ChatGPT4o作答
查看>>
Python中提示:no module named 'PIL'
查看>>
Python中提示:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position
查看>>
python中数据类型存储_浅谈Python中的数据类型
查看>>
python中文件最重要的功能是什么-学 Python 都用来干嘛的?
查看>>
python中文版语言_高盛最新调查:Python超过汉语成为未来最重要技能,你准备学哪种编程语言?...
查看>>
Python中文问题SyntaxError
查看>>
Python中方括号和括号括起来的列表有什么区别?
查看>>
python中时间处理_Python中处理时间的几种方法小结
查看>>
Python中枚举串口(包括虚拟端口)的跨平台方法是什么?
查看>>
python中根号下a怎么写_python中根号怎么表示
查看>>
Python中正则表达式的巧妙使用
查看>>
Python中浮点数的二进制表示(位不是十六进制)
查看>>