兔大夫:
「请问是兔豪的家属吗?」
兔豪爸:
「是,我就是。 请问我鹅子他...」
兔大夫:
「抱歉,我尽力了 ...」
「他得的是一种 "会常常跟你讨零用钱而且不管给他多少钱他都一定会花到只剩 50 块然後会把这 50 块还你" 症。」
「这是不治之症,目前医学上还没有办法改善。」
兔豪爸:
「所以,难道说我的鹅子...」
兔大夫:
「对,没救了。」
兔豪:
「爸,我要零用钱!」
兔豪爸:
「竟然已经 ... 没救了。」
兔豪:
「爸,我要零用钱!」
兔豪爸:
「好 ... 好... 你等等我。」
看来,就是有一个土豪爸,才会有个土豪儿子呀。
有多少花多少,但还会留个 50 元也算良心了 XD
不过其实啊,
像兔豪爸和兔豪这样的行为,
就是很经典的父子元件间的资料传递!
就让我们来看看怎麽实现吧!
其实啊,在实现元件间的资料传递时,
父传子是最简单的!
就是运用在元素上绑定属性就可以了!
来看看简单的举例:
<template>
<RabbitSon :allowance="money" />
</template>
<script>
export default {
name: "兔豪爸",
data() {
return {
money: 1000,
}
}
}
</script>
这样代表着兔豪爸已经把 1000 给兔豪了。
不过有一点可以注意的是,
在这个范例中的 :allowance
是一个自订属性。
而其实不管属性是否是自订的,
只要在子元件的 props 有对应的名称,
就能收到来自父元件的资料。
「欸?就这麽轻松?」
没错哦,就是这麽轻松。
不过这只是传递过去的部分,
其实啊,即使我们给了兔豪,
兔豪也还要做收下的动作。
所以我们接着就来看看兔豪要怎麽收到爸爸给的零用钱罗!
前面也说过,
props
必须要与父元件传递资料给我们时的属性名称对应,
这是什麽意思?
因为在子元件里,
比需要像在 data( )
中那样定义会用到什麽变数,
在 props
中也一样。
我们必须列出会要收到资料的属性名称,
这样就会自动与元素上的属性对应到了。
直接看例子:
<!-- RabbitSon.vue -->
<template>
<div>
我是兔豪,<br />
爸爸给了我 {{allowance}} 块当用钱。
</div>
</template>
<script>
export default {
name: "兔豪",
props: ["allowance"]
}
</script>
像这样,从父元件传入时的属性叫做 allowance
,那 props 中也必须定义出 "allowance"
才能顺利收取到资料。
不过这样还是没有还原出兔豪把「50 块还给爸爸」的动作。 接下来就是要讲解如何实现从子元件传递资料回父元件。
想要将资料传递回父元件,就必须靠 emit
。
emit 就是发射、发出的意思,
也就是指我们把资料由低往高送出的这个行为。
我们先直接看范例,
兔豪要在一收到钱时就马上花掉,
我们就在子元件挂载时处理这件事情。
也就会是:
<!-- RabbitSon.vue -->
<template>
<div>
我是兔豪,<br />
爸爸给了我 {{allowance}} 块当用钱。
</div>
</template>
<script>
export default {
name: "兔豪",
props: ["allowance"],
mounted() {
console.log("收到零用钱 " + this.allowance + " 元")
this.$emit("return", 50)
}
}
</script>
是不是看不懂那行 $emit 在做些什麽?
没关系,直接来看一下 emit 的用法:
$emit( 事件名称, 传递内容 )
这边所指的事件名称就是传递给父元件时,
在父元件那边所发生的事件。
所以跟父元件传递资料进来同理,
我们传递出去时父元件也须接收。
来看一下范例:
<template>
<RabbitSon :allowance="money" @return="getMoney($event)" />
</template>
<script>
export default {
name: "兔豪爸",
data() {
return {
money: 1000,
}
},
methods: {
getMoney( money ) {
console.log("儿子兔豪花剩下的 " + money + " 元")
}
}
}
</script>
会发现子元件身上有一个事件 @return
,这个事件就是在子元件中 this.$emit("return", 50)
时的事件名称
"return"。
在子元件内执行 emit 时,父元件这边的子元件就会触发 emit 时设定的事件。
而 this.$emit("return", 50)
後面的传递内容 "50" 就是事件中可以获取的事件参数
event。
这可能太复杂了,
这样很容易听不懂,
我们来图解。
这样应该就比较看得出互相传递的关系了!
不过现在我们仍然只是传递很简单的纯值内容,如果要传递物件
呢? 那我们就要讲到物件解构
的特性啦!
如果只是传递纯值,这很简单没有问题。
但如果是传递物件就必须要小心了!
直觉,我们可能会这样传递:
<template>
<RabbitSon :allowance="wallet" @return="getMoney($event)" />
</template>
<script>
export default {
name: "兔豪爸",
data() {
return {
wallet: {
money: 1000,
msg: "省着点用",
},
}
},
methods: {
getMoney( money ) {
console.log("儿子兔豪花剩下的 " + money + " 元")
}
}
}
</script>
但这会有一个问题,就是不安全
。
我们直接把物件当作属性来传递时,因为传递的是整个物件,所以父元件传递的和子元件所拿到的物件是同个记忆体位置
,这样在子元件中修改 props 进来的资料时,父元件的资料也会被同步改掉。
「兔兔,这样不是超赞的嘛! 要往回传递的时候都不用写那个很难搞懂的 emit,现在直接修改内容就好了!」
不,其实这一点都不赞哦!
为什麽前面说这麽做不安全呢?
因为这样其实是子元件对父元件资料污染
了!
之前有说过 SFC 元件的好处就是逻辑清晰,
如果我现在在内部处理资料的时候就会不小心改到父层的资料,这不是太可怕了吗?!
所以我们必须要用物件解构
的方式来进行!
如果传递的是整个物件,
我们就用直接的 v-bind
语法来完成:
<template>
<RabbitSon v-bind="wallet" @return="getMoney($event)" />
</template>
<script>
export default {
name: "兔豪爸",
data() {
return {
wallet: {
money: 1000,
msg: "省着点用",
},
}
},
methods: {
getMoney( money ) {
console.log("儿子兔豪花剩下的 " + money + " 元")
}
}
}
</script>
那在子元件中则是要修改成这样:
<!-- RabbitSon.vue -->
<template>
<div>
我是兔豪,<br />
爸爸给了我 {{money}} 块当用钱。<br />
爸爸还说:「{{msg}}」
</div>
</template>
<script>
export default {
name: "兔豪",
props: ["money","msg"],
mounted() {
console.log("收到零用钱 " + this.money + " 元")
this.$emit("return", 50)
}
}
</script>
可以发现虽然我们父元件传送的是物件,但在子元件中完全看不到物件的踪影,倒是 props 里都是物件内的属性。
没错,透过物件解构我们可以把属性拆出来都送给子元件
,这样就可以避免掉资料污染的问题。
一样再来上个图解。
先是以整个物件的方式传递,
到了子元件後再解开。
这样就可以了!
关於元件资料传递就差不多介绍到这里啦!
emit 的部分可能比较难理解一些,
不过搭配图解和前面叙述,
应该多看几次就能明白了~
下一篇,
又要来介绍很有趣的东西了!
好期待~~
关於兔兔们:
( # 兔兔小声说 )
许多人认为,夏威夷披萨是邪教。
认识兔兔的朋友们都知道兔兔不太吃夏威夷披萨,但绝对不是因为它是邪教,是因为朋友们都认为它是邪教所以我不敢吃啊 XD
不过其实有趣的是,
你们知道夏威夷披萨跟夏威夷关系其实并不大吗?对,我也惊呆了。
转述一下维基百科的内容:
「夏威夷披萨是希腊出生的加拿大厨师发明的,因为
受到中华料理中的酸、甜元素启发
,所以做出了夏威夷披萨。而披萨叫做夏威夷,只是因为使用的凤梨罐头上面印着夏威夷字样
。」好啦,不过凤梨的确是夏威夷特产,当地也有酸甜气味的早餐料理叫做 Acai bowl,有到夏威夷可以吃吃看哦~
在丛集管理方面,kubernetes 将 cluster 中的机器划分为一个 master 节点以及...
什麽是变化,我们在变化什麽? 当涉及到更改时,至关重要的是定义什麽是更改并阐明我们正在更改的内容。...
对大部分使用k8s服务的人来说都会有一个探讨的问题是,到底DB是否适合上k8s,其实我个人是觉得不适...
同步(Synchronous)与非同步(Asynchronous) 在理解执行上下文与呼叫堆叠之後,...
这是我30天的自我挑战,每篇文章都记录着自己的成长与收获,也请大家多多指教! Android是甚麽...