关于vue.js组件数据流的问题


Posted in Javascript onJuly 26, 2017

一、组件

组件,可以说是现代前端框架中必不可少的组成部分。使用组件,不仅能极大地提高代码的复用率和开发者的开发效率,对于代码后期的维护也有着非常重要的意义。前端开发,由于历史遗留原因,WebComponent 虽然好用,但其发展情况却受到极大地限制,和很多新兴的前端技术一样,可望而不可即。基于这样的情况,聪明的开发者们尝试通过框架内部集成相应的功能来完成组件化,各种现代前端框架基本上都有各自的实现。这里我们来分析一下 vue 的组件,重点关注数据的流向。

二、vue 组件

vue 的组件,创建模板的时候是基于普通的 html 的,不需要学习 jsx、handlebars 等的特殊语法,所以相对来说,学习成本比较低,更容易上手。使用 vue 组件的时候,一般分为组件注册和组件调用两个部分。

(一)组件注册

Vue.component('pop-box', {
  template:  '<div class="component-box">\
    <div class="component-content">\
    ..........
    </div>\
  </div>',

  props: [...],

  data: function () {
    return ...;
  },

  methods: {
    ...
  },

  mounted () {
    ...
  },

  ...
});

利用 Vue.component 方法我们可以很轻松的创建一个全局可用的组件,当然也可以在实例或组件内部注册局部组件,但原理大同小异。Vue.component 的第一个参数是组件的名字,或者说唯一标识符(id),后续调用它将通过这个名字进行调用;第二个参数是一个对象,通常它包含了模板(template)、组件内维护的数据(data、computed)、方法(methods)、钩子函数(created 、 mounted...)等关键信息。

值得注意的是:

  1. 组件内的 data 必须是一个函数,它的返回值将作为实际的 “data”;
  2. vue1.x 和 vue2.x 的钩子函数略有不同,如果发现钩子函数不生效,记得确认 vue 的版本。

(二)组件调用

(1)开始标签 + 结束标签模式

<pop-box text="200" v-bind:number="200"></pop-box>

(2)无结束标签模式

<pop-box text="200" v-bind:number="200" />

调用 vue 组件有以上两种模式。两种模式上,如果没有使用 slot 那么实际上并没有任何区别,但如果需要使用 slot 的时候,便只能使用同时包含开始标签和结束标签的模式。

值得注意的是,上面绑定数据的时候,直接采用 property="value" 的形式,不管 value 是数字还是字符串,property 最终都是字符串类型。如果想让其变成数字类型,请使用 v-bind:property="value" 的形式,或者简写为 :property="value" 。

三、vue 组件数据流

vue 遵循了典型的单向数据流的原则,即数据总是由父组件传递到子组件,子组件在其内部可以有自己维护的数据,但它无权修改父组件传递给它的数据,当开发者尝试这样做的时候,vue 将会报错。这样做的好处是,防止多个子组件都尝试修改父组件状态时,让这一行为变得难以追溯。vue 中具体实现方式如下:

关于vue.js组件数据流的问题

父组件通过绑定 props 的方式,将数据传递给子组件,但是子组件自己并没有权利修改这些数据,如果要修改,只能把修改这一个行为通过 event 的方式报告给父组件,由父组件本身决定改如何处理数据。

(一)简单实例

<div id="app">
  <my-counter @inc="increase" :counter="counter"></my-counter>
</div>
...
Vue.component('my-counter', {
  template:  '<div class="counter">\
    <div>{{counter}}</div>\
    <button @click="inc">increase</button>\
  </div>',

  props: ['counter'],

  methods: {
    inc: function () {
      this.$emit('inc');
    }
  }
});

var app = new Vue({
  el: '#app',
  data: {
    counter: 0
  },
  methods: {
    increase () {
      this.counter ++;
    }
  }
});

为了显得更简单这里只创建了一个 my-counter 组件作为子组件,我们可以姑且将 vue 的实例认为是一个父组件。

(二)分析数据流向分析

(1)我们在父组件中定义了一个数据叫 counter;
(2)调用组件的时候,通过 :counter="counter" 的方式,将父组件的 counter 以 prop 的方式传递到子组件中;
(3)子组件读取到 counter,并将其展示在模板中;
(4)用户点击按钮,counter 需要增加;
(5)子组件监听到这个事件,但它并不直接修改 counter,而是通过 this.$emit('inc'); 以自定义事件的形式,将需要增加的这一个事件报告给父组件;
(6)父组件中,由于通过执行过 @inc="increase" ,能够监听到子组件报告过来的事件,并在自己的 increase 方法中,实现 counter 的增加;
(7)父组件里的数据更新了,子组件里的数据也将自动更新,同时也将更新界面内容,这一过程由框架自动完成。

(三)总结

上面这一个示例,基本完整展示了 vue 主要的数据流向,但是这种基于 prop/evnet 的方式仅适用于存在直接的父子关系的组件,兄弟组件或者大量组件的数据流向如果再基于这种方式将会变得非常麻烦,这时可以考虑使用更加强大的状态管理模式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 嵌套函数指向this对象错误的解决方法
Mar 15 Javascript
javascript 随机展示头像实现代码
Dec 06 Javascript
js读取并解析JSON类型数据的方法
Nov 14 Javascript
jquery分页插件jquery.pagination.js实现无刷新分页
Apr 01 Javascript
jQuery 判断是否包含在数组中Array[]的方法
Aug 03 Javascript
JavaScript中splice与slice的区别
May 09 Javascript
vue与bootstrap实现时间选择器的示例代码
Aug 26 Javascript
JS 中document.write()的用法和清空的原因浅析
Dec 04 Javascript
bootstrap fileinput插件实现预览上传照片功能
Jan 23 Javascript
基于mpvue的简单弹窗组件mptoast使用详解
Aug 02 Javascript
解决VantUI popup 弹窗不弹出或无蒙层的问题
Nov 03 Javascript
使用JS实现鼠标放上图片进行放大离开实现缩小功能
Jan 27 Javascript
Vue.js弹出模态框组件开发的示例代码
Jul 26 #Javascript
VueJs单页应用实现微信网页授权及微信分享功能示例
Jul 26 #Javascript
node实现简单的反向代理服务器
Jul 26 #Javascript
Angular项目中$scope.$apply()方法的使用详解
Jul 26 #Javascript
Vue中计算属性computed的示例解读
Jul 26 #Javascript
让你彻底掌握es6 Promise的八段代码
Jul 26 #Javascript
Bootstrap datepicker日期选择器插件使用详解
Jul 26 #Javascript
You might like
PHP中全局变量global和$GLOBALS[]的区别分析
2012/08/06 PHP
PHP中的生成XML文件的4种方法分享
2012/10/06 PHP
ThinkPHP整合百度Ueditor图文教程
2014/10/21 PHP
详解PHP的Yii框架的运行机制及其路由功能
2016/03/17 PHP
PHP中TP5 上传文件的实例详解
2017/07/31 PHP
浅谈JavaScript中面向对象技术的模拟
2006/09/25 Javascript
JQuery 实现的页面滚动时浮动窗口控件
2009/07/10 Javascript
Mootools 1.2教程(3) 数组使用简介
2009/09/14 Javascript
用html+css+js实现的一个简单的图片切换特效
2014/05/28 Javascript
sogou地图API用法实例教程
2014/09/11 Javascript
jQuery中unbind()方法用法实例
2015/01/19 Javascript
详解JavaScript中jQuery和Ajax以及JSONP的联合使用
2015/08/13 Javascript
javascript新闻跑马灯实例代码
2020/07/29 Javascript
JS加载器如何动态加载外部js文件
2016/05/26 Javascript
简单实现jquery隔行变色
2017/11/09 jQuery
jquery学习笔记之无new构建详解
2017/12/07 jQuery
常见的浏览器存储方式(cookie、localStorage、sessionStorage)
2019/05/07 Javascript
五分钟搞懂Vuex实用知识(小结)
2019/08/12 Javascript
layui实现tab的添加拒绝重复的方法
2019/09/04 Javascript
JavaScript实时更新当前的时间的示例代码
2020/07/15 Javascript
[02:28]PWL开团时刻DAY3——Ink Ice与DeMonsTer之间的勾心斗角
2020/11/03 DOTA
python的描述符(descriptor)、装饰器(property)造成的一个无限递归问题分享
2014/07/09 Python
python下如何查询CS反恐精英的服务器信息
2017/01/17 Python
python hbase读取数据发送kafka的方法
2018/12/27 Python
Python3 全自动更新已安装的模块实现
2020/01/06 Python
解决python运行启动报错问题
2020/06/01 Python
Perry Ellis官网:美国男士品味服装
2016/12/09 全球购物
美国首屈一指的高品质珠宝设计师和零售商:Allurez
2018/01/23 全球购物
意大利奢侈品牌在线精品店:Jole.it
2020/11/23 全球购物
金融专业应届生求职信
2013/11/02 职场文书
医学专业职业生涯规划范文
2014/02/05 职场文书
企业文化建设实施方案
2014/03/22 职场文书
个人授权委托书
2014/04/03 职场文书
vue实现水波涟漪效果的点击反馈指令
2021/05/31 Vue.js
Android自定义scrollview实现回弹效果
2022/04/01 Java/Android
Golang Elasticsearches 批量修改查询及发送MQ
2022/04/19 Golang