一、自定义事件
事件名:
与组件和 prop 一样,事件名提供了自动的大小写转换。如果在子组件中触发一个以 camelCase (驼峰式命名) 命名的事件,你将可以在父组件中添加一个 kebab-case (短横线分隔命名) 的监听器。
定义自定义事件:
(1)可以通过 emits
选项在组件上定义发出的事件
父组件:
<HomeView @my-event="fn"></HomeView>
子组件:
<template>
<button @click="fn">点我触发mybtn组件内部的myclick事件</button>
</template>
<script>
export default {
emits:["myEvent","myclick"],
methods:{
fn(){
this.$emit("myClick",20)
},
fm(){
this.$emit("click",30)
}
}
}
</script>
(2) v-model
参数
子组件:
//1.接收参数
props:["title"]
//2.定义事件
emits: ['update:title']
//3.触发事件
this.$emit("update:title","子组件传递给父组件的值")
在Vue3中v-model也可以绑定多个
父组件:
<user-name v-model:msg1="msg1" v-model:msg2="msg2"></user-name>
子组件:
//1.接收参数
props:["msg1","msg2"]
//2.定义事件
emits: ['update:msg1','update:msg2']
//3.触发事件
this.$emit('update:msg1',"子组件传递给父组件的值1")
this.$emit('update:msg2',"子组件传递给父组件的值2")
二、状态驱动的动态 CSS
单文件组件的 <style>
标签可以通过 v-bind
这一 CSS 函数将 CSS 的值关联到动态的组件状态上
<script setup>
import {ref} from "vue"
let color = ref("skyblue")
let change = () => {
color.value = "green"
}
</script>
<template>
<div>
<div class="box">hello</div>
<button @click="change">change</button>
<Box1></Box1>
</div>
</template>
<style scoped>
.box {
color: v-bind(color);
}
</style>
三、注册组件
(1)vue3组件内部组合式API setup语法糖中注册组件
<script setup>
import Box1 from "./Box1.vue"
//只需要导入 不用写注册代码 会在打包的时候自动帮我们注册
</script>
<template>
<Box1></Box1>
< /template>
(2)注册全局组件
main.js文件中:
import { createApp} from 'vue'
import App from './App.vue'
const app=createApp(App)
import Box1 from "./Box.vue"
app.component(Box1.name,Box1)
app.mount('#app')//注意 一定要在app.mount之前注册全局组件 否则使用不了
然后再app.vue中就可以直接使用Box1组件
(3)定义同步组件:
Box1组件内:
<script>
import {defineComponent} from "vue"
export default defineComponent({
data(){
return {}
},
setup(){
}
});
</script>
(4)定义局部异步组件:
a.组件内部:
<script>
import {defineAsyncComponent} from "vue"
let Box1 = defineAsyncComponent(() => import("./Box1.vue")) //注意3.2之后不用引入defineAsyncComponent
export default {
components: {
Box1
},
setup() {}
}
</script>
b.setup语法糖:
<script setup>
import Box1 from "./Box1.vue"
import {defineAsyncComponent} from "vue"
let Box3=defineAsyncComponent(()=>import("./Box3.vue"))
//注意3.2之后不用引入defineAsyncComponent,而且这个变量名直接就是注册的组件名(打包时自动注册的)
</script>
(5)定义全局异步组件:
main.js文件中:
import { createApp,defineAsyncComponent} from 'vue'
import App from './App.vue'
const app=createApp(App)
let Box1=defineAsyncComponent(()=>import("./Box4.vue"))
app.component("Box1",Box1)
app.mount('#app')//注意 一定要在app.mount之前注册全局组件 否则使用不了
四、Suspense占位组件
等待异步组件时渲染一些额外的内容,让应用有更好的用户体验
<suspense>
组件有两个插槽。它们都只接收一个直接子节点。default
插槽里的节点会尽可能展示出来。如果不能,则展示 fallback
插槽里的节点。
<script setup>
import {defineAsyncComponent} from "vue"
let Box3 = defineAsyncComponent(() =>import("./Box3.vue"))
</script>
<template>
<div>
<suspense>
<template #default>
<Box3></Box3>
</template>
<template #fallback>
<h1>loading...</h1>
</template>
</suspense>
</div>
</template>
五、isRef、toRef、toRefs、readonly
(1)isRef 判断是否为响应性变量,返回值为boolear类型
<script setup>
import {ref,isRef} from "vue"
let msg=ref(10)
function fn(){
console.log(isRef(msg)) //判断是否为响应性变量
}
< /script>
(2)toRef 把引用数据的属性值设置为变量 并且关联和设置为响应性变量
toRefs 引用数据响应式解构
<script setup>
import {
reactive,
isRef,
toRef,
toRefs
} from "vue"
let obj = reactive({
name: "xiaozhang",
age: 21
})
// toRef()转换
let name = toRef(obj, "name")
let age = toRef(obj, "age")
// toRefs()转换
// let {name,age} = toRefs(obj)
let change1 = () => {
console.log(isRef(name));
name.value = "xiaoliao"
}
function change2() {
console.log(isRef(age));
age.value = 22
}
</script>
<template>
<div>
<p>{{name}}</p>
<p>{{age}}</p>
<button @click="change1">changename</button>
<button @click="change2">changeage</button>
</div>
</template>
<style scoped>
</style>
(3)readonly 把数据变为只读功能
import {isRef,reactive,toRef,toRefs,readonly} from "vue"
let obj = reactive({
name: "xiaozhang",
age: 21
})
let obj2=readonly({obj}) //obj2就只能读,而不能操作数据