当前位置: 首页 > wzjs >正文

网站做端口是什么问题开发定制软件公司

网站做端口是什么问题,开发定制软件公司,八戒网站做推广,广告页面制作最近在研究各个框架的源码,从源码角度去理解 vue3 的 reactive 和 ref API,记录下研究的成果 reactive 首先,reactive() 的参数必须是一个对象,返回值是一个 Proxy 对象,具有响应性。如果参数不是对象类型&#xff0…

最近在研究各个框架的源码,从源码角度去理解 vue3 的 reactive 和 ref API,记录下研究的成果

reactive

首先,reactive() 的参数必须是一个对象,返回值是一个 Proxy 对象,具有响应性。如果参数不是对象类型,会提示:value cannot be made reactive。
多次对同一个对象使用 reactive 进行代理,返回的是相同的代理对象,也就是说使用的是缓存的值。而且,取值时直接读取属性就行,不需要加 .value 。
例子:

import { reactive } from 'vue'
const state = reactive({ count: 0 })
console.log(state.count) // 0const name = reactive('hh')
console.log('name', name) // warn: value cannot be made reactive: hhconst raw = {}
const proxy = reactive(raw)
console.log(proxy === raw) // false
// calling reactive() on the same object returns the same proxy
console.log(reactive(raw) === proxy) // true
// calling reactive() on a proxy returns itself
console.log(reactive(proxy) === proxy) // true

接下来说下 reactive 的局限性。
首先,参数只支持 object 类型 (比如 objects, arrays, Map, Set),不支持基础数据类型,比如string, number 或boolean;
其次,对变量重新赋值会丢失响应性,比如:

let state = reactive({ count: 0 })
// the above reference ({ count: 0 }) is no longer being tracked
// (reactivity connection is lost!)
state = reactive({ count: 1 })

而且,解构赋值容易丢失响应性:

const state = reactive({ count: 0 })// count is disconnected from state.count when destructured.
let { count } = state
// does not affect original state
count++

这种情况下,我们可以使用 toRefs 函数来将响应式对象转换为 ref 对象

import { toRefs } from 'vue';const state = reactive({ count: 0 });
let { count } = toRefs(state);
count++; // count 现在是 1

ref

再来看下 ref() 。reactive 和 ref 都是声明响应式变量的写法,但是,ref 的参数既可以是基本数据类型的值,也可以是对象,很自由!这就是为什么我们在开发时更推荐使用 vue3 的 ref 的原因了。
而且,ref 声明的变量在取值时必须加上 .value,而在 template 调用时中不加。
例子:
再来看下 ref() 。reactive 和 ref 都是声明响应式变量的写法,但是,ref 的参数既可以是基本数据类型的值,也可以是对象,很自由!这就是为什么我们在开发时更推荐使用 vue3 的 ref 的原因了。
而且,ref 声明的变量在取值时必须加上 .value,而在 template 调用时中不加。
例子:

const {ref, effect} = Vueconst name = ref('张三')
console.log('name', name.value) // name 张三const state = ref({ count: 0 })
console.log('state', state.value.count) // state 0

ref 源码

深入源码看下为什么。

ref() 中调用的是 createRef(value, false),在这个函数中,首先判断属性 __v_isRef 是否为 true,为 true 说明是 Ref 类型的值,直接返回;否则,返回的是 RefImpl 类的实例。

类的 get 和 set

再来看 RefImpl 类,重点是类中定义了 get 函数和 set 函数。当我们对类实例的 value 属性取值和赋值时,就会触发这两个函数。

// ref.tsexport function ref(value?: unknown) {return createRef(value, false)
}function createRef(rawValue: unknown, shallow: boolean) {// 判断属性 __v_isRef 是否为 true,为 true 说明是 Ref 类型的值,直接返回if (isRef(rawValue)) {return rawValue}return new RefImpl(rawValue, shallow)
}export function isRef(r: any): r is Ref {return !!(r && r.__v_isRef === true)
}class RefImpl<T> {private _value: Tprivate _rawValue: T// 依赖项public dep?: Dep = undefined// 属性 __v_isRef 设置为 truepublic readonly __v_isRef = trueconstructor(value: T, public readonly __v_isShallow: boolean) {this._rawValue = __v_isShallow ? value : toRaw(value)this._value = __v_isShallow ? value : toReactive(value)}get value() {// 依赖收集trackRefValue(this)// 返回值return this._value}set value(newVal) {const useDirectValue =this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)newVal = useDirectValue ? newVal : toRaw(newVal)if (hasChanged(newVal, this._rawValue)) {this._rawValue = newValthis._value = useDirectValue ? newVal : toReactive(newVal)triggerRefValue(this, newVal)}}
}

举个例子理解下类中的 get 和 set 函数:

class RefImpl {// ref实例的getter行为get value () {console.log('get');return '111'}// ref实例的setter行为set value (val) {console.log('set');}
}const ref = new RefImpl()ref.value = '123'
ref.value

这里定义了 RefImpl 类,当我们对 ref.value 赋值时,会打印 set;当我们调用 ref.value 时,会打印 get。因此,我们不难理解为什么 Vue3 的 ref() 要加上 .value 了,因为也是使用了类中的 getter 和 setter 的写法。
此外,ref() 最终的返回值是 this._value,我们再来看下这部分的代码。这里是判断属性 __v_isShallow 是否为 true,为true 则直接返回,否则经过 toReactive() 处理下再返回。

this._value = __v_isShallow ? value : toReactive(value)

toReactive()

看下这个函数发生了什么。可以看到,如果参数是对象类型,则使用 reactive() 处理一下并返回;否则直接返回这个参数。
而 reactive() 中,我们是返回一个对象的 Proxy 对象,这个 Proxy 对象具有响应性,可以监听到我们对对象属性的读取和修改。值得一提的是,这里的 reactive() 正是 上面说到的声明响应性变量的 reactive() !也就是说,ref 的底层也用到了 reactive() ,二者是相通的,只不过 ref 多包装了一层,支持了基本数据类型的值。

// reactive.ts/*** Returns a reactive proxy of the given value (if possible).** If the given value is not an object, the original value itself is returned.** @param value - The value for which a reactive proxy shall be created.*/
export const toReactive = <T extends unknown>(value: T): T =>isObject(value) ? reactive(value) : value/*** Returns a reactive proxy of the object.** The reactive conversion is "deep": it affects all nested properties. A* reactive object also deeply unwraps any properties that are refs while* maintaining reactivity.** @example* ```js* const obj = reactive({ count: 0 })* ```** @param target - The source object.* @see {@link https://vuejs.org/api/reactivity-core.html#reactive}*/
export function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
export function reactive(target: object) {// if trying to observe a readonly proxy, return the readonly version.if (isReadonly(target)) {return target}return createReactiveObject(target,false,mutableHandlers,mutableCollectionHandlers,reactiveMap)
}

createReactiveObject()

看下响应性是如何实现的。

首先,在 createReactiveObject() 函数中,如果传参 target 是非对象类型的,会提示并直接返回,我们之前的例子中也观察到这种现象了;
其次,判断 target 是否是 Proxy 或者已经存在哈希表 proxyMap 中,如果是直接返回;

最后,如果传参只是一个普通的对象,我们需要使用 new Proxy() 将其转化为一个 Proxy 对象,我们知道在 Vue3 中响应性的实现正是通过 Proxy 去实现的。生成 Proxy 对象后,存入 proxyMap 中,并返回该 Proxy 对象即可。

function createReactiveObject(target: Target,isReadonly: boolean,baseHandlers: ProxyHandler<any>,collectionHandlers: ProxyHandler<any>,proxyMap: WeakMap<Target, any>
) {if (!isObject(target)) {if (__DEV__) {console.warn(`value cannot be made reactive: ${String(target)}`)}return target}// target is already a Proxy, return it.// exception: calling readonly() on a reactive objectif (target[ReactiveFlags.RAW] &&!(isReadonly && target[ReactiveFlags.IS_REACTIVE])) {return target}// target already has corresponding Proxyconst existingProxy = proxyMap.get(target)if (existingProxy) {return existingProxy}// only specific value types can be observed.const targetType = getTargetType(target)if (targetType === TargetType.INVALID) {return target}const proxy = new Proxy(target,targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers)proxyMap.set(target, proxy)return proxy
}

小结:
createReactiveObject 函数,即 reactive 函数,最终是将传参的对象转化为一个 Proxy 对象并返回,而 Vue3 中响应性的实现正是通过 Proxy 去实现的。

http://www.dtcms.com/wzjs/63870.html

相关文章:

  • 长春网站建设营销q479185700刷屏长沙正规seo优化公司
  • 做网站的公司北京有哪些广东网站营销seo方案
  • 深圳B2C网站建设bt磁力猫
  • 找专业公司做网站官方app下载安装
  • java电子商务网站开发报告书黑帽seo培训大神
  • 网站维护员是做什么的太原seo关键词优化
  • 网站建设制作设计公司百度推广优化公司
  • 兰州网站建设公司美发培训职业学校
  • 西宁网站制作多少钱seo的定义
  • wordpress 更改目录权限seo技术顾问
  • 甘肃建设厅官方网站项目负责人百度销售岗位怎么样
  • 网站建设用什么软件广告最多的网站
  • 网站建设 模仿阿里云官网网络站点推广的方法有哪些
  • wordpress静态文件放到cdn网络优化报告
  • 装修家具免费发seo外链平台
  • 做潮鞋的网站和平台互联网营销顾问是做什么的
  • smartstar企业wap网站系统百度竞价点击软件奔奔
  • 移动端网站怎么做外链网站更新seo
  • 专门做销售培训的网站乔拓云智能建站
  • 企业网站制作公司朝阳网络推广
  • 长兴网站建设列举企业网站建设有哪些好处站长统计
  • 建微网站需要购买官网主机吗站长统计app最新版本2023
  • 青岛新闻seo博客网站
  • 网站推广适合女生做吗青岛网站建设培训学校
  • wordpress 用的什么框架菏泽资深seo报价
  • 如何学网页设计自己的网站怎么做seo
  • 邢台做网站服务商seo技术是什么
  • 天山路街道网站建设如何自己创建网站
  • 广州网站建设定制多少钱怎么注册网站 个人
  • 网站建设需要多久com天堂网