一,props父传子
props 可以实现父子组件通信,props数据还是只读的!单向数据流
// 父组件
给子组件添加属性的方式传值
<HelloWorld msg="Vue" />
// 子组件接收
在使用 <script setup> 的单文件组件中,props 可以使用 defineProps() 宏来声明:
defineProps({ msg: String })
在没有使用 <script setup> 的组件中,prop 可以使用 props 选项来声明:
export default {
props: ['msg'], setup(props) {
// setup() 接收 props 作为第一个参数
console.log(props.msg) }
}
二,子传父-自定义事件
// 子组件 在子组件内部通过emit触发事件
let $emit = defineEmits(['changeBtn'])
const handler = () => { $emit('changeBtn', '子组件数据')}
在没有使用 <script setup> 的组件中export default {
emits: ['changeBtn'], setup(props, ctx) {
ctx.emit('changeBtn') }
}
// 父组件
<script setup>
import HelloWorld from './components/HelloWorld.vue'
const changeBtn = (val) => { console.log(val)}
</script>
template>
<HelloWorld msg="Vue" @changeBtn="changeBtn" />
</template>
三,全局事件总线-推荐使用mitt 插件
// 总线 bus文件
import mitt from 'mitt';
const $bus = mitt();
export default $bus
// 兄弟组件1
<script setup>
import $bus from '../bus/index'
const handler = () => { $bus.emit('changeBtn', '兄弟组件数据')}
</script>
<template>
<h1 @click="handler">兄弟组件1</h1>
</template>
// 兄弟组件2
<script setup>
import $bus from '../bus/index'
import { onMounted } from 'vue'
onMounted(() => { $bus.on('changeBtn', (val)=> { console.log(val) })})
</script>
<template>
<h1>兄弟组件2</h1>
</template>
四,v-model 父子组件数据同步
可写多个v-model
// 父组件 - 写法1
<script setup>
import { ref } from "vue"
import HelloWorld from "./components/HelloWorld.vue"
const msg = ref("vue")
</script>
<template>
<HelloWorld v-model="msg" />
</template>
// 父组件 - 写法2
<script setup>
import { ref } from "vue"
import HelloWorld from "./components/HelloWorld.vue"
const msg = ref("vue")
</script>
<template>
<HelloWorld v-model:msg="msg" />
</template>
// 子组件
// 默认值 -- modelValue
// 1
<script setup>
defineProps(['modelValue'])
const $emit = defineEmits(['update:modelValue'])
const handel = ()=> { $emit('update:modelValue',123)}
</script>
<template>
<h1 @click="handel">{{ modelValue }}</h1>
</template>
// 2
<script setup>
defineProps(['msg'])
const $emit = defineEmits(['update:msg'])
const handel = ()=> { $emit('update:msg',123)}
</script>
<template>
<h1 @click="handel">{{ msg }}</h1>
</template>
新版>>> defineModel
<script setup>
import { defineModel } from 'vue'
const modelValue = defineModel()
</script>
五,useAttrs
可以获取组件标签身上的属性和事件
props和useAttrs都可以获取,如果用props接收了,则useAttrs就接收不到了
// 父组件
<script setup>
import { ref } from "vue"
import HelloWorld from "./components/HelloWorld.vue"
const msg = ref("vue")
const change = () => { alert("vue")}
</script>
<template>
<HelloWorld type="error" :title="msg" @click="change" />
</template>
// 子组件
<script setup>
import { useAttrs } from "vue"
const $attrs = useAttrs()
const props = defineProps(["title"])
</script>
<template>
<div :="$attrs">12345678</div>
</template>
六,ref和$parent
ref可以获取真实的dom节点,可以获取到子组件实例
$parent可以在子组件内获取父组件的实例
组件内部数据是对外关闭的,想让外部访问可通过defineExpose方法对外暴露
// 父组件
<script setup>
import { ref } from "vue"
import HelloWorld from "./components/HelloWorld.vue"
const msg = ref("vue")
defineExpose({msg})
const son = ref()
const onChange = () => { console.log(son) }</script><template> <HelloWorld ref="son" /> <div @click="onChange">按钮</div></template>
// 子组件
<script setup>
import { ref } from "vue"
const money = ref(10000)
const onChange = ($parent) => { console.log($parent)}
// 组件内部数据是对外关闭的,想让外部访问可通过defineExpose方法对外暴露
defineExpose({money})
</script>
<template>
<div @click="onChange($parent)">111111</div>
</template>
七,provide-inject
// 父组件
<script setup>
import { ref, provide } from "vue"
import child from "./components/HelloWorld.vue"
const msg = ref("vue")
provide("msg", msg)
</script>
<template>
<child />
</template>
// 子组件
<template>
<div>儿子组件</div>
<grandson />
</template>
<script setup>
import { inject } from "vue"
import grandson from "./grandson.vue"
const msg = inject("msg")
console.log("儿子组件", msg)
</script>
// 孙子组件
<template>
<div>孙子组件</div>
</template>
<script setup>
import { inject } from "vue"
const msg = inject("msg")
console.log("孙子组件", msg)
</script>
八,pinia
1,选项式 API
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
2,组合式 API
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})