1、props
? ? ? ? 作用:子組件之間的通信。
父傳子:屬性值的非函數。
子傳父:屬性值是函數。
? ? ? ?父組件:
<template><div>{{ childeData }}</div>——————————————————————————————<child :parentData="parentData" :sendData="getChildData"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child from './childeIndex.vue'const childeData=ref("");
const parentData=ref("parentData");function getChildData(data:string){childeData.value=data;
}</script>
? ? ? ? 子組件:
<template><div>{{ parentData }}</div><button @click="sendData(data)"></button>
</template>
<script setup lang="ts" name="child">
import { ref } from 'vue'
defineProps(['parentData','sendData'])const data=ref('aaa')</script>
2、自定義事件
? ? ? ? 通過父組件定義函數,子組件調用父組件的函數來實現參數的傳遞。
????????父組件:
<template><div>{{ childeData }}</div>——————————————————————————————<child @send-toy="getChildData"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child from './childeIndex.vue'const childeData=ref("");function getChildData(data:string){childeData.value=data;
}</script>
? ? ? ? 子組件:
<template><div>子組件</div><button @click="sendDat"></button>
</template>
<script setup lang="ts" name="child">import { ref } from 'vue'let data=ref('我是子組件')const emit = defineEmits(['send-toy'])function sendDat(){emit('send-toy',data)}</script>
3、mitt
????????實現任意組件的通信。個人理解:在組件與組件之間提供了一個平臺,都向這個平臺發送、讀取數據。
安裝步驟:
- npm i mitt
- 新建文件utiles/emitter.ts
- 在需要的文件中引入emitter,進行綁定 事件,或調用事件。
- ?在文件中進行解綁(unmounted中)
? ? ? ?emitter.ts
import mitt from 'mitt'
const emitter=mitt()
export default emitter
? ? ? ? 獲取數據的文件
<template><h2>child2中的數據:{{ src }}</h2>
</template>
<script setup lang="ts" name="child1">import { onUnmounted, ref } from 'vue'import emitter from '@/utils/emitter'const src=ref('')//監聽事件emitter.on('getData',(data:string)=>{src.value=data})//在組件銷毀時取消監聽onUnmounted(()=>{emitter.off('getData')})
</script>
? ? ? ? 發送數據的文件
<template><h2>child2的數據:{{ data }}</h2><button @click="getdata"> 點擊獲取數據 </button>
</template>
<script setup lang="ts" name="child2">import { ref } from 'vue'import emitter from '@/utils/emitter'const data = ref('222')function getdata(){emitter.emit('getData',data)}
</script>
4、v-model
? ? ? ? 原理:實現雙向綁定,通過傳遞props參數實現父傳子,通過emit傳遞input或者點擊事件實現子傳父。
? ? ? ? 父組件:
<template><!-- 這個寫法的本質就是下面那種 --><input type="text" v-model="str"/><input type="text" :value="str" @input="str=(<HTMLInputElement>$event.target).value"/><!-- 自定義組件,一二種方法一致 --><selfInput v-model="str"></selfInput><!-- 此處的$event就是傳遞的數據 --><selfInput :modelValue="str" @update:modelValue="str=$event"></selfInput></template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import selfInput from './selfInput.vue';let str = ref('');
</script>
? ? ? ? 自定義組件(selfInput.vue):
<template><input type="text" :value="modelValue" @input="emit('update:modelValue',($event.target as HTMLInputElement).value)"/>
</template>
<script setup lang="ts" >
import { ref,defineProps,defineEmits } from 'vue';defineProps(['modelValue'])const emit = defineEmits(['update:modelValue'])</script>
如果自定義自定義組件中的名稱,可以實現多個組件的雙向綁定。
? ? ? ? 父組件:
<template>{{ str }} --------{{ pass }}<selfInput v-model:name="str" v-model:pass="pass"></selfInput>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import selfInput from './selfInput.vue';let str = ref('');
let pass = ref('');
</script>
? ? ? ? 子組件:
<template><input type="text" :value="name" @input="emit('update:name',($event.target as HTMLInputElement).value)"/><input type="text" :value="pass" @input="emit('update:pass',($event.target as HTMLInputElement).value)"/>
</template>
<script setup lang="ts" >
import { ref,defineProps,defineEmits } from 'vue';defineProps(['name','pass'])const emit = defineEmits(['update:name','update:pass'])</script>
5、$attrs
? ? ? ? 作用:適用于當前組件,向子組件通信(祖-->孫)。
當父組件給子組件傳遞參數,且子組件沒有使用props進行接收時,所傳遞的參數存在attrs中。在子組件中使用$attrs就可以獲取所有未被接收的數據。
? ? ? ? 父組件:
<template><div>{{ a }}</div><hr/><div>{{ b }}</div><hr/><div>{{ c }}</div><hr/><child v-bind="{a,b,c}" @changeA="changeA"></child>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child from './chile.vue';
let a=ref(1);
let b=ref(2);
let c=ref(3);
function changeA(value:number){a.value=value;
}
</script>
? ? ? ? 子組件:
<template><div>{{ a }}</div><hr/>--------------------------------<sun v-bind="$attrs"></sun>
</template>
<script setup lang="ts" name="chile">import sun from './sun.vue'defineProps(['a'])
</script>
? ? ? ? 孫組件:
<template><div>{{ b }}</div><hr/><div>{{ c }}</div><hr/><button @click="changeAa">修改a</button>
</template>
<script setup lang="ts" >const num=defineProps(['b','c']);const emit=defineEmits(['changeA']);function changeAa(){emit('changeA',num.b);}
</script>
6、$refs、$parent
? ? ? ? $refs:用于父組件修改子組件中的數據。獲取所有子組件暴露的數據。
$parent:用于子組件修改父組件的數據。獲取父組件所有暴露的數據。
????????以上的前提:使用defineExpose暴露數據。
? ? ? ? 父組件:
<template><h1>父組件數據</h1><h1>{{ a }}</h1><button @click="changeChildeA($refs)">修改子組件數據</button><br/>--------------------------------<child1 ref="child1"/>--------------------------------<child2 ref="child2"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref } from 'vue';
import child1 from './childe1.vue';
import child2 from './childe2.vue';
let a=ref(1);
function changeChildeA(refs:any){refs.child1.b++;refs.child2.b++;
}
defineExpose({a})
</script>
? ? ? ? 子組件1:
<template> <h1>子組件數據</h1><h1>a:{{ a }}</h1><h1>b:{{ b }}</h1><button @click="changeParent($parent)">修改父組件的a</button>
</template>
<script setup lang="ts" >
import { ref } from 'vue'
let a=ref(1)
let b=ref(1)
function changeParent(parent:any){parent.a++
}
//暴露
defineExpose({b
})
</script>
? ? ? ? 子組件2:
<template> <h1>子組件數據</h1><h1>a:{{ a }}</h1><h1>b:{{ b }}</h1>
</template>
<script setup lang="ts" >
import { ref } from 'vue'
let a=ref(1)
let b=ref(1)//暴露
defineExpose({a,b
})
</script>
7、provide、inject
? ? ? ? 作用:實現祖孫組件之間的數據傳遞。
傳遞數據:provide(“數據名稱”,數據)。
接收數據:inject(“數據名稱”,默認值)。
? ? ? ? 父組件:
<template><h1>父組件數據</h1><h1>{{ a }}</h1>--------------------------------<child1 ref="child1"/>
</template>
<script setup lang="ts" name="parentIndex">
import { ref,provide } from 'vue';
import child1 from './childe1.vue';let a=ref(0);
function changeA(value:number){a.value+=value;
}provide("parent",{a:a,changeA})</script>
? ? ? ? 子組件:
<template> <h1>子組件數據</h1><h1>a:{{ a }}</h1><div><button @click="changeA(1)">更改父組件的a</button></div>
</template>
<script setup lang="ts" >
import { ref,inject } from 'vue'
let {a,changeA} = inject('parent',{a:ref(0),changeA:function(x:number){}})
</script>
8、插槽
? ? ? ? 作用:引入組件時可以給組件傳遞一些HTML元素。? ? ? ??
默認插槽
? ? ? ? 父組件中引入子組件時,子組件標簽內部的元素就是會傳入slot的參數。
子組件中的slot就相當于占位符,給未來傳進來的元素預留空位。
? ? ? ? 父組件:
<template><h1>父組件數據</h1><div class="child"><child1 :title="'第一個'"><div style="color: aqua;">1111111111</div></child1><child1 :title="'第二個'"><div style="color:black;">22</div></child1></div>
</template>
<script setup lang="ts" name="parentIndex">
import child1 from './childe.vue';
</script>
<style scoped>
? ? ? ? 子組件:
<div class="child"><h1 style="color: black;">{{ title }}</h1><slot>默認值</slot></div></template>
<script setup lang="ts" >defineProps(['title'])
</script>
具名插槽
? ? ? ? 作用:可以指定元素插入的位置。
用法:在定義插槽位置時,使用name屬性定義其名字。
在應用組件時,在其標簽或Templet標簽內部定義v-slot(或使用#+名字)屬性。
? ? ? ? 父組件:? ? ??
<template><h1>父組件數據</h1><div class="child"><child1 :title="'第一個'"><template #b><div style="color: aqua;">1111111111</div></template></child1><child1 :title="'第二個'"><template #a><div style="color:black;">22</div></template></child1></div>
</template>
<script setup lang="ts" name="parentIndex">
import child1 from './childe.vue';
</script>
? ? ? ? 子組件:
<template> <div class="child"><h1 style="color: black;">{{ title }}</h1><slot name="a">默認值</slot><h1>-------------分隔符--------------------</h1><slot name="b">默認值</slot></div></template>
<script setup lang="ts" >defineProps(['title'])
</script>
作用域插槽
? ? ? ? 作用:當父組件需要子組件的數據。
用法:在定義slot標簽時,使用props寫法進行傳遞參數。
在父組件中使用v-slot拿到參數。
如果同時使用了具名插槽:v-slot:name=‘parms’? ? ? ? ? ? ? ?
? ? ? ? 父組件:
<template><h1>父組件數據</h1><div class="child"><child1 :title="'第一個'"><template #a="{game,a}"><ul><li v-for="item in game" :key="item.id">{{ item.name }}</li></ul></template></child1></div>
</template>
<script setup lang="ts" name="parentIndex">
import child1 from './childe.vue';
</script>
? ? ? ?子組件:
<template> <div class="child"><h1 style="color: black;">{{ title }}</h1><slot name="a" :game="game" :a="a">默認值</slot></div></template>
<script setup lang="ts" >
import { reactive } from 'vue'; defineProps(['title'])const game=reactive([{id:1,name:'a'},{id:2,name:'b'},])const a=1;
</script>