Vue中官网是这么介绍组件的:组件允许我们将UI划分为独立的、可重用的部分,并且对每个部分进行单独的思考
如果一个文件包含四五个组件,那么他们之间的数据通信如何解决呢,所以组件中数据通信是Vue中非常重要的知识
//父组件
<template>
<div>
这是父组件
div>
<child :state=state :ParentFn=ParentFn>child>
template>
<script setup lang="ts">
import { ref } from 'vue';
import child from "./components/index.vue"
const state = ref<string>('这是父组件的state')
const ParentFn =() => {
console.log('这是父组件的方法')
}
script>
//子组件
<template>
<div>这是子组件div>
<div>这是父组件传过来的值{{ props.state}}div>
<button @click="props.ParentFn">触发父组件方法button>
template>
<script lang="ts" setup>
const props = defineProps({
state: String,
ParentFn:Function,
})
script>
attrs:包含父作用域里除 class 和 style 除外的非 props 属性集合//父组件
<template>
<child :msg1="msg1" :msg2="msg2" title="good">child>
template>
<script setup>
import child from "./components/index.vue"
import { ref, reactive } from "vue"
const msg1 = ref(1)
const msg2 = ref(2)
script>
//子组件
<template>
<div>{{attrs}}div>
template>
<script lang="ts" setup>
import {useAttrs} from "vue"
defineProps({
msg1: Number
})
const attrs = useAttrs()
console.log(attrs) //{ "msg2": 2, "title": "good" }
script>
//子组件第二种使用方式
//将父组件传递的所有非 prop 属性绑定到子组件的元素上
<template>
<div v-bind="$attrs">div>
template>
//父组件
//子组件
这是子组件
ref绑定在子组件上可以在父组件中来访问子组件的实例
在子组件使用defineExpose暴露方法或变量
//父组件
<template>
<div> 这是父组件div>
<div> 这是子组件的数据{{childRef?.state }}div>
<button @click="childRef!.fnFromChild">触发子组件button>
<child ref="childRef">child>
template>
<script setup lang="ts">
import { ref } from 'vue';
import child from "./components/index.vue"
const childRef = ref<null | {state:string,fnFromChild:Function}>(null)
script>
//这是子组件
<template>
<div>这是子组件div>
template>
<script lang="ts" setup>
import { ref } from 'vue';
const state = ref<string>("hello")
const fnFromChild = () => {
console.log('这是子组件的方法')
}
defineExpose(
{
state,
fnFromChild
}
)
script>
v-model: 在子组件直接修改父组件数据
//这是父组件
<template>
<div> 这是父组件{{ params }}div>
<child v-model="params">child>
template>
<script setup lang="ts">
import { ref } from 'vue';
import child from "./components/index.vue"
const params = ref<string>('1')
script>
//这是子组件
<template>
<div>这是子组件{{ modelValue }}div>
template>
<script lang="ts" setup>
defineProps({
modelValue: String
})
//实现了父传子
script>
// 实现子组件修改父组件数据
<template>
<div>这是子组件{{ modelValue }}div>
<button @click="updateValue">子组件的方法 改变父组件数据button>
template>
<script lang="ts" setup>
defineProps({
modelValue: String
})
const emit = defineEmits(["update:modelValue"])
const updateValue = () => {
emit("update:modelValue","我是父组件的值 我被子组件改变的")
}
script>
v-model在组件上使用双向绑定
defineModel()其实就是上述例子的语法糖defineModel() 返回的值是一个 ref, 它的 .value 和父组件的 v-model 的值同步
⚠️ 注意
如果为 defineModel prop 设置了一个 default 值且父组件没有为该 prop 提供任何值,会导致父组件与子组件之间不同步
//父组件
<template>
<div> 这是父组件{{ count}}div>
<child v-model="count">child>
template>
<script setup lang="ts">
import { ref } from 'vue';
import child from "./components/index.vue"
const count= ref<number>(1)
script>
//子组件
<template>
<div>这是子组件{{ model}}div>
<button @click="update">子组件的方法 改变父组件数据button>
template>
<script lang="ts" setup>
const model = defineModel({default : 1})
function update() {
model.value++
}
script>
组件上的 v-model 也可以接受一个参数
//父组件
<child v-model:title="bookTitle" />
//子组件
<script setup>
const title = defineModel('title')
script>
<template>
<input type="text" v-model="title" />
template>
多个v-model绑定
//父组件
<child v-model:first-name="first" v-model:last-name="last" />
//子组件
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
script>
<template>
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
template>
用于提供可以被后代组件注入的值
这个组件库用的多些,因为组件库不知道你会在哪使用它提供的值
//先代组件
<script setup>
import { ref, provide } from 'vue'
import { countSymbol } from './injectionSymbols'
// 提供静态值
provide('path', 'good')
// 提供响应式的值
const count = ref(0)
provide('count', count)
// 提供时将 Symbol 作为 key
provide(countSymbol, count)
script>
//后代组件
<script setup>
import { inject } from 'vue'
import { countSymbol } from './injectionSymbols'
// 注入不含默认值的静态值
const path = inject('path')
// 注入响应式的值
const count = inject('count')
// 通过 Symbol 类型的 key 注入
const count2 = inject(countSymbol)
// 注入一个值,若为空则使用提供的默认值
const bar = inject('path', '/default-path')
script>
接下来贴一波日常使用的代码
创建文件夹stroe
创建文件index.ts
//这样引入方便pinia使用插件比如
// 比如持久化 pinia.use(piniaPluginPersistedstate)
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
//在main.ts中
import pinia from '@/stores'
app.use(pinia)
创建文件user.ts
import { defineStore } from 'pinia'
import { UserState } from '@/stores/interface'
export const useUserStore = defineStore('Oner-user', {
state: (): UserState => ({
token: '',
userInfo: { name: 'Oner' },
userVerify: '',
currentPage: 0,
}),
getters: {},
actions: {
// Set Token
setToken(token: string) {
this.token = token
},
// Set setUserInfo
setUserInfo(userInfo: UserState['userInfo']) {
this.userInfo = userInfo
},
setUserVerify(verify: string) {
this.userVerify = verify
},
setCurrentPage(value: number) {
this.currentPage = value
},
},
})
在任意组件中使用
const userStore = useUserStore()
console.log(userStore.token) // ''
console.log(userStore.setToken("zhaimoudetoken"))
console.log(userStore.token) // zhaimoudetoken
文章到这里就结束了,希望对你有所帮助。