0

0

深入探讨Vue.js组件和组件通信

高洛峰

高洛峰

发布时间:2017-01-16 12:39:24

|

1795人浏览过

|

来源于php中文网

原创

基本是按照官网的 guide 全部梳理了一遍:http://vuejs.org/guide/index.html 这里我们以一个 todo list 应用为例来把相关的只是都串起来,这篇里面的全部代码都在github上 https://github.com/lihongxun945/vue-todolist

 Vue 实例

一个 Vue 应用是由一个 root vue instance 引导启动的,而 Vue instance 是这么创建的:

var vm = new Vue({
 // options
})

 一个 instance 实际上就是 MVVM 中的一个 VM。 传入的配置对象中data里的所有属性都会被挂载到 instance上,而为了避免命名冲突,Vue 内置方法都会以 $ 开头的属性挂载到 instance 上。

立即学习前端免费学习笔记(深入)”;

instance 从创建到销毁会经历如下生命周期:

在初始化的时候大致经过三步:
 •绑定数据监听,即对 data 的监听
 •编译模板
 •插入document或者替换对应dom
 # Vue 基本语法 

数据绑定

Vue 使用的是一种 类 mastache 语法。常用绑定语法分这么几类:
 •mastache 语法,比如 {{ data }} {{ data | filter}}
 •v-bind 绑定属性,比如 v-bind: href, v-bind:class
 •v-on 绑定事件, 比如 v-on:click, v-on:submit 

其中 v-* 都是 directive 

例子:

 属性计算

Vue 支持一个很有意思的属性计算语法,可以指定一个属性由其他属性计算出来,这样就不用通过 $watch 来实现了:

var vm = new Vue({
 el: '#example',
 data: {
 a: 1
 },
 computed: {
 // a computed getter
 b: function () {
 // `this` points to the vm instance
 return this.a + 1
 }
 }
})

 ## 流程控制和列表相关的语法 包括 `v-if`, `v-show`, `v-else`, `v-for` 

表单

双向数据绑定:


 ## 动画 动画的实现方式和 Angular 以及 React 都是一样的,都是通过添加和删除 class 来实现的。 # Component 

组件的基本用法

Component 的定义包括两部分:

1 创建component类:

var Profile = Vue.extend({
 template: "
Lily
" });

 2 注册一个 tagname:

Vue.component("me-profile", Profile);

 这样我们就可以通过 tagname 来使用这么组件了:

...

 Vue.component("me-profile", Profile); 属于全局注册,如果只是在某一个页面内使用,可以通过局部注册的方式:

var vm = new Vue({
 el: "#todo",
 components: {
 "my-profile": Profile
 },
 ...
}

 其中因为我们的 Vue 实例是绑定在 todo 元素上的,所以如果把 my-profile 放在这个元素外面是无效的,只有放在这个里面才会被 Vue 的这个实例引导初始化。

注意事项: 

Vue 构造函数可以传的参数基本都可以用在 Vue.extend 上,但是对 el 和 data 两个参数需要注意,为了避免不同实例间共享同一个对象,总是要通过 function 返回一个新的对象比较靠谱:

var MyComponent = Vue.extend({
 data: function () {
 return { a: 1 }
 }
})

 因为参数都一样,其实他们俩就是同一个东西,不过一个是组件,一个是用来引导Vue启动的。

模板注意事项

因为 Vue 就是原生的DOM,所以有些自定义标签可能不符合DOM标准,比如想在 table 中自定义一个 tr,如果直接插入 my-component 不符合规范,所以应该这样写:

 Props 传递数据

在 Vue 中每个组件都是独立的,不能也不应该直接访问父类的data。所以我们通过 props 来向子组件传递数据,是不是和 React 的方式很像?

不同于 React,在 Vue 中子组件需要先声明自己的 props 才行:

var Profile = Vue.extend({
 props: ["name"],
 template: `
 

{{name}}'s Todo List

{{name}} is a good girl

` });

 然后我们可以在使用 Profile 的时候这样传递参数:

 这种是通过字面量传递参数,所以传递的值一定是字符串。还有一种方式是动态传参,通过 v-bind 来传递参数,可以双向绑定数据或者传非字符串参数:

 v-bind 如果是一个字符串,则是绑定父组件的data中对应的字段,比如上面就是双向绑定了 input 的值。如果是一个数字则就是绑定了一个数字。

Vue 还可以显式指定单向还是双向的数据绑定:

Shop7z网上购物系统至尊版
Shop7z网上购物系统至尊版

Shop7z网上购物系统支持电脑版+手机版+支付宝及微信支付,支持QQ和微信一键登陆,系统集众家之所长,大气超美观页面+手机版+商品组合套餐+限时抢购秒杀+图片批量上传+淘宝数据包导入+弹出式分类菜单+不同规格不同价格+新订单邮件通知+销售报表打印与Excel输出+物流跟踪打印查询+会员积分及优惠券+邮件群发+图片在线管理+销售统计报表+五种价格体系+礼品礼券+微信公众号支付+扫码支付等等等。

下载


 


 

 Props 校验

一个好的组件总是应该先验证参数是否正确,另外可能还需要设置一些参数的默认值:

var Profile = Vue.extend({
 input: {
 type: String
 }
});

 父子组件通信

上面讲到的 props 其实就是父组件向子组件传递消息的一种方式。 
在子组件中有一个 this.$parent 和 this.$root 可以用来方法父组件和根实例。不过,现在我们应该避免这么做。因为组件本身就是为了封装独立的逻辑,如果又去直接访问父组件的数据就破坏了组件的封装性。 
所以我们应该还是应该通过父组件向子组件传递 props 的方式来通信。

当然 props 其实只能做回调。在 React 中就探讨过这个问题,React 的做法就是通过 props 来做,传一个回调函数给子组件。其实我不是很喜欢这种把回调函数传来传去的方式,我更喜欢的是事件的方式。Vue 中子组件可以通过通过事件和父组件进行通信的。向父组件发消息是通过 this.$dispatch,而向子组件发送消息是通过 this.$boardcast,这里都是向所有的父亲和孩子发送消息,但是一旦执行一个回调之后就会停止,除非这个回调函数显式返回了 true。

我们把之前的Todo List拆成不同的组件来实现,这样可以体验下如何进行组件的双向通信,我们拆分出两个组件,分别是 List 和 Form 。

Form 负责处理用户输入,并在提交表单的时候向父组件发送一个 add 消息,代码如下:

var Form = Vue.extend({
 props: {
 username: {
 type: String,
 default: "Unnamed"
 }
 },
 data: function() {
 return {
 input: "",
 };
 },
 template: `
 

{{username}}'s Todo List

`, methods: { add: function() { this.$dispatch("add", this.input); //这里就是向父组件发送消息 this.input = ""; } } });

 List 只负责展示列表和处理用户勾选操作,它接收到 add 消息之后会在自己上添加一个条目:

var List = Vue.extend({
 template: `
 
`, props: { initList: { type: Array } }, data: function() { return { list: [] } }, events: { add: function(input) { if(!input) return false; this.list.unshift({ title: input, done: false }); } } });

 然后,因为这是两个组件,当然需要一个 Vue 实例来引导启动,我们的实例如下:

var vm = new Vue({
 el: "#todo",
 components: {
 "todo-form": Form,
 "todo-list": List
 },
 events: {
 add: function(input) {
 this.$broadcast("add", input);
 }
 }
});

 注意,其实 Form 和 List 在逻辑上是平级的组件,所以他们没有父子关系,他们共同都是 vm 的孩子。这里 vm 接到 Form 的消息之后会转发给 List。

html 代码就更简单了:

 Slot

通过 Slot 可以实现把父组件渲染出来的HTML插入到子组件中,目前还不清楚什么时候会需要这样做,而且这么做对子组件的侵入性太大。

动态切换组件

这个功能感觉有点多余,感觉很多情况下我们应该是通过逻辑代码来实现切换,而不是通过Vue内置的动态组件来切换。不过用来实现一个类似 tab 切换的功能还是很方便的。

我们这里给 Todo List 增加一个 about 页面。那么首先我们需要把 vm 改成一个组件,这个组件叫 Todo,它就是整个 Todo 页面:

var Todo = Vue.extend({
 template: `
 
not show
`, components: { "todo-form": Form, "todo-list": List }, events: { add: function(input) { this.$broadcast("add", input); } } });

 

 其实改动就第一行。

然后我们需要创建一个 About 组件:

var About = Vue.extend({
 template: `
 

About Todo List V0.1.0

Content here

` });

 接下来是重点了,我们要创建一个实例 vm,这vm要负责切换这两个页面:

var vm = new Vue({
 el: "body",
 data: {
 currentView: "todo"
 },
 components: {
 "todo": Todo,
 "about": About
 }
});

 这里我们定义了一个 currentView 字段,当然可以是任意名称,然后通过特殊的 component 标签来进行组件切换:


 

 上面的代码有两处需要注意:
 •通过 component这个特殊标签,然后用 :is 属性来进行组件的切换。
 •radio 通过双向绑定来修改 currentView 字段,从而实现点击之后就可以进行切换。

数据绑定的实现原理

Vue 把双向绑定称作 reactive,可以翻译为响应式数据绑定。内部是通过 ES5 定义的 getter 和 setter 方法实现的,所以不支持 IE8 及以下浏览器,这种实现方式有两个容易犯错的地方:
 •如果在 data 上直接添加和删除属性是无法被检测到的,一般删除是不会的,但是可能会动态添加,这个时候应该通过 vm.$set(“name”, value) 的方式来添加。
 •无法检测到对象内部的变化,也就是只能检测 data 的属性变化,如果 data.a 是一个对象,那么 data.a.b = 1 这种变化是无法被检测到的。这种情况下应该创建一个新的对象并赋值给 data.a 就行了。 

异步更新机制

Vue 对DOM的更新是异步的! 这个异步是在一个异步队列中进行的,不过这个异步队列会在当前的 Event Loop 中执行完,所以如果修改了 Data 立刻去DOM中做查询操作是不对的,这个时候DOM还没有更新,正确的做法是这样做:

vm.msg = 'new message' // change data
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
 vm.$el.textContent === 'new message' // true
})

 或者这样:

vm.$nextTick(function () {
 this.$el.textContent === 'new message' // true
})

 花了半天时间才看完组件,下面应该去看一下另一个重点: Directive

本文已被整理到了《Vue.js前端组件学习教程》,欢迎大家学习阅读。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多X深入探讨Vue.js组件和组件通信相关文章请关注PHP中文网!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.7万人学习

React 教程
React 教程

共58课时 | 4.4万人学习

Bootstrap4.x---十天精品课堂
Bootstrap4.x---十天精品课堂

共22课时 | 1.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号