基本是按照官网的 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
例子:
f996d692740c207efa7ef2cd58d696ef
属性计算
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`
表单
双向数据绑定:
9dc6161fc1b615b1bd3917481aa047b2
f3cf7170f549be506b74da26afa56721
## 动画 动画的实现方式和 Angular 以及 React 都是一样的,都是通过添加和删除 class 来实现的。 # Component
组件的基本用法
Component 的定义包括两部分:
1 创建component类:
var Profile = Vue.extend({ template: "<div> Lily </div>" });
2 注册一个 tagname:
Vue.component("me-profile", Profile);
这样我们就可以通过 tagname 来使用这么组件了:
<div id="todo"> <my-profile></my-profile> <form v-on:submit="add" v-on:submit.prevent> <input type="text" v-model="input"/> <input type="submit" value='add' /> </form> ... </div>
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 不符合规范,所以应该这样写:
<table> <tr is="my-component"></tr> </table>
Props 传递数据
在 Vue 中每个组件都是独立的,不能也不应该直接访问父类的data。所以我们通过 props 来向子组件传递数据,是不是和 React 的方式很像?
不同于 React,在 Vue 中子组件需要先声明自己的 props 才行:
var Profile = Vue.extend({ props: ["name"], template: ` <h2>{{name}}'s Todo List</h2> <h4>{{name}} is a good girl</h4> ` });
然后我们可以在使用 Profile 的时候这样传递参数:
92de4287932759d26a80be367583ea152ce8caae7ced446f67526b3e9d39dfa1
这种是通过字面量传递参数,所以传递的值一定是字符串。还有一种方式是动态传参,通过 v-bind 来传递参数,可以双向绑定数据或者传非字符串参数:
1c79ee1f069084334f635869e4eacee42ce8caae7ced446f67526b3e9d39dfa1
v-bind 如果是一个字符串,则是绑定父组件的data中对应的字段,比如上面就是双向绑定了 input 的值。如果是一个数字则就是绑定了一个数字。
Vue 还可以显式指定单向还是双向的数据绑定:
<!-- default, one-way-down binding --> <child :msg="parentMsg"></child> <!-- explicit two-way binding --> <child :msg.sync="parentMsg"></child> <!-- explicit one-time binding --> <child :msg.once="parentMsg"></child>
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: ` <h1>{{username}}'s Todo List</h1> <form v-on:submit="add" v-on:submit.prevent> <input type="text" v-model="input"/> <input type="submit" value='add' /> </form> `, methods: { add: function() { this.$dispatch("add", this.input); //这里就是向父组件发送消息 this.input = ""; } } });
List 只负责展示列表和处理用户勾选操作,它接收到 add 消息之后会在自己上添加一个条目:
var List = Vue.extend({ template: ` <ul> <li v-for='todo in list'> <label v-bind:class="{ done : todo.done }" > <input type="checkbox" v-model="todo.done"/> {{todo.title}} </label> </li> </ul>`, 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 代码就更简单了:
<div id="todo"> <todo-form username='Lily'></todo-form> <todo-list></todo-list> </div>
Slot
通过 Slot 可以实现把父组件渲染出来的HTML插入到子组件中,目前还不清楚什么时候会需要这样做,而且这么做对子组件的侵入性太大。
动态切换组件
这个功能感觉有点多余,感觉很多情况下我们应该是通过逻辑代码来实现切换,而不是通过Vue内置的动态组件来切换。不过用来实现一个类似 tab 切换的功能还是很方便的。
我们这里给 Todo List 增加一个 about 页面。那么首先我们需要把 vm 改成一个组件,这个组件叫 Todo,它就是整个 Todo 页面:
var Todo = Vue.extend({ template: ` <div id="todo"> <todo-form username='Lily'></todo-form> <todo-list></todo-list> <slot>not show</slot> </div> `, components: { "todo-form": Form, "todo-list": List }, events: { add: function(input) { this.$broadcast("add", input); } } });
其实改动就第一行。
然后我们需要创建一个 About 组件:
var About = Vue.extend({ template: ` <div id="about"> <p>About Todo List V0.1.0</p> <p>Content here</p> </div>` });
接下来是重点了,我们要创建一个实例 vm,这vm要负责切换这两个页面:
var vm = new Vue({ el: "body", data: { currentView: "todo" }, components: { "todo": Todo, "about": About } });
这里我们定义了一个 currentView 字段,当然可以是任意名称,然后通过特殊的 component 标签来进行组件切换:
<component :is="currentView"></component> <ul> <li><label><input type="radio" name='page' value='todo' v-model='currentView'> Home</label></li> <li><label><input type="radio" name='page' value='about' v-model='currentView'> About</label></li> </ul>
上面的代码有两处需要注意:
•通过 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中文网!

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

WebStorm Mac版
好用的JavaScript开发工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。