门户网站建设公司咨询,免费制作自己的微网站吗,在市场部做网站多少工资,企业网站托管电话文章目录 一、props二、自定义事件三、mitt四、v-model1.v-model的本质2.v-model用在组件标签上3.更换modelValue4.更换modelValue时#xff0c;可以在组件标签上多次使用v-model 五、$attrs六、$refs,与#xffe5;parent1. 回顾标签ref属性修改组件信息2. $refs实现父修改所… 文章目录 一、props二、自定义事件三、mitt四、v-model1.v-model的本质2.v-model用在组件标签上3.更换modelValue4.更换modelValue时可以在组件标签上多次使用v-model 五、$attrs六、$refs,与parent1. 回顾标签ref属性修改组件信息2. $refs实现父修改所有子组件信息3. $parent实现子修改父 七、provide、inject祖孙通信1. 祖传孙2. 孙传祖 八、pinia,见之前的博客九、插槽slot1. 默认插槽2. 具名插槽3. 作用域插槽 组件通信总结 一、props
概述props是使用频率最高的一种通信方式常用与 父传子。
若 父传子属性值是非函数。若 子传父属性值是函数。
父传子
!--父组件--
Child :carcar /
scriptlet car ref(奔驰)
/script!--子组件接收数据--h4父亲给的车{{ car }}/h4scriptdefineProps([car])
/script子传父: 需要父提前给子传递函数通过参数接收子传递的数据
!--父组件--h4 v-iftoy子组件给的玩具{{ toy }}/h4Child :carcar :sendToysendToy /
scriptlet toy ref()function sendToy(value: string) {toy.value value}
/script!--子组件传递数据--
button clicksendToy(toy)把玩具给子组件/button
script setup langts nameChildimport { ref } from vuelet toy ref(奥特曼)defineProps([car, sendToy])
/script二、自定义事件
触发事件的语法 let emit defineEmits([函数名])// 触发事件emit(函数名,需要传递的参数)举例
!--父组件自定义事件send-toy--h4 v-showtoy子组件传递过来的玩具{{ toy }}/h4Child send-toygetToy /
scriptlet toy ref()function getToy(value: string) {toy.value value}
/script!--子组件接收数据--
!--触发send-toy事件父组件进而调用了getToy函数并收到了参数toy--button clickemit(send-toy, toy)玩具给父组件/buttonscriptlet toy ref(奥特曼)// 接收之后,emit(send-toy)就是在触发事件let emit defineEmits([send-toy])
/scriptemit接收两个事件
let emit defineEmits([a,b])触发时
emit(a)
emit(b)三、mitt
消息订阅pubsub全局事件总线$bus,mitt都是一样的思想。 接收数据的提前绑好事件(提前订阅消息) 提供数据的在合适的时候触发事件(发布消息)
安装mittnpm i mitt新建文件src\utils\emitter.ts// 引入mitt
import mitt from mitt;// 创建emitter
const emitter mitt()// 创建并暴露mitt
export default emitter绑定事件emitter.on(事件名,(){回调函数逻辑 }) 触发事件emitter.emit(事件名,传递的参数) 解绑事件emitter.off(事件名) 解绑所有事件emitter.all.clear() 接收数据的组件绑定事件在组件卸载前解绑事件 发送数据的组件触发事件
四、v-model
UI 组件库大量使用v-model进行通信。
1.v-model的本质 !-- v-model双向绑定用在html标签上 --input typetext v-modelusername!-- 上边代码的本质是 --!-- :valueusername实现数据到页面input...实现页面到数据--input typetext :valueusername inputusername (HTMLInputElement$event.target).value(HTMLInputElement$event.target).value其实就是$event.target.value,因为ts语法的限制需要加断言。
2.v-model用在组件标签上
!-- 修改modelValue --
ChildInput v-modelusername /
!-- 本质是默认写modelValue也可以修改修改见第3点更换modelValue --
ChildInput :modelValueusername update:modelValueusername $event /:modelValueusernameprops实现父传子 update...类似于自定义事件实现子传父$event是子组件传过来的值
ChildInput 组件中
template!--将接收的modelValue值赋给input元素的value属性目的是为了呈现数据 --!--给input元素绑定原生input事件触发input事件时进而触发update:model-value事件触发时将$event.target.value通过参数传回去--input typetext :valuemodelValueinputemit(update:modelValue, (HTMLInputElement$event.target).value)
/templatescript setup langts nameChildInput
// 接收父组件传递的值
defineProps([modelValue])
// 声明事件
let emit defineEmits([update:modelValue])
/script流程就是
(1) 子组件将用户输入的值传给父组件 子组件中通过触发事件将$event.target.value的值(也就是用户输入的值)传给父组件父组件将username的值改为用户输入的值。
(2) 用户输入的值传给子组件进而呈现在页面上 通过父组件的modelValue将新的username值传给子组件子组件通过props接收后赋给input标签的value属性呈现用户输入的数据。
3.更换modelValue
需要在v-model后加上别名
!-- 修改modelValue --ChildInput v-model:mimapassword /!-- 本质 --
ChildInput :mimausername update:mimausername $event /4.更换modelValue时可以在组件标签上多次使用v-model 注意
父组件中update:modelValueusername $event 子组件中 inputemit(update:modelValue, $event.target.value)
什么时候用$event,什么时候用$event.target.value $event是什么什么时候能.target 对于原生事件$event就是事件对象,能.target对于自定义事件$event就是触发事件时所传递的数据,不能.target 五、$attrs
用来实现祖孙组件之间的通信。当父组件向子组件通过props传值时子组件defineProps()只接收部分值剩下没接收的值则存在了$attrs里。
1. 未读取的数据存在$attrs里
!-- 父组件 --
div classfatherh3父组件/h3h4a:{{ a }}/h4h4b:{{ b }}/h4h4c:{{ c }}/h4h4d:{{ d }}/h4!-- v-bind{ x: 100, y: 200 } 等价于 :x100 :y200 --Child :aa :bb :cc :dd v-bind{ x: 100, y: 200 } /!-- 等价于 --!-- Child :aa :bb :cc :dd :x100 :y200 / --
/div
!-- 子组件 --h4a:{{ a }}/h4h4其他{{ $attrs }}/h4scriptdefineProps([a])/script2. 祖向孙传数据
!--Father.vue--Child :aa :bb :cc :dd v-bind{ x: 100, y: 200 } /!--Child.vue中间组件啥也不接受传给GrandChild--GrandChild v-bind$attrs /!--GrandChild.vue--div classgrand-childh3孙组件/h3h4a:{{ a }}/h4h4b:{{ b }}/h4h4c:{{ c }}/h4h4d:{{ d }}/h4h4x:{{ x }}/h4h4y:{{ y }}/h4/div
script setup langts nameGrandChilddefineProps([a, b, c, d, x, y])
/script3. 孙向祖传数据 Father.vue:通过props传递函数
Child :aa :bb :cc :dd v-bind{ x: 100, y: 200 } :updateAupdateA /!-- 等价于 --
script setup langts nameFatherfunction updateA(value: any) {a.value value}
/scriptChild.vue
!--Child.vue中间组件啥也不接受传给GrandChild--
GrandChild v-bind$attrs /GrandChild.vue:调用函数
button clickupdateA(666)更新A/button
script setup langts nameGrandChilddefineProps([a, b, c, d, x, y, updateA])
/script六、$refs,与parent
正确的是$ref与$parent,标题打这两个术语会出错。 $refs用于父传子 $parent用于子传父
属性说明$refs值为对象包含所有被ref属性标识的DOM元素或组件实例。$parent值为对象当前组件的父组件实例对象。
1. 回顾标签ref属性修改组件信息 子组件1Child1.vue
templatediv classchild1h3子组件1/h3h4 玩具{{ toy }}/h4h4 书籍{{ book }}本/h4/div
/templatescript setup langts nameChild1
import { ref } from vue;
let toy ref(奥特曼)
let book ref(3)
// 向外暴露出来父组件才能读取到子组件的值
defineExpose({ toy, book })
/script子组件2Child2.vue结构类似
...
script setup langts nameChild2
...
let computer ref(联想)
let book ref(6)
// 向外暴露
defineExpose({ computer, book })
/script父组件Father.vue修改子组件信息
templatediv classfatherh3父组件/h3h4房产有{{ house }}套/h4button clickchangeToy修改子组件1的玩具/buttonbutton clickchangeComputer修改子组件2的电脑/buttonChild1 refc1 /Child2 refc2 //div
/templatescript setup langts nameFather...let house ref(4)// 获取到两个组件的实例对象let c1 ref()let c2 ref()function changeToy() {c1.value.toy 小猪佩奇}function changeComputer() {c2.value.computer 华为}
/script父组件通过ref获取子组件实例对象后可以对其属性进行修改的前提条件时子组件将该属性defineExpose()暴露出来。
2. $refs实现父修改所有子组件信息
父组件Father.vue
button clickgetAllChild($refs)增加所有子组件的书数量/button
script// 参数或者写成 refs:{[key:string]:any}function getAllChild(refs: any) {console.log(refs,refs);for (let key in refs) {// 修改所有子组件的书本属性refs[key].book 3}}
/script3. $parent实现子修改父
父组件Father.vue将数据暴露出去子组件才能获取到该属性并修改:
let house ref(4)
defineExpose({ house })子组件Child1.vue
button clickminusHouse($parent)卖出一套房产/button
scriptfunction minusHouse(parent: any) {console.log(parent,parent);parent.house - 1}
/script这里读取数据不用写.value见之前的记录。
七、provide、inject祖孙通信
$attrs实现祖孙通信了打扰了中间层而provide与inject不会打扰中间层。
提供数据provide(数据或方法,数据或方法) 接收(注入)数据inject(数据)
1. 祖传孙
祖组件Father.vue
script setup langts nameFatherlet car ref(奔驰)// 传递的数据通过provide提供provide(car, car)
/script孙组件GrandChild.vue div classgrand-childh3我是孙组件/h3h4车子{{ car }}/h4/div
script setup langts nameGrandChild// 1.引入injectimport { inject } from vue// 2. 读取数据let car inject(car)
/script注意如果接收数据时 let car inject(car2)祖组件没有提供名为car2的数据则孙组件读取到的car值是undefined; 孙组件可设置默认值 let car inject(car2,奥迪) // car的默认值是奥迪2. 孙传祖
思想还是祖给孙传递函数孙通过参数的方式来给祖传信息。
祖组件Father.vue
script setup langts nameFather
import { ref, provide } from vue;
let money ref(500)function spendMoney(value: number) {money.value - value
}
// 可以将数据或方法一起传递
provide(moneyContext, { money, spendMoney })
/script孙组件GrandChild.vue div classgrand-childh3我是孙组件/h3h4银子{{ money }}万元/h4h4车子{{ car }}/h4button clickspendMoney(6)花钱/button/divscript setup langts nameGrandChildimport { inject } from vue// 解构取值// let { money, spendMoney } inject(moneyContext)// 上面的方式会有警告ts不确定是否会有money和spendMoney所以给个默认值let { money, spendMoney } inject(moneyContext, { money: 0, spendMoney: (param: number) { } })
/script注意为什么传递的不是money.value而是money?
provide(moneyContext, { money.value, spendMoney })如果传递.value则传递的只是一个值
八、pinia,见之前的博客
Vue3(四) pinia
九、插槽slot
回顾Vue2插槽内容Vue2插槽
1. 默认插槽
将组件标签中的html结构放入slot所在的位置
2. 具名插槽
上边的例子中游戏列表四个字在英雄联盟等列表的上方是因为页面结构中h2游戏列表/h2在ul的上方。 如果页面结构中h2游戏列表/h2在ul的下方。如何仍旧保持这样的页面效果 采用具名插槽通过v-slot:插槽名或#插槽名 指定要把页面结构放在哪个插槽里。 Categorytemplate #s2video video :srcvideoUrl controls/video/templatetemplate #s1h2今日影视推荐/h2/template/Category3. 作用域插槽
子组件Game
templatediv classgameh2游戏列表/h2!-- 需要传递的值 --slot :youxigames xhh yhello/slot/div
/templatescript setup langts nameGame
import { reactive } from vue;
let games reactive([{ id: asgytdfats01, name: 英雄联盟 },{ id: asgytdfats02, name: 王者农药 },{ id: asgytdfats03, name: 红色警戒 },{ id: asgytdfats04, name: 斗罗大陆 }
])
/script父组件Father.vue params包含所有参数 总结 默认插槽具名插槽 命名slot namexxx/slot; 使用 template #xxx或 template v-slotxxx作用域插槽 数据在子组件身上 slot :xxxyyy :n1zzz /slot 父组件使用数据 template v-slotparams params接收所有传递过来的数据 template v-slot:defalutparams 通过插槽名指定接收某个插槽的数据 template #defalut{xxx} 通过#插槽名指定接收某个插槽的数据 组件通信总结