持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情
setup函数的特性
setup中不能使用this,this指向undefined,在beforeCreate之前执行
setup函数在beforeCreate和created之前执行
setup函数执行于beforeCreate和created之前,也就是说setup函数里面无法使用data和methods方法中的数据。执行顺序如下:
代码如下:
<script>
export default {
name: "App",
beforeCreate() {
console.log("beforeVreate执行");
},
created() {
console.log("created执行");
},
setup() {
console.log("setup执行");
},
};
</script>
在setup函数中定义的变量和方法需要return出去,不然无法在模板中使用
setup中最后适用一个return语句才能使用setup函数中定义的变量和方法,不适用return不会报error,但是无法获得想要获得的变量或者方法,如下图所示,分别是无return和有return语句的示意图:
代码如下:
<script>
import { ref } from "vue"
export default {
name: "App",
setup() {
const name = ref("张三")
console.log("setup执行")
return {
name,
}
},
}
</script>
setup函数是Composition API的入口
**Options API 和 Composition API **
Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 是有所不同的,可以说composition API是vue3.0的一大特点,它不会像 Options API一样,约定了该在哪个位置做什么事,比如说需要在data里面设置变量,在watch里面设置监听属性、在methods里面设置事件方法等,这在一定程度上强制了我们进行代码分割。Composition API就没有这样的约定,代码组织很灵活,代码直接全部都写在setup里面即可。
Options API:
-
props 里面设置接收参数
-
data 里面设置变量
-
computed 里面设置计算属性
-
watch 里面设置监听属性
-
methods 里面设置事件方法
Options APi 约定了我们该在哪个位置做什么事,这反倒在一定程度上也强制我们进行了代码分割。
Composition API:
现在用 Composition API,控制代码写在 setup 里面即可。
setup函数提供了两个参数* props 和 context*,重要的是在 setup 函数里没有了 this,在 vue3.0 中,访问他们变成以下形式: this.xxx => context.xxx
小结:
使用 Composition API 的核心在于将变量和方法抽取到一个模块中,降低代码耦合,提高代码复用率,哪里需要使用在哪里导入即可。可见前文参考中的说明。
期待的代码格式如下:
<script>
import UserA from './A'
import UserB from './B'
export default {
setup() {
// 定义方法
const {A,methodA} = UserA()
const {B,methodB} = UserB()
console.log("setup执行")
return {
A,
methodA,
B,
methodB,
}
},
}
</script>
setup函数定义变量
reactive
Reactive函数接受一个普通对象,返回该对象的响应式代理。reactive定义的变量直接像往常一样取值改值就好,reactive用于定义复杂数据类型,比如数组、对象等,不可用于定义简单的数据类型比如整数类型、布尔类型等类型。
代码如下:
<script>
import { reactive } from "vue";
export default {
setup() {
// 1. setup需要返回值, setup中返回的值才能在模板中使用
// 2. reactive中传入一个普通对象,返回一个代理对象
// 3. 普通对象没有响应式,需要reactive
const car = reactive({
brand: '宝马',
price: 100
})
console.log(car);
return {
car
};
},
};
</script>
输出结果如下:
ref
ref 函数接受一个简单类型的值,返回一个可改变的 ref 对象。返回的对象有唯一的属性 value在 setup 函数中,通过 ref 对象的 value 属性可以访问到值在模板中,ref 属性会自动解套,不需要额外的 .value,如果 ref 接受的是一个对象,会自动调用 reactive
代码如下:
<script>
import { ref } from "vue";
export default {
name: "App",
setup() {
const name = ref("张三");
console.log("setup执行");
console.log("name.value --> " + name.value);
console.log(name);
return {
name,
};
},
};
</script>
输出如下:
toRefs
toRefs 用于将响应式对象转换为结果对象,其中结果对象的每个属性都是指向原始对象相应属性的ref,reactive的响应式功能是赋予给对象的,但是如果给对象解构或者展开的时候,会让数据丢失响应式的能力。使用toRefs可以保证该对象展开的每一个属性都是响应式的。
示例代码:
<script>
import { ref, reactive, toRefs } from "vue";
export default {
setup() {
const state = {
money: 100,
car: {
brand: "宝马",
price: 1000000,
},
name: "zs",
};
console.log(state);
const newState = toRefs(state);
setTimeout(() => {
state.money = 200;
console.log(state, newState);
}, 2000);
return {
state,
...newState,
};
},
};
</script>
结果如下,state中的money由100变成200了,但界面渲染中(视图)的money=100是不变的:
小结:
1、ref是对元数据的拷贝,修改响应式数据时不会影响之前的数据,视图会更新
2、toRef和toRefs是对元数据的引用,修改响应式数据时,元数据也会改变,但是视图不会更新,toRef修改的是对象的某个属性,toRefs修改的是整个对象
3、toRefs的使用场景:如果想让响应式数据和原来的数据关联起来同步更新,并且不更新视图,那么就可以使用toRefs
Vue2.0 --> Vue3.0 的 script 结构变化
vue2.0的script结构
<script>
// 引入组件login、top等
export default {
name: "main",
// 注册组件
components: {
// login,
// top,
// index,
},
beforeCreate(){},
created() {
},
// ...
data() {
return {
// 定义变量
}
},
methods: {
// 定义方法
},
},
}
</script>
vue3.0的script结构,使用setup
错误示例如下,这种方式并没有很好地使用组合式API(Composition API),使用组合式API是为了减小耦合,提高组件的复用,这种方式并没有体现组件的复用,严格意义上不算组合式API的使用。
<script>
export default {
setup() {
const A = ref('')
const methodsA = ()=>{
// todo
}
const B = ref('')
const methodsB = ()=>{
// todo
}
const C = ref('')
const methodsC = ()=>{
// todo
}
},
return: {
A,
methodsA,
B,
methodsB,
C,
methodsC,
},
};
</script>
正确使用组合式API的简单示例如下,将A和methodA提取到一个模块中,使用时导入即可,降低了耦合程度,同时提高了模块的复用率,哪里需要用到直接导入即可,不需要反复编写重复代码。
<script>
import userA from "./mudoleA"
import userB from "./mudoleB"
import userC from "./mudoleC"
export default {
name: "app",
// 注册组件
components: {
// login,
// top,
// index,
},
setup() {
const { A, methodsA } = userA()
const { B, methodsB } = userB()
const { C, methodsC } = userC()
},
return: {
A,
methodsA,
B,
methodsB,
C,
methodsC,
},
}
</script>
vue3.0的setup语法糖形式
这种形式是官方推荐使用的形式,使用这种形式就不用显示的导入并注册组件,比如HelloWorld等,导入即自动注册;也不用显示的导出组件,比如App这个组件,自动导出。同时也不需要使用return语句返回方法和变量,可以直接使用定义的方法和变量。
<script setup>
// vue3.0之后,使用<script setup>这个语法糖,就不用显示的导入并注册组件,比如HelloWorld等,导入即自动注册;也不用显示的导出组件,比如App这个组件,自动导出
import HelloWorld from "./components/HelloWorld.vue";
const props = defineProps({
title:{
type: String,
default: ()=>{ return '测试信息'}
}
})
const { A, methodsA } = userA()
const { B, methodsB } = userB()
const { C, methodsC } = userC()
</script>