1.props
1.child
<template><div class="child"><h3>子组件</h3><h4>玩具:{{ toy }}</h4><h4>父给的车:{{ car }}</h4><button @click="sendToy(toy)">把玩具给父亲</button></div>
</template><script setup lang="ts" name="Child">import {ref} from 'vue'// 数据let toy = ref('奥特曼')// 声明接收propsdefineProps(['car','sendToy'])
</script><style scoped>.child{background-color: skyblue;padding: 10px;box-shadow: 0 0 10px black;border-radius: 10px;}
</style>
2.father
<template><div class="father"><h3>父组件</h3><h4>汽车:{{ car }}</h4><h4 v-show="toy">子给的玩具:{{ toy }}</h4><Child :car="car" :sendToy="getToy"/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref} from 'vue'// 数据let car = ref('奔驰')let toy = ref('')// 方法function getToy(value:string){toy.value = value}
</script><style scoped>.father{background-color:rgb(165, 164, 164);padding: 20px;border-radius: 10px;}
</style>
2.自定义事件
1.child
<template><div class="child"><h3>子组件</h3><h4>玩具:{{ toy }}</h4><button @click="emit('send-toy',toy)">测试</button></div>
</template><script setup lang="ts" name="Child">import { ref } from "vue";// 数据let toy = ref('奥特曼')// 声明事件const emit = defineEmits(['send-toy'])// emit('send-toy',toy)
</script><style scoped>.child{margin-top: 10px;background-color: rgb(76, 209, 76);padding: 10px;box-shadow: 0 0 10px black;border-radius: 10px;}
</style>
2.father
<template><div class="father"><h3>父组件</h3><h4 v-show="toy">子给的玩具:{{ toy }}</h4><!-- 给子组件Child绑定事件 --><Child @send-toy="saveToy"/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import { ref } from "vue";// 数据let toy = ref('')// 用于保存传递过来的玩具function saveToy(value:string){console.log('saveToy',value)toy.value = value}
</script><style scoped>.father{background-color:rgb(165, 164, 164);padding: 20px;border-radius: 10px;}.father button{margin-right: 5px;}
</style>
3.mitt
1.安装mitt
npm i mitt
//引入mitt
import mitt from "mitt";
//调用mitt得到emitter emiiter能:绑事件,触发事件
const emmiter = mitt();// //绑定事件
// emmiter.on('test1',()=>{
// console.log('test1被调用');// })
// emmiter.on('test2',()=>{
// console.log('test2被调用');// })// console.log('a');// setInterval(()=>{
// console.log('2秒后触发事件');// emmiter.emit('test1');
// emmiter.emit('test2');
// },1000)// setTimeout(()=>{
// console.log('2秒后触发事件');// // emmiter.off('test1');// emmiter.all.clear()
// // emmiter.emit('test2');
// },3000)//暴露emmiter
export default emmiter;
2.father
<template><div class="father"><h3>父组件</h3><Child1/><Child2/></div>
</template><script setup lang="ts" name="Father">import Child1 from './Child1.vue'import Child2 from './Child2.vue'
</script><style scoped>.father{background-color:rgb(165, 164, 164);padding: 20px;border-radius: 10px;}.father button{margin-left: 5px;}
</style>
3.child1
<template><div class="child1"><h3>子组件1</h3><h4>玩具:{{ toy }}</h4><button @click="emitter.emit('send-toy',toy)">玩具给弟弟</button></div>
</template><script setup lang="ts" name="Child1">import {ref} from 'vue'import emitter from '@/utils/emmitter';// 数据let toy = ref('奥特曼')
</script><style scoped>.child1{margin-top: 50px;background-color: skyblue;padding: 10px;box-shadow: 0 0 10px black;border-radius: 10px;}.child1 button{margin-right: 10px;}
</style>
4.child2
<template><div class="child2"><h3>子组件2</h3><h4>电脑:{{ computer }}</h4><h4>哥哥给的玩具:{{ toy }}</h4></div>
</template><script setup lang="ts" name="Child2">import {ref,onUnmounted} from 'vue'import emitter from '@/utils/emmitter';// 数据let computer = ref('联想')let toy = ref('')// 给emitter绑定send-toy事件emitter.on('send-toy',(value:any)=>{toy.value = value})// 在组件卸载时解绑send-toy事件onUnmounted(()=>{emitter.off('send-toy')})
</script><style scoped>.child2{margin-top: 50px;background-color: orange;padding: 10px;box-shadow: 0 0 10px black;border-radius: 10px;}
</style>
4.v-model
1.child
<template><div><!-- <el-inputv-model="input"style="width: 240px"placeholder="Please input"clearable/> --><input type="text" :value="modelValue" @input="emit('update:modelValue',(<HTMLInputElement> $event.target).value)"></div>
</template><script setup lang="ts" name="AtguiguInput">
import { ref } from "vue";defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);</script><style lang="css" scoped>
input {border: 2px solid black;background-image: linear-gradient(45deg, red, yellow, green);height: 30;font-size: 20px;color: white;
}
</style>
2.father
<template><div class="father"><h3>父组件</h3><!-- <input type="text" v-model="username"> --><!-- 双向绑定原理 --><!-- <input type="text" :value="username" @input="username = (<HTMLInputElement> $event.target).value" > --><!-- v-model用在组件标签上 --><AtguiguInput v-model="username" /><!-- 上面那行代码等价下面代码 本质 就是 往下传一个属性 ,一个事件, input改变的同时,触发事件,导致属性更新,有重新渲染模板 -->
<!-- <AtguiguInput :modelValue="username" @update:modelValue="username = $event" /> --></div>
</template><script setup lang="ts" name="Father">import { ref } from "vue";
import AtguiguInput from './AtguiguInput.vue'// 数据let username = ref('zhansgan')let password = ref('123456')
</script><style scoped>
.father {padding: 20px;background-color: rgb(165, 164, 164);border-radius: 10px;
}
</style>
可以写多个
<template><div class="father"><h3>父组件</h3><h4>{{ username }}</h4><!-- <input type="text" v-model="username"> --><!-- 双向绑定原理 --><!-- <input type="text" :value="username" @input="username = (<HTMLInputElement> $event.target).value" > --><!-- v-model用在组件标签上 --><!-- <AtguiguInput v-model="username" /> --><!-- 上面那行代码等价下面代码 本质 就是 往下传一个属性 ,一个事件, input改变的同时,触发事件,导致属性更新,有重新渲染模板 -->
<!-- <AtguiguInput :modelValue="username" @update:modelValue="username = $event" /> --><!-- 修改modelvalue -->
<AtguiguInput v-model:name="username" v-model:pwd ="password"/></div>
</template><script setup lang="ts" name="Father">import { ref } from "vue";
import AtguiguInput from './AtguiguInput.vue'// 数据let username = ref('zhansgan')let password = ref('123456')
</script><style scoped>
.father {padding: 20px;background-color: rgb(165, 164, 164);border-radius: 10px;
}
</style>
5.$attrs
1.father
<template><div class="father"><h3>父组件</h3><h4>a:{{a}}</h4><h4>b:{{b}}</h4><h4>c:{{c}}</h4><h4>d:{{d}}</h4><Child :a="a" :b="b" :c="c" :d="d" v-bind="{x:100,y:200}" :updateA="updateA"/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref} from 'vue'let a = ref(1)let b = ref(2)let c = ref(3)let d = ref(4)function updateA(value:number){a.value += value}
</script><style scoped>.father{background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}
</style>
2.child
<template><div class="child"><h3>子组件</h3><GrandChild v-bind="$attrs"/></div>
</template><script setup lang="ts" name="Child">import GrandChild from './GrandChild.vue'
</script><style scoped>.child{margin-top: 20px;background-color: skyblue;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;}
</style>
3.grandchild
<template><div class="grand-child"><h3>孙组件</h3><h4>a:{{ a }}</h4><h4>b:{{ b }}</h4><h4>c:{{ c }}</h4><h4>d:{{ d }}</h4><h4>x:{{ x }}</h4><h4>y:{{ y }}</h4><button @click="updateA(6)">点我将爷爷那的a更新</button></div>
</template><script setup lang="ts" name="GrandChild">defineProps(['a','b','c','d','x','y','updateA'])
</script><style scoped>.grand-child{margin-top: 20px;background-color: orange;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;}
</style>
6.$refs $parent
1.father
<template><div class="father"><h3>父组件</h3><h4>房产:{{ house }}</h4><button @click="changeToy">修改Child1的玩具</button><button @click="changeComputer">修改Child2的电脑</button><button @click="getAllChild($refs)">让所有孩子的书变多</button><Child1 ref="c1"/><Child2 ref="c2"/></div>
</template><script setup lang="ts" name="Father">import Child1 from './Child1.vue'import Child2 from './Child2.vue'import { ref,reactive } from "vue";let c1 = ref()let c2 = ref()// 注意点:当访问obj.c的时候,底层会自动读取value属性,因为c是在obj这个响应式对象中的/* let obj = reactive({a:1,b:2,c:ref(3)})let x = ref(4)console.log(obj.a)console.log(obj.b)console.log(obj.c)console.log(x) */// 数据let house = ref(4)// 方法function changeToy(){c1.value.toy = '小猪佩奇'}function changeComputer(){c2.value.computer = '华为'}function getAllChild(refs:{[key:string]:any}){console.log(refs)for (let key in refs){refs[key].book += 3}}// 向外部提供数据defineExpose({house})
</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}.father button {margin-bottom: 10px;margin-left: 10px;}
</style>
2.child1
<template><div class="child1"><h3>子组件1</h3><h4>玩具:{{ toy }}</h4><h4>书籍:{{ book }} 本</h4><button @click="minusHouse($parent)">干掉父亲的一套房产</button></div>
</template><script setup lang="ts" name="Child1">import { ref } from "vue";// 数据let toy = ref('奥特曼')let book = ref(3)// 方法function minusHouse(parent:any){parent.house -= 1}// 把数据交给外部defineExpose({toy,book})</script><style scoped>.child1{margin-top: 20px;background-color: skyblue;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;}
</style>
3.child2
<template><div class="child2"><h3>子组件2</h3><h4>电脑:{{ computer }}</h4><h4>书籍:{{ book }} 本</h4></div>
</template><script setup lang="ts" name="Child2">import { ref } from "vue";// 数据let computer = ref('联想')let book = ref(6)// 把数据交给外部defineExpose({computer,book})
</script><style scoped>.child2{margin-top: 20px;background-color: orange;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;}
</style>
7.$provide $inject
1.father
<template><div class="father"><h3>父组件</h3><h4>银子:{{ money }}万元</h4><h4>车子:一辆{{car.brand}}车,价值{{car.price}}万元</h4><Child/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref,reactive,provide} from 'vue'let money = ref(100)let car = reactive({brand:'奔驰',price:100})function updateMoney(value:number){money.value -= value}// 向后代提供数据provide('moneyContext',{money,updateMoney})provide('car',car)</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}
</style>
2.child
<template><div class="child"><h3>我是子组件</h3><GrandChild/></div>
</template><script setup lang="ts" name="Child">import GrandChild from './GrandChild.vue'
</script><style scoped>.child {margin-top: 20px;background-color: skyblue;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;}
</style>
3.grandchild
<template><div class="father"><h3>父组件</h3><h4>银子:{{ money }}万元</h4><h4>车子:一辆{{car.brand}}车,价值{{car.price}}万元</h4><Child/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref,reactive,provide} from 'vue'let money = ref(100)let car = reactive({brand:'奔驰',price:100})function updateMoney(value:number){money.value -= value}// 向后代提供数据provide('moneyContext',{money,updateMoney})provide('car',car)</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}
</style>
8.插槽slot
1.默认插槽
1.child
<template><div class="category"><h2>{{title}}</h2><slot>默认内容</slot></div>
</template><script setup lang="ts" name="Category">defineProps(['title'])
</script><style scoped>.category {background-color: skyblue;border-radius: 10px;box-shadow: 0 0 10px;padding: 10px;width: 200px;height: 300px;}h2 {background-color: orange;text-align: center;font-size: 20px;font-weight: 800;}
</style>
2.father
<template><div class="father"><h3>父组件</h3><div class="content"><Category title="热门游戏列表"><ul><li v-for="g in games" :key="g.id">{{ g.name }}</li></ul></Category><Category title="今日美食城市"><img :src="imgUrl" alt=""></Category><Category title="今日影视推荐"><video :src="videoUrl" controls></video></Category></div></div>
</template><script setup lang="ts" name="Father">import Category from './Category.vue'import { ref,reactive } from "vue";let games = reactive([{id:'asgytdfats01',name:'英雄联盟'},{id:'asgytdfats02',name:'王者农药'},{id:'asgytdfats03',name:'红色警戒'},{id:'asgytdfats04',name:'斗罗大陆'}])let imgUrl = ref('https://z1.ax1x.com/2023/11/19/piNxLo4.jpg')let videoUrl = ref('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}.content {display: flex;justify-content: space-evenly;}img,video {width: 100%;}
</style>
2.具名插槽
1.child
<template><div class="category"><slot name="s1">默认内容1</slot><slot name="s2">默认内容2</slot></div>
</template><script setup lang="ts" name="Category"></script><style scoped>.category {background-color: skyblue;border-radius: 10px;box-shadow: 0 0 10px;padding: 10px;width: 200px;height: 300px;}
</style>
2.father
<template><div class="father"><h3>父组件</h3><div class="content"><Category><template v-slot:s2><ul><li v-for="g in games" :key="g.id">{{ g.name }}</li></ul></template><template v-slot:s1><h2>热门游戏列表</h2></template></Category><Category><template v-slot:s2><img :src="imgUrl" alt=""></template><template v-slot:s1><h2>今日美食城市</h2></template></Category><!-- 语法糖。 简便写法 --><Category><template #s2><video video :src="videoUrl" controls></video></template><template #s1><h2>今日影视推荐</h2></template></Category></div></div>
</template><script setup lang="ts" name="Father">import Category from './Category.vue'import { ref,reactive } from "vue";let games = reactive([{id:'asgytdfats01',name:'英雄联盟'},{id:'asgytdfats02',name:'王者农药'},{id:'asgytdfats03',name:'红色警戒'},{id:'asgytdfats04',name:'斗罗大陆'}])let imgUrl = ref('https://z1.ax1x.com/2023/11/19/piNxLo4.jpg')let videoUrl = ref('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}.content {display: flex;justify-content: space-evenly;}img,video {width: 100%;}h2 {background-color: orange;text-align: center;font-size: 20px;font-weight: 800;}
</style>
3.作用域插槽
1.child
<template><div class="game"><h2>游戏列表</h2><slot :youxi="games" x="哈哈" y="你好"></slot></div>
</template><script setup lang="ts" name="Game">import {reactive} from 'vue'let games = reactive([{id:'asgytdfats01',name:'英雄联盟'},{id:'asgytdfats02',name:'王者农药'},{id:'asgytdfats03',name:'红色警戒'},{id:'asgytdfats04',name:'斗罗大陆'}])
</script><style scoped>.game {width: 200px;height: 300px;background-color: skyblue;border-radius: 10px;box-shadow: 0 0 10px;}h2 {background-color: orange;text-align: center;font-size: 20px;font-weight: 800;}
</style>
2.father
<template><div class="father"><h3>父组件</h3><div class="content"><Game><template v-slot="params"><ul><li v-for="y in params.youxi" :key="y.id">{{ y.name }}</li></ul></template></Game><Game><template v-slot="params"><ol><li v-for="item in params.youxi" :key="item.id">{{ item.name }}</li></ol></template></Game><Game><template #default="{youxi}"><h3 v-for="g in youxi" :key="g.id">{{ g.name }}</h3></template></Game></div></div>
</template><script setup lang="ts" name="Father">import Game from './Game.vue'
</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}.content {display: flex;justify-content: space-evenly;}img,video {width: 100%;}
</style>