[Vue] 跟着 Vue 闯荡前端世界

Vue 与 React 的概念都是先针对页面拆分组件化来进行开发,最后再将所有组件合成为我们所需的功能,而组件沟通存在许多种方式及浅在问题,开发人员可以依照需求自行搭配使用,而本篇来研究一下基本的父子上下层的基础沟通方式。


前言


网页应用程序单页面就可能存在许多组件,当然有些组件的运行相当独立,不需要与外部进行过多的沟通,但是我相信绝大部分的组件都存在着与其他组件沟通的需求;我们当然可以采用 veux 官方建议的状态管理套件,角色如同 react 的 redux 来管理各组件之共用状态,但势必付出一些代价( ex.学习成本、多写一些代码来套用 vuex 数据流)。不可否认在大型网页应用程序是有透过 vuex 来管理错综复杂状态之必要性,但本篇先借由一些基本的沟通方式入门,后续有机会在说明 vuex 相关的操作概念及实践方式。

父子组件沟通原则


为了提高组件的独立性与重用性,父组件会透过 props 向下传递数据给子组件,当子组件有事情要通知父组件时会透过 emit 事件告知父组件,如此确保每个组件都是独立在相对隔离的环境中运行,可以大幅提高组件的维护性。

ref: http://cn.vuejs.org/v2/guide/components.html#Prop

pass props


此属性是作为外部传入数据的接口,为遵循单向数据流,避免子组件无意修改了父组件数据,因此在设计上 props 是单向绑定机制。

  • 当父组件更新传入值的时候,子组件 props 都会更新为最新值
  • 子组件不允许直接异动 props 属性值 (主控台会发出警告消息)
  • 子组件强行修改 props 属性值时,由于单向数据流的特性,因此是不会异动到父组件的数值。
特别注意若传入对象或数组型态数据时,若子组件强行修改 props 值是会异动到父组件的数据喔!

建立子组件

来验证一下上述特性,首先建立 Product Card 子组件 (ProductCard.vue),并且建立两个 props 接受外部传入之数据,及一个 props 接收外部传入的方法 。

  • type : 表示数据型态 (会进行类型检测,不符会在主控台发出警告消息)
  • default : 设定默认值 (无传入数据时,使用默认值)
  • required : 是否为必输入属性 (默认为 false)

另外有两的 method 用来强行修改 props 属性数据

  • 修改 string 型态的 props 属性
  • 修改 object 型态的 props 属性

画面如下,提供两个修改数据的连结供测试

其中点选 More Info 按键就是直接执行外部传入的 function props ,并且传入参数至该 function 中。

建立父组件

接着建立 Props Tester 父组件 (PropsTester.vue),并且使用 Product Card 子组件。

传入三个 props (string, object and function) 至该组件中

在父组件中呈现的画面如下,上方输入框呈现父组件数据,皆透过 v-model 双向绑定各数据;下方则是传入数据后所呈现出的子组件,皆使用 v-bind 单向绑定传入 props 的数据。

测试父子交互

当父组件更新传入值的时候,子组件 props 都会更新为最新值

在子组件修改传入  props 型态为 string 数据时,系统会发出警告,并且无法异动父组件数据

但在子组件修改传入  props 型态为 object数据时,可是会直接异动父组件数据(双向绑定) 喔!

最后点选 More Info 后顺利执行父层透过 function props 传入的方法,并且确实传入变量至该方法中。

emit event


先前有提到父组件传入的数据是不行被异动的,因此如果要在子组件操作该数据,并且要在数据异动时通知父组件,让父组件去做相对应的数据处理时,就要透过 emit 事件通知父层。

如何在子层使用父层传入的数据?

  • 子层内部使用,变动后无须通知父层 :
    简单定义 data 属性 internalMadeFrom,将传入值 madeFrom 作为该值的初始值,后续在子组件就直接操作 internalMadeFrom 即可。
  • 父子共用,异动必须通知父层 :
    定义 computed 计算属性 clonedMadeFrom,在 getter 中直接参考 props 传入 madeFrom 数据,在 setter 中直接将异动后新值透过 emit 发送特定事件让父层接收(可透过此机制让父层更新 madeFrom 值,再透过 prop 传递新值进子组件,更新子层 madeFrom 数据,就类似双向绑定作用),后续在子组件就直接操作 clonedMadeFrom 即可。

若选择通知父层,因此子层对所有 madeFrom props 的操作(显示/修改)都须调整为 clonedMadeFrom。

如何在父层监听子层传出的事件?

首先须定义出接收到子层送出数据异动事件后,所需执行的方法;在此定义 onMadeFromChanged 方法,接收子组件修改的新数值,重新更新父层 madeFrom 数据,达到双向绑定的作用。

最后透过 v-on 在子组件上加入事件 handler,事件名称为 mateFromChanged (子组件 emit 的事件名称 )。

执行结果

此结果类似自行实做 v-model 双向绑定机制,重点流程如下:

  1. 子组件修改 computed 的变量,触发 setter 方法执行 emit 事件,并送出修改后的数据
  2. 父组件监听到子组件送出的事件,更新父组件该特定传入值 madeFrom 为子组件修改后的新数据
  3. 因父组件传入 prop 的 madeFrom 数据变动后,子组件 props 都会更新为最新值

为何说类似实践 v-model 呢?因为如果实践 v-model 只需在组件中定义名为 value 的 props 数据,并在 value 变动时 emit 名为 input 的事件传递变更后 value 值即可,而父层只需透过 v-model 传递数据就可以达到双向绑定的效果,是不需要自行处理 v-on:input 来更新数据喔!(因为v-model已经帮忙实践这段)

参考资讯


Vue 2 官方文档 - props

测试代码已上传 GitHub 中,有需要的朋友可以参考一下。
若有更好的建议或做法再请不吝指导一下啰! 感谢!


希望此篇文章可以帮助到需要的人

若内容有误或有其他建议请不吝留言给笔者喔 !