一、setup:组合API
ref是一个函数,用于定义一个响应式的数据,返回的是一个ref对象,对象中有一个value属性,如果需要对数据进行操作,需要使用该ref对象调用value属性的方式进行数据操作。
一般用来定义一个基本类型的响应式数据。
const count=ref(0)
const update=()=>{
count.value++
}
update()
二、定义变量:
1、const / let声明变量
声明后必须初始化赋值,如:const name='aaa',不可以 const name;
2、reactive和ref(响应式)
ref可以定义基本数据类型或对象类型的响应式数据
import { ref } from "vue";
const name= ref('张三')
console.log(name);
reactive只能定义对象类型的响应式数据(一般定义数组和对象)
import { reactive } from "vue";
const user = reactive({
id: 1,
name: "张三",
age: 20,
});
console.log(user.name);
ref创建的变量必须使用.value
ref 有.value属性,reactive没有
3、修改数据
①修改reactive定义的对象
// 1、如果obj和newObj的键值对不一致 先清空obj再赋值
Object.keys(obj).forEach(key => {
delete obj[key]
})
Object.assign(obj,newObj);
// 2、如果一致
Object.assign(obj,newObj);
②修改reactive定义的数组
// 先清空数组再赋值,防止arr中的数据遗留
arr.length = 0 ;
Object.assign(arr,newArr)
③清空reactive定义的数组
arr.length = 0
④修改reactive定义的数组
// 先清空数组再赋值,防止arr中的数据遗留
arr.length = 0 ;
Object.assign(arr,newArr)
// 使用数组的操作方法(必须是可以改变原数组的方法)
pageList.push(...arr)
三、computed计算属性:
计算属性有缓存,方法没有缓存
计算属性函数中如果只传一个回调函数,表示的是get
计算属性中有set和get方法
import { reactive, ref, computed } from "vue";
const user = reactive({
firstName: "东方",
lastName: "不败",
});
// vue3中的计算属性
// 计算属性函数中如果只传一个回调函数,表示的是get
const fullName = computed(() => {
return user.firstName + "_" + user.lastName;
});
// 返回get和set方法
const fullName2 = computed({
get() {
return user.firstName + "_" + user.lastName;
},
set(val: string) {
user.firstName = val.split("_")[0];
user.lastName = val.split("_")[1];
},
});
四、watch监视:监视指定的数据
watch可以监视多个数据,当我们使用watch监视非响应式数据的时候,需要改成箭头函数的形式
watch([() => user.firstName, () => user.lastName, fullName3], () => {
console.log("-----");
});
作用:监视数据的变化(和vue2中watch作用一致)
只能监视以下4种数据:
1、ref定义的数据
2、reactive定义的数据(监视reactive定义的对象类型数据,默认是开启深度监视的)
3、函数返回一个值
4、一个包含上述内容的数组
immediate:初始化默认会执行一次watch
deep:深度监视
watch(
user,
({ firstName, lastName }) => {
fullName3.value = firstName + "-" + lastName;
},
{ immediate: true, deep: true }
);
停止监视:stopWatch()
五、watchEffect监视:
不需要配置immediate,本身就会默认监视,默认会执行一次
watchEffect(() => {
fullName3.value = user.firstName + "-" + user.lastName;
});
六、toRefs:
toRefs可以把一个响应式对象转换成普通对象,该普通对象每个property都是一个ref
ref的另一个作用:可以获取页面中的元素
七、生命周期-钩子函数:
onBeforeMount(() => {});
onMounted(() => {});
onBeforeUpdate(() => {});
onUpdated(() => {});
onBeforeUnmount(() => {});
onUnmounted(() => {});
八、组件通信
1、props(父传子)
props可以实现父子组件通信,在vue3中我们可以通过defineProps获取父组件传递的数据,且在组件内部不需要引入defineProps方法可以直接使用
父组件中:
<template>
<div class="box">父组件</div>
<Child title="传给子组件" :msg="msg"></Child>
</template>
<script setup lang="ts">
import Child from "./Child.vue";
const msg = "一条消息";
</script>
子组件中接收:
- 需要使用defineProps方法去接受父组件传递过来的数据
- defineProps是vue3提供的方法
- props的数据是只读的
<template>
<div class="son">子组件--{{ title }}--{{ msg }}</div>
</template>
<script setup lang="ts">
let props = defineProps(["title", "msg"]);
console.log(props);
</script>
2、自定义事件
原生DOM事件
原生的DOM事件不管是放在标签身上,还是放在组件标签身上都是原生DOM事件
<template>
<div>
<Son2 @click="handler"></Son2>
</div>
</template>
<script setup lang="ts">
import Son2 from "./Event2.vue";
const handler = () => {
console.log('9999999');
}
</script>
自定义事件
如果子组件定义了自定义事件,原生DOM事件就不会触发
父组件中:
<template>
<div>
<Event @change="getMsg"></Event>
</div>
</template>
<script setup lang="ts">
import Event from "./Event1.vue";
const getMsg = (data) => {
console.log(data);
};
</script>
子组件中使用defineEmits方法返回的函数触发的自定义事件:
第一个参数是事件类型,之后的参数就是要传递的数据
<template>
<div class="son">这是子组件</div>
<button @click="handel">点击触发自定义事件</button>
</template>
<script setup lang="ts">
let emit = defineEmits([]);
const handel = () => {
emit("change", "改变后的值");
};
</script>
3、全局事件总线(兄弟组件传值)
全局事件总线可以实现任意组件通信,Vue3中使用全局事件总线功能可以使用插件mitt实现
npm i mitt
在src目录下新建bus文件夹,在index.ts中引入mitt插件:mitt一个方法,方法执行会返回bus对象
import mitt from 'mitt';
const $bus = mitt();
export default $bus;
兄弟组件一:
<template>
<div>
<div class="box">这是子组件1</div>
<button @click="handle">点击给兄弟传值</button>
</div>
</template>
<script setup lang="ts">
import $bus from "../../bus";
// 点击回调
const handle = () => {
$bus.emit("send", { msg: "一句话" });
};
</script>
兄弟组件二:
<template>
<div>
<div class="box">这是子组件2</div>
<div>{{ msg2 }}</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import $bus from "../../bus";
const msg2 = ref("");
// 组合式API函数
import { onMounted } from "vue";
// 组件挂载完毕的时候,当组件绑定一个事件,接收将来兄弟组价传递的数据
onMounted(() => {
// 第一个参数是事件类型,第二个参数是时间回调
$bus.on("send", (msg) => {
console.log(msg);
msg2.value = msg.msg;
});
});
</script>
4、v-model
v-model指令:收集表单数据,数据双向绑定
v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
父传子:props
子传父:自定义事件
父组件中:
<template>
<div>
<div>父组件:{{ msg }}</div>
<!-- <Child :modelValue="msg" @change:modelValue="handel"></Child> -->
<!--
v-model在组件身上使用
第一:相当于给组件传递props[modelValue]
-->
<Child v-model="msg" @change:modelValue="handel"></Child>
<hr />
<Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
</div>
</template>
<script setup lang="ts">
// v-model收集表单数据,实现实现双向数据绑定
// v-model也可实现组件数据通信,父子组件数据同步
import { ref } from "vue";
import Child from "./Child.vue";
import Child1 from "./Child1.vue";
// 父组件数据
let msg = ref("这是父组件数据");
// 自定义事件的回调
const handel = (data) => {
// 接收子组件传递过来的数据
msg.value = data;
// console.log(data);
};
// 父组件数据
const pageNo = ref(4);
const pageSize = ref(10);
</script>
子组件中:
<template>
<div>
<div>子组件:{{ modelValue }}</div>
<button @click="handel">点击传递数据给父组件</button>
</div>
</template>
<script setup lang="ts">
// 接收props
let props = defineProps(["modelValue"]);
let $emit = defineEmits(["change:modelValue"]);
// 子组件内部按钮的点击回调
const handel = () => {
$emit("change:modelValue", "改变后的数据");
};
</script>