简介
Vue3 最大的一个变动应该就是推出了 CompositionAPI,可以说它受ReactHook 启发而来;它我们编写逻辑更灵活,便于提取公共逻辑,代码的复用率得到了提高,也不用再使用 mixin 担心命名冲突的问题。
ref 与 reactive 是 Vue3
新推出的主要 API
之一,它们主要用于响应式数据的创建。
reactive
能做的,ref
都能胜任,并且 ref
底层还是使用 reactive
来做的!!!
ref
函数可以接收原始数据类型与引用数据类型
reactive
函数只能接收引用数据类型。
当你明确知道需要包裹的是一个对象,那么推荐使用 reactive,其他情况使用 ref 即可
reactive包装函数
<template>
<div>
<!-- 案列1 -->
<button @click="myClick">点我</button>
<div>{{ obj.name }}--{{ obj.age }}</div>
<div>{{ obj2.email }}</div>
<!-- <div>{{ obj3 }}</div> -->
<hr>
<!-- 列表案列 -->
<ul>
<li v-for="item in obj.datalist" :key="item">{{ item }}</li>
</ul>
<!-- 模糊查询案列 -->
<input type="text" v-model="obj.mytitle">
<ul>
<li v-for="item in GetSelectItems()" :key="item">{{ item }}</li>
</ul>
</div>
</template>
<script>
import { reactive } from 'vue';
export default {
setup() {
//用reactive是一个包装函数,包装后就得到了一个响应式对象obj (setup中可以存在多个reactive,只是正常情况下一个就够用了,比如下面的obj 和obj2)
//注意const是申明常量的,常量不是不可变的吗?为什么还可以通过obj.name = "李四"来改变它呢?
//其实obj只是reactive({name: "张三",age: 29})这个对象的一个引用(指针),obj不能再进行修改,只是说obj不能再指向其他的对象了,例如:obj="aaa"就会报错,因为obj所指向对象的引用已经变化了。
//但是obj指向的这个对象它本身的属性是可以修改的,所以 obj.name = "李四"不会报错
const obj = reactive({
name: "张三",
age: 29,
datalist: ["aaa", "bbb", "ccc"],
mytitle: ""
})
const obj2 = reactive({ email: "abc@qq.com" })
//const obj3=reactive("张三"); //reactive不支持这种简单类型的包装,它只支持复杂类型的包装,如对象,数组等。
//const obj3=reactive(""); //reactive不支持这种简单类型的包装
//const obj3=reactive(1); //reactive不支持这种简单类型的包装
const myClick = () => {
obj.name = "李四"
}
const GetSelectItems = () => {
//includes() 方法用于判断字符串是否包含指定的子字符串
//filter方法是过滤方法, item表示当前遍历datalist数组的项,如果当前项包含了input中输入的值,则找出来,然后统一返回一个数组
var selectIitemArr = obj.datalist.filter(item => item.includes(obj.mytitle))
return selectIitemArr;
}
//所有的函数与对象都需要在return中进行返回
//obj,myClick是定义在setup中的,它只能在setup中使用,为了在setup外面使用(例如DOM中)我们就必须要把他们暴露出去,就需要放到return中进行返回
return {
obj, //等同于obj:obj
obj2,
obj3,
myClick, //返回myClick
GetSelectItems,
}
}
}
</script>
ref包装函数
<template>
<div>
<!-- 案列1 -->
<button @click="myClick">点我</button>
<div>{{ obj.name }}--{{ obj.age }}</div>
<div>{{ obj2.email }}</div>
<div>{{ obj3 }}</div>
<div>{{ obj4 }}</div>
<div>{{ obj5 }}</div>
<div>{{ obj6?"中国":"美国" }}</div>
<hr>
<!-- 列表案列 -->
<ul>
<li v-for="item in obj.datalist" :key="item">{{ item }}</li>
</ul>
<!-- 模糊查询案列 -->
<input type="text" v-model="obj.mytitle">
<ul>
<li v-for="item in GetSelectItems()" :key="item">{{ item }}</li>
</ul>
</div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
setup() {
//用reactive是一个包装函数,包装后就得到了一个响应式对象obj (setup中可以存在多个reactive,只是正常情况下一个就够用了,比如下面的obj 和obj2)
//注意const是申明常量的,常量不是不可变的吗?为什么还可以通过obj.name = "李四"来改变它呢?
//其实obj只是ref({name: "张三",age: 29})这个对象的一个引用(指针),obj不能再进行修改,只是说obj不能再指向其他的对象了,例如:obj="aaa"就会报错,因为obj所指向对象的引用已经变化了。
//但是obj指向的这个对象它本身的属性是可以修改的,所以 obj.value.name = "李四"不会报错
const obj = ref({
name: "张三",
age: 29,
datalist: ["aaa", "bbb", "ccc"],
mytitle: ""
})
const obj2 = ref({ email: "abc@qq.com" })
const obj3=ref("王五"); //ref支持这种简单类型的包装 原理就是new Proxy({value:"王五"}) 注意:在DOM模板中使用{{obj3}} 在<script>中使用需要在后面加.value 如:obj3.value
const obj4=ref(""); //ref支持这种简单类型的包装 原理就是new Proxy({value:""})
const obj5=ref(1); //ref支持这种简单类型的包装 原理就是new Proxy({value:1})
const obj6=ref(true);
const myClick = () => {
obj.value.name = "李四"
}
const GetSelectItems = () => {
//特别注意:经过ref包装函数包装的对象,在<script>中必须要在对象名称后面.value ,在DOM模板中则不需要.value
// 比如:
// obj.value.name; 获取obj对象中的name值
// obj.value.age; 获取obj对象中的age值
// obj.value.datalist; 获取obj对象中的datalist值
// obj.value.mytitle; 获取obj对象中的mytitle值
//includes() 方法用于判断字符串是否包含指定的子字符串
//filter方法是过滤方法, item表示当前遍历datalist数组的项,如果当前项包含了input中输入的值,则找出来,然后统一返回一个数组
var selectIitemArr = obj.value.datalist.filter(item => item.includes(obj.value.mytitle))
return selectIitemArr;
}
//所有的函数与对象都需要在return中进行返回
//obj,myClick是定义在setup中的,它只能在setup中使用,为了在setup外面使用(例如DOM中)我们就必须要把他们暴露出去,就需要放到return中进行返回
return {
obj, //等同于obj:obj
obj2,
obj3,
obj4,
obj5,
obj6,
myClick, //返回myClick
GetSelectItems,
}
}
}
</script>
reactive与ref共存
<template>
<div>
<!-- 案列1 -->
<button @click="myClick">点我</button>
<div>{{ obj.name }}--{{ obj.age }}</div>
<div>{{ obj2.email }}</div><hr>
<!-- 可以直接用mydata -->
<ul>
<li v-for="item in mydata" :key="item">{{ item }}</li>
</ul>
<!-- 也可以将mydata放到reactive包装函数中然后通过obj对象来用 -->
<ul>
<li v-for="item in obj.mydata" :key="item">{{ item }}</li>
</ul>
<ul>
<li v-for="item in mylist.mydata" :key="item">{{ item }}</li>
</ul>
<div>{{mylist.obj.name}}</div>
</div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
setup() {
//有一种情况就是通过import导入的组件(JS)中存在用ref包装的,而我们当前组件组件用的是reactive包装的,为了保持风格统一(当然不统一也行)我们也可以将ref中的包装对象直接放到reactive包装函数中:
//举列:
const mydata = ref([1, 2, 3]);//我们可以直接用mydata,也可以将mydata放到reactive包装函数中
const obj = reactive({
name: "张三",
age: 29,
datalist: ["aaa", "bbb", "ccc"],
mytitle: "",
mydata //也可以将ref包装函数包装的对象mydata放到reactive包装函数中
})
const mylist=ref({
mydata,
obj //也可以将reactive包装函数包装的对象obj放到ref包装函数中
})
const obj2 = reactive({ email: "abc@qq.com" })
return {
obj, //等同于obj:obj
obj2,
mydata,
mylist
}
}
}
</script>