子元件向父元件传值与讯息

人类沟通需要技巧,程序语言靠的是方法。

我们除了可以透过 Props 来让父元件传值给子元件外,也可以透过子元件向父元件传递讯息,并可以直接在子元件中操控父元件里的资料。

在父元件传值给子元件所使用的 Props ,在传递资料时是单向资料流(One-Way Data Flow),也就是说,只允许子元件向父元件传递资料,而不允许子元件直接操控 Props 里的资料。有这个原则的原因是因为如果直接让子元件直接操控 Props 里的资料,资料的控制逻辑会变的很复杂与杂乱。单向资料流还是比较容易理解,Vue 也较推荐单向资料流的用法。虽然可以做到双向但 Vue 不建议使用双向。

那麽在 Vue 如何透过自定义事件向父元件传递讯息呢?即是使用 Vue 的内建$emit()方法。

子元件透过自定义事件向父元件传递讯息

语法:<button v-on:click="$emit('enlarge-text')>Enlarge Text</button>
说明:一个子元件里的按钮,点击时会触发一个特定的方法$emit(),并带上一个参数,此参数为自定义的事件名称enlarge-text,这个事件会传递给父元件,所以父元件会去监听这个事件。

父元件中监听子元件的事件

语法:<menu-item v-on:enlarge-text="fontSize += 0.1"></menu-item>
说明:v-on:enlarge-text为绑定事件名称,fontSize += 0.1则为事件对应的处理逻辑。

透过实作的情境会比较清楚传递的运作原理:
实作范例效果:在子元件中点击Enlarge Text按钮之後,会控制父元件中的parentsMsg使文字有大小变化。

  1. 在父元件的 HTML template 插入我们在data的属性parentsMsg内容为'Hello, is parentsMsg',为控制目标。
  2. 在子元件的样版template里加上按钮绑定监听事件,并以$emit()方法,带上指定的自定义事件参数。
  3. 在父元件的 HTML template 绑定刚刚的自定义事件参数
  4. 在父元件的methods增加方法handleSize,每按一次按钮增加字体大小 5px,并在 data 里增加属性fontSize: 12,预设值。
  5. 在父元件的 HTML template 的插入值parentsMsg 元素上绑定元素的字体大小,记得要加入字体单位px
<!-- 父元件的HTML -->
<div id="app">
  <menu-item @enlarge-text="handleBiggerSize"></menu-item>
</div>
<script>
// 子元件 使用$emit()传递
Vue.component('menu-item',{
  template: `
    <div>
      <div >{{parentsMsg}}</div>
      <button @click="$emit('enlarge-text')">放大父元件中元素的字体大小</button>
    </div>
  `
})
// 父元件
const vm= new Vue({
  el:'#app',
  data:{
    parentsMsg: 'Hello, is parentsMsg',
    fontSize: 16,
  },
  methods:{
    handleBiggerSize: function(){
      // 字体变大
      this.fontSize += 5
    },
  }
})
</script>

子元件向父元件传值

我们也可以直接在$emit()里以第二个参数带值进去,就不需要每次去父元件的方法里修改。
子元件透过自定义事件向父元件传递讯息+带值
语法:<button v-on:click="$emit('enlarge-text',0.1)>Enlarge Text</button>
说明:一个子元件里的按钮,点击时会触发一个特定的方法$emit(),并带上两个参数,第一参数为自定义的事件名称enlarge-text,第二参数是值,个事件和值会直接传给父元件,所以父元件会去监听这个事件。

父元件中监听子元件的事件

接收语法:<menu-item v-on:enlarge-text+= $event"></menu-item>
说明:v-on:enlarge-text为绑定事件名称,fontSize += $event则为事件对应的处理逻辑会对应到子主件的绑定方法的第二参数值,$event是固定的写法。

当按下子元件的模版template里的按钮,会直接取到第二参数作为放大字体的增加单位。

实作范例效果:

<!-- 父元件的HTML -->
<div id="app">
  <menu-item @minify-text="handleMinifySize($event)"></menu-item>
</div>
<script>
// 子元件 使用$emit()传递
Vue.component('menu-item',{
  template: `
    <div>
      <div >{{parentsMsg}}</div>
      <button @click="$emit('minify-text',5)">缩小父元件中元素的字体大小</button>
    </div>
  `
})
// 父元件
const vm= new Vue({
  el:'#app',
  data:{
    parentsMsg: 'Hello, is parentsMsg',
    fontSize: 16,
  },
  methods:{
    handleMinifySize: function(value){
      // 字体变大
      this.fontSize -= value
    }
  }
})
</script>

每日一句法文有益身心:Je suis fatigué ! --> 者.虽.发踢给! --> 我好累啊!


<<:  Processing - Day 27 数学好棒棒 第二篇章

>>:  [Day 28] LeetCode - 387 First Unique Character in a String

Day16-sklearn(1)正规化StandardScaler、MinMaxScaler、MaxAbsScaler

正规化 缩小资料的呈现比例 可使数值呈现在一定的范围内 使我们在训练模型时,增加梯度下降的容易度并提...

Day 13:巢状路由的孩子-Nested Routes

目前设定的 Navbar 路由架构还算单纯,并且只有单层路径,但是当专案规模愈来愈大、功能类别拆分的...

Day19 参加职训(机器学习与资料分析工程师培训班),Python程序设计

上午:Python程序设计 延续上次的tkinter,制作Menu有下拉式选单的功能 import ...

Day26 Java String(Ⅰ)

String类提供了1.equals() 2. equalsIgnoreCase()方法来比较两个字...