- 父传子 props方式
- 子传父 emit方式
- 子传父 v-model方式
- 子传父 ref方式
- provide/inject
- 子组件传子组件 借助插件mitt
- pinia 仓库
父传子 props方式
1.给子组件绑定属性
2.子组件用props接受并加入自己的数据源
父组件
<template>
<div class="parent-wrap">
<input type="text" v-model="value" class="form-control" placeholder="请输入">
<div class="inpt-group-append">
<button class="btn btn-primary" @click="handle">添加</button>
</div>
</div>
<childVue :list="list"></childVue> //1.给子组件绑定属性list
</template>
<script>
import childVue from './child.vue'
import { reactive, toRefs } from '@vue/reactivity'
export default {
components:{
childVue
},
setup(){
const state=reactive({
value:'',
list:['javascrpit','html','css']
})
const handle=()=>{
state.list.push(state.value)
state.value=''
}
return {
...toRefs(state),
handle
}
}
}
</script>
子组件
<template>
<ul class="list-group">
<li class="list-group-item" v-for="item in list" :key="item">
{{item}}
</li>
</ul>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
export default {
props:{ //2.子组件用props接受并加入自己的数据源
list:Array
},
setup(props,ctx){
const state=reactive({
list:props.list,
},
)
return{
...toRefs(state)
}
}
}
</script>
效果
父组件输入你好点添加 子组件列表会出现
子传父 emit方式
子组件
- emits:['toList'], 声明toList事件
- ctx.emit('toList',state.list) 抛出事件toList
<template>
<div class="parent-wrap">
<input type="text" v-model="value" class="form-control" placeholder="请输入">
<div class="inpt-group-append">
<button class="btn btn-primary" @click="handle">添加</button>
</div>
</div>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
export default {
emits:['toList'], //1
setup(props,ctx){
const state=reactive({
value:'',
list:['javascrpit','html','css']
})
const handle=()=>{
ctx.emit('toList',state.list) //2
}
return {
...toRefs(state),
handle
}
}
}
</script>
父组件
- @toList="toList" 绑定事件
- const toList=(list)=>{ list就是传过来的值 state.list=list}
<template>
<childVue @toList="toList"></childVue> //3
<ul class="list-group">
<li class="list-group-item" v-for="item in list" :key="item">
{{item}}
</li>
</ul>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
import childVue from './child.vue'
export default {
components:{
childVue
},
setup(){
const state=reactive({
list:[]
},
)
const toList=(list)=>{ //4
state.list=list}
return{
...toRefs(state),
toList
}
}
}
</script>
子传父 v-model方式
1.在父传子props基础上 给子组件绑定属性时加v-model: 2.子组件从props收到的数据修改,然后update抛出,这样父组件数据也改变了 3.切记不能直接拿着props.list修改 会变成双向数据流,改变vue单向数据流初衷,并且把握不住数据源流转
父组件
<template>
<childVue v-model:list="list"></childVue> //111111111111111111111111111
<ul class="list-group">
<li class="list-group-item" v-for="item in list" :key="item">
{{item}}
</li>
</ul>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
import childVue from './child.vue'
export default {
components:{
childVue
},
setup(){
const state=reactive({
list:['javascrpit','html','css']
},
)
return{
...toRefs(state),
}
}
}
</script>
子组件
<template>
<div class="parent-wrap">
<input type="text" v-model="value" class="form-control" placeholder="请输入">
<div class="inpt-group-append">
<button class="btn btn-primary" @click="handle">添加</button>
</div>
</div>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
export default {
emits:['update:list'], //4.定义update:list 固定语法 list是父组件传过来的
props:[
'list'
],
setup(props,ctx){
const state=reactive({
value:'',
})
const handle=()=>{
const arr=props.list //2.获取父组件数据
arr.push(state.value) //3.修改后的数据arr
ctx.emit('update:list',arr) //5.ctx.emit('update:list',arr)
}
return {
...toRefs(state),
handle
}
}
}
</script>
子传父 ref方式
父组件直接拿到子组件dom结构获取数据
1.ref="childref"
2. const childref=ref(null)
3. v-for="item in childref?.list" :key="item"
父组件
<template>
<childVue ref="childref"></childVue> //1111111111111111111111111
<ul class="list-group">
<li class="list-group-item" v-for="item in childref?.list" :key="item">//33333333333333
{{item}}
</li>
</ul>
</template>
<script>
import { reactive, ref, toRefs } from '@vue/reactivity'
import childVue from './child.vue'
export default {
components:{
childVue
},
setup(){
const childref=ref(null) //222222222222222222222222222222
const state=reactive({
list:''
},
)
return{
...toRefs(state),
childref
}
}
}
</script>
子组件
子组件含有数据源list
<template>
<div class="parent-wrap">
<input type="text" v-model="value" class="form-control" placeholder="请输入">
<div class="inpt-group-append">
<button class="btn btn-primary" @click="handle">添加</button>
</div>
</div>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
export default {
setup(props,ctx){
const state=reactive({
value:'',
list:['javaScript','html','css']
})
const handle=()=>{
}
return {
...toRefs(state),
handle
}
}
}
</script>
provide/inject api传值 只能外层向里传父传子,优点是不管嵌套多深都能传值
父组件
-
import { provide ,readonly} from 'vue' //父组件引入 -
provide('list',readonly(state.list)) //父组件在setup里面传 randonly(只读,怕子组件对父组件修改) -
import { inject } from 'vue' //子组件引入api -
state.list= inject('list') //子组件在setup接受
<template>
<div class="parent-wrap">
<input type="text" v-model="value" class="form-control" placeholder="请输入">
<div class="inpt-group-append">
<button class="btn btn-primary" @click="handle">添加</button>
</div>
</div>
<childVue></childVue>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
import { provide ,readonly} from 'vue'
import childVue from './child.vue'
export default {
components:{
childVue
},
setup(props,ctx){
const state=reactive({
value:'',
list:['javaScript','html','css']
})
provide('list',readonly(state.list)) //111111111111111
const handle=()=>{
}
return {
...toRefs(state),
handle
}
}
}
</script>
子组件
<template>
<ul class="list-group">
<li class="list-group-item" v-for="item in list" :key="item">
{{item}}
</li>
</ul>
</template>
<script>
import { reactive, ref, toRefs } from '@vue/reactivity'
import childVue from './child.vue'
import { inject } from 'vue'
export default {
components:{
},
setup(){
const state=reactive({
list:[],
},
)
state.list= inject('list') //22222222222222222222222222222
return{
...toRefs(state),
}
}
}
</script>
子组件传子组件 借助插件mitt 像vue2中的eventbus
1. npm install --save mitt
2. 创建bus.js文件
import mitt from 'mitt'
const emitter = mitt()
export default emitter
3. 子组件1引入并抛出值
add是名字,state.value是值
import emitter from './bus'
emitter.emit('add',state.value) (在setup里面接收)
4. 子组件2引入并接收值
add是名字,e是接收的参数
import emitter from './bus'
emitter.on('add',(e)=>{
state.list.push(e)
})
pinia 仓库 相当于vue2中的vuex
- npm install pinia查看pinia文档
2.在src 创建store文件夹和index.js文件
index.js代码如下
import { createPinia } from 'pinia'
const store = createPinia()
export default store
main.js引入
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
createApp(App).use(store).mount('#app')
3.index同级再定义一个文件 index是仓库 新定义出来文件的像是仓库分类出来的一块区域
user.js区域仓库代码如下
import { defineStore } from 'pinia'
export const useStore = defineStore('main', { //userStore是区域名 任取
id:'user',
state(){
return {
//数据源
name:'papapiu'
}
}
})
4.现在可以拿到页面去用(区域仓交互跟拿到页面去用一样,引入,调用拿到区域上下文对象,直接访问)
import {useStore} from '../store/user.js'//饮热
const userStore=useStore()//useStore调用结果就是取出来的厂库区域(上下文对象) 可以在页面userStore.name访问
5.组件通信时,可以将任一组件数据写一个区域仓库,任一组件都可以拿得到。