setup()
函数是一个新的组件选项,作为组件中 Composition API 的起点。setup()
会在 beforeCreate
钩子函数之前执行。setup()
中不能执行 this
,this
指向 undefined。<template>
<div>app</div>
</template>
<script>
export default {
setup() {
console.log("setup执行了");
},
beforeCreate() {
console.log("beforeCreate执行了");
},
};
</script>
reactive
函数接受一个普通对象,返回该对象的响应式代理。
<template>
<div>{{ arr.title }}{{ arr.num }}</div>
<button @click="arr.num++">修改</button>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
let arr = reactive({
title: "名称",
num: 100,
});
return {
arr,
};
},
};
</script>
ref
函数接受一个简单类型的值,返回一个可改变的 ref
对象,返回的对象有唯一的属性 value
。setup()
函数中,通过 ref
对象的 value
属性可以访问到值。ref
属性会自动解套,不需要额外的 .value
。ref
接受的是一个对象,会自动调用 reactive
。<template>
<div>{{ title }}</div>
<button @click="title = '名称2'">修改</button>
</template>
<script>
import {ref} from 'vue'
export default {
setup() {
let title = ref("名称1");
return {
title,
};
},
};
</script>
property
都是一个 ref
。reactive
的响应式功能都是赋予给对象的,但是如果给对象结构或者展开的时候,会让数丢失响应式的能力。toRefs
可以保证该对象展开的每一个属性都是响应式的。<template>
<div>{{ mame }}</div>
<div>{{ arr.title }}{{ arr.num }}</div>
<button @click="mame = 'ls'">修改</button>
<button @click="arr.num++">修改</button>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
setup() {
let state = reactive({
mame: "zs",
arr: {
title: "名称",
num: 100,
},
});
return {
...toRefs(state),
};
},
};
</script>
ref
,返回一个原始对象的只读代理。<template>
<div>{{ num }}</div>
<button @click="num++">修改</button>
</template>
<script>
import { ref, readonly } from "vue";
export default {
setup() {
let num = ref(100);
return {
num: readonly(num),
};
},
};
</script>
computed
函数用于创建一个计算属性。getter
函数,会返回一个不允许修改的计算属性。getter
和 setter
函数的对象,会返回一个允许修改的计算属性。<template>
<div>今年年龄:<input v-model="age" /></div>
<div>明年年龄:<input v-model="nextAge" /></div>
<div>后年年龄:<input v-model="nextAge2" /></div>
</template>
<script>
import { ref, computed } from "vue";
export default {
setup() {
let age = ref(19);
// 计算属性
// 1.传入一个函数 getter ,返回一个不允许修改的计算属性
let nextAge = computed(() => {
return parseInt(age.value) + 1;
});
// 2.传入一个对象,包括get和set,可以创建一个可以被修改的计算属性
let nextAge2 = computed({
get() {
return parseInt(age.value) + 2;
},
// 接收一个参数,当前的值
set(value) {
age.value = value - 2;
},
});
return {
age,
nextAge,
nextAge2,
};
},
};
</script>
watch
函数接收3个参数:ref
或者 getter
函数。immediate
和 deep
。{deep:true}
深度监听{immediate:true}
立即监听watch
可以监听一个 ref
或者一个带有返回值的 getter
函数。watch
可以监听单个数据源,也可以监听多个数据源。watch
函数会有返回值,用于停止监听。<template>
<div>数据1:{{ num1 }}</div>
<button @click="num1++">按钮1</button>
<br />
<div>数据2:{{ num2 }}</div>
<button @click="num2++">按钮2</button>
<br />
<div>数据3:{{ arr.title }}</div>
<button @click="arr.title = '奔驰'">按钮3</button>
</template>
<script>
import { reactive, ref, toRefs, watch } from "vue";
export default {
setup() {
let state = reactive({
num1: 100,
arr: {
title: "宝马",
},
});
let num2 = ref(100);
// 监听一个state中的值
watch(
() => state.num1,
(newValue, oldValue) => {
console.log("数据1发生变化", newValue, oldValue);
}
);
// 监听一个单独的数据
watch(num2, (newValue, oldValue) => {
console.log("数据2发生变化", newValue, oldValue);
});
// 监听一个state中的对象
watch(
() => state.arr,
(newValue) => {
console.log("数据3发生变化", newValue);
},
{
deep: true,
immediate: false,
}
);
// 监听多个值
watch(
[() => state.arr, num2],
([newArr, newNum]) => {
console.log("数据4发生变化", newArr, newNum);
},
{
deep: true,
}
);
// 监听整个state
watch(
state,
(newValue) => {
console.log("state变化了", newValue);
},
{ deep: true }
);
return {
...toRefs(state),
num2,
};
},
};
</script>
setup()
期间同步使用。beforCreate
> 使用 setup()
created
> 使用setup()
beforeMount
> onBeforeMount
mounted
> onMounted
beforeUpdate
> onBeforeUpdate
update
> onUpdate
beforeDestroy
> onBeforeUnmount
destroyed
> onUnmounted
errorCaptured
> onErrorCaptured
为了获得对模板内元素和组件实例的引用,我们可以像往常一样在 setup()
中声明一个 ref
并返回它。
<template>
<div ref="hRef">模板ref</div>
</template>
<script>
import { ref, onMounted } from "vue";
export default {
setup() {
let hRef = ref(null);
onMounted(() => {
console.log(hRef.value.innerHTML);
});
return {
hRef,
};
},
};
</script>
https://v3.cn.vuejs.org/guide/component-provide-inject.html
provide
和 inject
提供依赖注入,用于实现组件之间的通讯。类似于Vue2中的 provide
和 inject
。provide
和 inject
可以用于跨多级组件进行通讯。祖级组件:
<template>
<div>这是祖级组件:{{ num }}</div>
<button @click="num++">修改</button>
<br /><br />
<Child></Child>
</template>
<script>
import { ref, provide } from "vue";
import Child from "./Child.vue";
export default {
components: {
Child,
},
setup() {
let num = ref(100);
// 后代组件调用的方法
let changeNum = (v) => {
// v : 后代组件传递过来的值
num.value = v;
};
// 向后代级组件提供属性
provide("num", num);
provide("changeNum", changeNum);
return {
num,
};
},
};
</script>
子组件
<template>
<div>这是子组件:{{ num }}</div>
<br /><br />
<Grand></Grand>
</template>
<script>
import { inject } from "vue";
import Grand from "./Grand.vue";
export default {
components: {
Grand,
},
setup() {
// 接受父组件传过来的值
let num = inject("num");
return {
num,
};
},
};
</script>
孙子组件:
<template>
<div>这是孙子组件:{{ num }}</div>
<button @click="fn">修改</button>
</template>
<script>
import { inject } from "vue";
export default {
setup() {
// 接受祖级组件传过来的值
let num = inject("num");
// 修改祖级组件中的数据
let changeNum = inject("changeNum");
let fn = () => {
// 传参改变祖级组件中的数据
changeNum(200);
};
return {
num,
fn,
};
},
};
</script>