今天项目中,在vant的弹窗组件popup中又增加了一层作为子组件,实现了弹窗的自定义。父组件Father将数据传递给Child。props:{showDialog:Boolean}props是一个代理对象。子组件可以将props.showDialog转换为计算属性。constvisible=computed({get:()=>props.showDialog,set:newVal=>{context.emit('toggleStatus',newVal)}})不过今天主要是看看ref做了什么。接下来分为两部分:setuphook中refDOM节点的ref属性1.refsetup(props,context){const{showDialog}=toRefs(props)constvisible=ref(showDialog)watch中setuphook(()=>visible.value,newVal=>{context.emit('toggleStatus',newVal)})return{visible,}}对象结构会使其无响应,toRefs包裹的对象可以避免这种情况.子组件创建一个可见变量来控制弹出组件是否显示。使用ref接收showDailog属性并返回响应式和可变的ref对象。然后通过监听visible.value值的变化,触发父组件showDialog更新值。嗯,看起来与源的反应性连接已保持!我的子组件一定会收到父亲的更新!但是这样做有一个问题。控制台很快会报出??reactivity.esm-bundler.js:336Setoperationonkey"showDialog"failed:targetisreadonly。Proxy{showDialog:true}toRefs文档原文:将响应式对象转换为普通对象,其中result对象的每个属性都是一个ref,指向原始对象对应的属性。那么,showDailog是如何变成ref对象的呢?toRefs方法遍历其参数对象,为对象的每个值添加__v_isRef=true属性:_key:K){}getvalue(){returnthis._object[this._key]}setvalue(newVal){this._object[this._key]=newVal}}__v_isRef将此对象标记为ref对象。接下来我们看一下ref方法的作用。导出函数ref(value?:unknown){returncreateRef(value)}functioncreateRef(rawValue:unknown,shallow=false){if(isRef(rawValue)){returnrawValue}returnnewRefImpl(rawValue,shallow)}refreceiveshowDailog,判断为ref对象时,返回自身。弹窗组件关闭时直接给visible赋值false,其实是在挑战props的readonly属性。控制台警告并拒绝执行您的任务。这种情况下,初始化visible为false,然后监听showDialog触发visible。constvisible=ref(false)consttoggle=(newVal:boolean)=>(visible.value=newVal)watch(()=>showDialog.value,newVal=>{toggle(newVal)})watch(()=>visible.value,newVal=>{console.log('visible=------',visible)context.emit('toggleStatus',newVal)})问题还没有结束。如果ref函数接收到的参数不是ref对象怎么办?换句话说,newRefImpl(rawValue,shallow)是做什么的?classRefImpl
