组件
自定义组件的意思就是自定义tag标签,这个标签包含着一段html
代码
组件是可复用的 Vue
实例, 说白了就是一组可以重复使用的模板
和 JSTL
的自定义标签、Thymeleaf
的 th:fragment
有着异曲同工之妙,通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
在Vue中,组件是最重要的组合部分,官方中定义组件为可复用的Vue实例,分为全局组件和局部组件,接下来通过实例来分别演示两种不同的组件。
组件的全局注册和局部注册
官方文档:https://cn.vuejs.org/guide/components/registration.html
定义组件
父组件
<script setup>
import MyCounter from "@/components/myCounter.vue";
</script>
<template>
<MyCounter />
</template>
<style scoped>
</style>
子组件
<script setup>
import {ref} from "vue";
const count = ref(0)
</script>
<template>
<button @click="count++">已经点击了 {{ count }} 次</button>
</template>
<style scoped>
</style>
Props
父组件与子组件的 “沟通”
Props官方文档:https://cn.vuejs.org/guide/components/props.html
下面是最简单的prop例子
父组件
<script setup>
import MsgBox from "@/components/msgBox.vue";
</script>
<template>
<MsgBox :msg="'mahe666'" />
</template>
<style scoped>
</style>
子组件
<script setup>
defineProps(['msg'])
</script>
<template>
<p>子组件接收到的消息是:{{msg}}</p>
</template>
<style scoped>
</style>
也可以使用 列表渲染 的方式重复渲染组件
父组件
<script setup>
import MsgBox from "@/components/msgBox.vue";
import {reactive} from "vue";
const arr = reactive(["mahe666", "mahe888", "mahe233"])
</script>
<template>
<MsgBox v-for="item in arr" :msg="item" />
</template>
<style scoped>
</style>
子组件
<script setup>
defineProps(['msg'])
</script>
<template>
<p>子组件接收到的消息是:{{msg}}</p>
</template>
<style scoped>
</style>
监听事件
子组件与父组件的 “沟通”
仅触发事件
父组件
<script setup>
import MsgBox from "@/components/msgBox.vue";
function action(){
alert("HelloWorld")
}
</script>
<template>
<MsgBox @triggerEvent="action()" />
</template>
<style scoped>
</style>
子组件
触发事件并传值
有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让子组件决定父要做什么。这时可以使用 $emit 的第二个参数来提供这个值
然后当在父级组件监听这个事件的时候,我们可以通过 $event
访问到被抛出的这个值
父组件
<script setup>
import MsgBox from "@/components/msgBox.vue";
import {ref} from "vue";
const str = ref("HelloWorld")
</script>
<template>
<MsgBox @triggerEvent="str = $event" />
<p v-text="str"></p>
</template>
<style scoped>
</style>
子组件
<script setup>
</script>
<template>
<!-- 这里不加div会弹出警告 -->
<div>
<button @click="$emit('triggerEvent', 'triggerEvent')">子组件里的按钮</button>
</div>
</template>
<style scoped>
</style>
如果事件处理函数是方法
父组件
<script setup>
import MsgBox from "@/components/msgBox.vue";
import {ref} from "vue";
const str = ref("HelloWorld")
function action(data){
str.value = data
}
</script>
<template>
<MsgBox @triggerEvent="action" />
<p v-text="str"></p>
</template>
<style scoped>
</style>
子组件
<script setup>
</script>
<template>
<!-- 这里不加div会弹出警告 -->
<div>
<button @click="$emit('triggerEvent', 'triggerEvent')">子组件里的按钮</button>
</div>
</template>
<style scoped>
</style>
组件的双向绑定
父组件
<script setup>
import MyButton from "@/components/MyButton.vue";
import {computed, ref} from "vue";
const num = ref(0)
const squareNum = computed(() => {
return num.value ** 2
})
const cubeNum = computed(() => {
return num.value ** 3
})
</script>
<template>
<my-button v-model="num" />
<p>平方值为:{{ squareNum }}</p>
<p>立方值为:{{ cubeNum }}</p>
</template>
<style scoped>
</style>
子组件
<script setup>
const num = defineModel({default: 0})
let emit = defineEmits(['value']);
function action(){
num.value++
emit("value", num)
}
</script>
<template>
<button @click="action">当前数字是 {{ num }}</button>
</template>
<style scoped>
</style>
组合式API 定义组件name属性
相关博客:https://blog.csdn.net/XianZhe_/article/details/134211764