一、依赖注入
依赖注入就是祖先组件向后代组件传递数据,使用 provide()和 inject()函数来实现
这两个函数只能在 setup()函数中使用
在祖先组件中使用 provide()函数向下传递数据
在后代组件中使用 inject()函数获取上层传递传递过来的数据
// 父组件
<template>
<div class="hello">
<h1> 父组件 </h1>
<son></son>
<button @click="colorRef='red'"> 红 </button>
<button @click="colorRef='yellow'"> 黄 </button>
<button @click="colorRef='blue'"> 蓝 </button>
</div>
</template>
<script>
import {provide,ref} from 'vue'
import son from './son.vue'
export default {setup(){
// 向后代传数据 不会响应式更新
provide('color','yellow');
// 传递响应式的数据
let colorRef = ref('red')
provide('colorRef',colorRef);
return{colorRef}
},
components: {son}
}
</script>
// 子组件
<template>
<div class="son">
<h1> 子组件 </h1>
<grandson></grandson>
</div>
</template>
<script>
import grandson from './grandson.vue'
export default {setup(){ },
components: {grandson}
}
</script>
// 孙子组件
<template>
<div class="grandson">
<h1 :style="{color:color}"> 孙组件 1 </h1>
<h1 :style="{color:colorRef}"> 孙组件 1 </h1>
</div>
</template>
<script>
import {inject} from 'vue'
export default {setup(){const color = inject('color');
const colorRef = inject('colorRef');
return {
color,
colorRef
}
}
}
</script>
二、模板 Refs
通过 ref()函数还可以引用页面上的元素或组件
步骤:
1、在 setup()中创建一个 ref()对象并返回
2、在页面上为元素添加 ref 属性,并设置属性值与创建的 ref 对象的名称相同
3、当前页面渲染完成后(onMounted),可以通过该 ref 对象获取到页面中对应的 dom 元素
//refs.vue
<template>
<div>
<h1 ref="hRef"> 这是一段文字,需要获取 </h1>
<hr>
<compRefs ref="comRef" :onChanges="onChanges"></compRefs>
</div>
</template>
<script>
import {ref,onMounted} from 'vue'
import compRefs from './compRef.vue'
export default {setup(){
// 创建一个值为 null 的 ref 对象并返回
const hRef = ref(null);
// 获取组件
const comRef = ref(null);
// 在页面渲染完成后
onMounted(()=>{console.log(hRef.value) //DOM 对象
console.log(comRef.value) //DOM 对象
hRef.value.style.color = 'red'
comRef.value.onChange(); // 父组件调用子组件方法})
let onChanges = ()=>{hRef.value.innerHTML = 'hello'}
return{
hRef,
comRef,
onChanges
}
},
components:{compRefs}
}
</script>
//compRefs.vue
<template>
<div>
<p>{{msg}}</p>
<button @click="childMethod"> 点击 </button>
</div>
</template>
<script>
import {ref,onMounted} from 'vue'
export default {
props:{onChanges: Function},
setup(props){const msg = ref('welcome');
let onChange = ()=>{msg.value += 'hello'}
let childMethod = ()=>{console.log(props)
props.onChanges(); // 子组件调用父组件方法}
onMounted(()=>{})
return{
msg,
onChange,
childMethod
}
}
}
</script>
三、响应式系统工具集
1、isRef
检查一个值是否为一个 ref 对象。
import{ref,reactive,isRef} from 'vue'
export default {setup(){let num = ref(5);
let single = 5;
let obj = reactive({age:5})
let numFlag = isRef(num); //true
let singleFlag = isRef(single); //false
let objFlag = isRef(obj); //false
return{
numFlag,
singleFlag,
objFlag
}
},
}
2、isReactive
检查一个对象是否是由 reactive 创建的响应式代理。
import{ref,reactive,isReactive} from 'vue'
export default {setup(){let num = ref(5);
let single = {num:5};
let obj = reactive({age:5})
let numFlag = isReactive(num); //false
let singleFlag = isReactive(single); //false
let objFlag = isReactive(obj); //true
return{
numFlag,
singleFlag,
objFlag
}
},
}
3、isReadonly
检查一个对象是否是由 readonly 创建的只读代理。
import {ref,reactive,isReadonly,readonly} from 'vue'
export default {setup(){let num = ref(5);
let single = readonly({name:'tom'});
let obj = reactive({age:5})
let numFlag = isReadonly(num); //false
let singleFlag = isReadonly(single); //true
let objFlag = isReadonly(obj); //false
return{
numFlag,
singleFlag,
objFlag
}
},
}
4、isProxy
检查一个对象是否是由 reactive 还是 readonly 方法创建的代理。
import {ref,reactive,isProxy,readonly} from'vue'
export default {setup(){let num = ref(5);
let single = readonly({name:'tom'});
let obj = reactive({age:5})
let numFlag = isProxy(num); //false
let singleFlag = isProxy(single); //true
let objFlag = isProxy(obj); //true
return{
numFlag,
singleFlag,
objFlag
}
},
}
5、unref
如果参数是一个 ref 则返回它的 value,否则返回参数本身。它是 val = isRef(val) ? val.value : val 的语法糖。注意:unref 都是小写的
import {ref,reactive,unref,readonly} from 'vue'
export default {setup(){let num = ref(5);
let single = readonly({name:'tom'});
let obj = reactive({age:5})
let numFlag = unref(num); //5
let singleFlag = unref(single); //{name:'tom'}
let objFlag = unref(obj); //{age:5}
return{
numFlag,
singleFlag,
objFlag
}
},
}
6、toRef
用来为一个 reactive 对象的属性创建一个 ref。这个 ref 可以被传递并且能够保持响应性,可以被传递。
<template>
<div>
<p>obj:{{obj.num}}</p>
<p>objFlag:{{objFlag}}</p>
<button @click="onChange"> 修改 num</button>
</div>
</template>
<script>
import {reactive,toRef} from 'vue'
export default {setup(){
let obj = reactive({
age:5,
num:1
})
// 只能是 reactive 对象中的一个属性
let objFlag = toRef(obj,'num');
const onChange = ()=>{
objFlag.value = 10;
console.log(obj.num) //10
console.log(objFlag.value) //10
}
return{
objFlag,
obj,
onChange
}
},
}
</script>
7、toRefs
用来将 reactive 对象转换为一个普通对象,但该普通对象的每个 属性都是一个 ref,并且这个 ref 具有响应式,可以被传递。
<template>
<div>
<p>obj:{{obj.name}}</p>
<p>obj:{{obj.num}}</p>
<p>objFlag:{{objFlag}}</p>
<button @click="onChange"> 修改 num</button>
</div>
</template>
<script>
import {reactive,toRefs} from 'vue'
export default {setup(){
let obj = reactive({
name:'tom',
num:1
})
let objFlag = toRefs(obj);
const onChange = ()=>{
objFlag.name.value = 'Json';
objFlag.num.value = 10;
console.log(obj.num) //10
console.log(obj.name) //Json
}
return{
objFlag,
obj,
onChange
}
},
}
</script>
欢迎关注公众号(web 学习吧),一起学习进步: