vue.js中文教程(编)

vue.js中文教程(编)

vue.js全面的学习资料,按照学习认知的接受过程重新梳理知识框架,帮助学习者快速定位知识点,解决开发中的问题。

前言

在阅读了《vue.js权威指南》之后,我转载请注明出处:www.tangshuang.net原创内容,盗版必究。发现它基于1.0版本已经完全不适用当前的未经授权,禁止复制转载。【本文受版权保护】2.0版本了,大部分介绍虽然很详尽,甚至【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】还分析了源码,但是实际上感觉是在浪费纸张【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。,因为读者要看源码会到github上自己本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】阅读,书里面只需要告诉读者项目的代码结构【本文受版权保护】原创内容,盗版必究。,让读者可以快速找到对应的源码即可。而且【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】权威指南版本落伍会带来一些使用上的困难,本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】特别是一些api无法使用的时候,很苦恼。
本文作者:唐霜,转载请注明出处。 所以,我只把这本书当做一本接触vue的【本文受版权保护】【版权所有】唐霜 www.tangshuang.net入门书,省略了其中非常多的部分,从中大致转载请注明出处:www.tangshuang.net【本文受版权保护】领略vue的使用方法和理念。我大部分时候【本文首发于唐霜的博客】未经授权,禁止复制转载。,更多的是对照官网的文档进行开发,一边开【版权所有,侵权必究】【本文首发于唐霜的博客】发一边写代码,经常发现自己找不到对应的文【原创不易,请尊重版权】【本文受版权保护】档,翻来翻去很久,才能找到自己需要的内容原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

未经授权,禁止复制转载。【原创内容,转载请注明出处】【作者:唐霜】

而且官网的文档不是很详细,有些注意点并没【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。有说的很详细,导致开发的时候遇到一些坑,原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。或者不是很理解,使用的时候就乱用,多试几【转载请注明来源】原创内容,盗版必究。次就可以试出正确用法。当然这是笨蛋的方法本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】

原创内容,盗版必究。【原创内容,转载请注明出处】【转载请注明来源】

另外,我认为vue-router和vue转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。-resource是两个必须讲清楚的插件本文作者:唐霜,转载请注明出处。【作者:唐霜】,《权威指南》里面虽然也讲了,但是对照官【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】方文档,还是落伍了。不过《权威指南》的框本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】架结构很好,可以借鉴作为学习的大体框架。

【原创不易,请尊重版权】原创内容,盗版必究。【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】【转载请注明来源】ngnet】

鉴于这些情况,我专门编这本书,用来帮助v【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】ue的学习者快速理清知识体系。注意,我用本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】的是“编”,也就是说本书的内容基本上是复【转载请注明来源】【版权所有,侵权必究】制黏贴来的,只不过把知识结构重新梳理,以【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net便更好的学习这门框架。因此,对前人的努力【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net做出感谢。

原创内容,盗版必究。【转载请注明来源】【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netngnet】

之所以没有通过gitbook等方式开源本【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。书,是因为我觉得那样更难维护,而且不利于【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。拷贝。最重要的是,那样没有一个直观的反馈著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net方式,如果你在阅读本书的时候遇到一些疑问【未经授权禁止转载】【转载请注明来源】,请在下方的留言框中进行留言,我会第一时本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。间进行回复。当然,如果本书有不足之处,也【作者:唐霜】【关注微信公众号:wwwtangshuangnet】请你留言,我会完善它。

转载请注明出处:www.tangshua未经授权,禁止复制转载。原创内容,盗版必究。ng.net【转载请注明来源】

背景了解

我在morningstar一直使用的都是【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。backbone,并且接触了compon未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】ent的理念,但backbone对我来说【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net还是太重了,于是我在寻找其他的compo【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】nent替代方案,最早进入我的视线的是r【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.neteact,但在接触之后,发现react门【转载请注明来源】本文作者:唐霜,转载请注明出处。槛稍微有点高,方法名太长,方式太复杂,可本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。以说“不符合我的审美”,当然,我还会继续未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net学习react,因为我在接触vue之后,本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】发现react在技术理念上,确实是一个未【未经授权禁止转载】【作者:唐霜】来的产品,这并不是说vue不好,vue非未经授权,禁止复制转载。【作者:唐霜】常好,所以我才会先花时间学习它,并且在我著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net的业余项目中直接使用它。未来react只【版权所有】唐霜 www.tangshuang.net【转载请注明来源】会作为我的一个工具,而vue则是我当下最【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。佳的选择。

【访问 www.tangshuang.n【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】ang.net

vue是什么?

Vue.js(读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架。vue的英文意思就是“视图”,所以可以未经授权,禁止复制转载。【本文受版权保护】知道,vue是一个偏视图的js框架,根据【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】官方的解释的理解,vue不属于MVC的范原创内容,盗版必究。转载请注明出处:www.tangshuang.net畴,因为它只有MV,而且它的M是内置于框【作者:唐霜】【原创不易,请尊重版权】架内核中,对于开发者而言,可能基本上都是本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】在处理V的东西。这也是为什么现在把vue原创内容,盗版必究。【原创内容,转载请注明出处】和react对比如此热门的原因之一。既然【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。是解决视图问题,那么不可避免的就会和DO【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netM打交道,自然就会联想到react首创的本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netVirtual DOM理念,这在后文会详本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。细分析虚拟DOM是怎么回事。vue2.0【版权所有,侵权必究】【转载请注明来源】也使用了Virtual DOM,因此在视著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net图层面的渲染速度也非常快。

【作者:唐霜】著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】【未经授权禁止转载】

总之,vue是一个关注视图层面的js框架【本文受版权保护】本文作者:唐霜,转载请注明出处。

本文作者:唐霜,转载请注明出处。【本文受版权保护】著作权归作者所有,禁止商业用途转载。

既然是框架,而非库,那么就意味着它已经帮【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。你处理好了很多问题,当然,同时也限制了一著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net些方式。这和react不同,react实【转载请注明来源】【转载请注明来源】际上限制更少一些,内部封装更少一些,re本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。act官方把自己称为library(库)【本文受版权保护】【原创内容,转载请注明出处】。虽然是一个框架,但vue并不以构建ap【原创内容,转载请注明出处】【本文受版权保护】p为最终目标,实际上,组件思想在vue中本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net更加突出。因此,在基于vue的开发中,请本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】更多思考组件,这和angular的时代可【本文首发于唐霜的博客】【转载请注明来源】能有些不同。

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua未经授权,禁止复制转载。未经授权,禁止复制转载。ng.net本文作者:唐霜,转载请注明出处。

发展历史

Vue.js正式发布于2014年2月,对【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】于目前的Vue.js:

【访问 www.tangshuang.n【转载请注明来源】本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】原创内容,盗版必究。【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。ngnet】【转载请注明来源】

在开发人数上,覆盖70多贡献者。
本文版权归作者所有,未经授权不得转载。 在受关注度上,GitHub拥有 200著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。00 多 Star。
【本文受版权保护】 从脚手架、构建、插件化、组件化,到编辑著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。器工具、浏览器插件等,基本涵盖了从开发到转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】测试等多个环节。

【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。et 获取更多精彩内容】【本文受版权保护】【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】et 获取更多精彩内容】【作者:唐霜】

Vue.js的发展里程碑如下:

【作者:唐霜】著作权归作者所有,禁止商业用途转载。

2013年12月24日,发布0.7.0。
【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netngnet】 2014年1月27日,发布0.8.0。
本文版权归作者所有,未经授权不得转载。 2014年2月25日,发布0.9.0。
【版权所有】唐霜 www.tangshu【转载请注明来源】【作者:唐霜】ang.net 2014年3月24日,发布0.10.0原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net
未经授权,禁止复制转载。 2015年10月27日,正式发布1.0【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。.0。
本文作者:唐霜,转载请注明出处。 2016年4月27日,发布2.0的pr【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】eview版本。
原创内容,盗版必究。 2016年10月,2.0正式版发布,整【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net个框架重新编写,性能提升,支持服务端渲染【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。

vue的作者

我是对国产框架比较鄙视的,特别是以前用t本文作者:唐霜,转载请注明出处。【作者:唐霜】hinkphp,但在前端领域,我接触过s【作者:唐霜】【转载请注明来源】eajs,原本觉得非常不错,可是后来也湮转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】灭了,就觉得国产开发框架没戏。看到vue【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net之前,并不知道它的作者是中国人,觉得这个【转载请注明来源】著作权归作者所有,禁止商业用途转载。项目超有国际范儿。当后来知道vue的作者【版权所有】唐霜 www.tangshuang.net【转载请注明来源】竟然是中国人,就突然感觉不一样。当然,这【原创内容,转载请注明出处】【原创不易,请尊重版权】和框架创作者是哪国人没有太大关系,但能够【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net如此优雅的写出vue,也不得不令人敬佩。

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【访问 www.tangshuang.n未经授权,禁止复制转载。原创内容,盗版必究。et 获取更多精彩内容】

尤雨溪,网名尤小右,英文名Evan,毕业【版权所有,侵权必究】【未经授权禁止转载】于上海复旦附中,在美国完成大学学业,本科原创内容,盗版必究。转载请注明出处:www.tangshuang.net毕业于Colgate Universit【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。y,后在Parsons设计学院获得Des【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。ign & Technology著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】艺术硕士学位,后职于纽约Google C【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】reative Lab,现在和阿里巴巴w本文作者:唐霜,转载请注明出处。【转载请注明来源】eex合作。
本文版权归作者所有,未经授权不得转载。 这里是他的知乎主页,你可以follow他的twitter和他交流。

【原创内容,转载请注明出处】转载请注明出处:www.tangshua【作者:唐霜】【关注微信公众号:wwwtangshuangnet】ng.net【原创内容,转载请注明出处】

作为设计专业毕业的学生,即使有googl本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。e工作经历,能够写出vue这样高审美的框著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。架,除了跪服也没有其他。这里是teahour对他的语言采访,你可以近【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net距离听听大牛的声音。

【版权所有】唐霜 www.tangshu【未经授权禁止转载】转载请注明出处:www.tangshuang.netang.net【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。

vue和其他框架或库的比较

原本应该把标题取名“我为什么选择vue”【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】,但是个人认为还是严肃点好。以下内容全部【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。自官方文档,官方对vue和React、Angula著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】r、Ember、Knockout、Pol【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】ymer、Riot这些框架都进行了比较,【版权所有,侵权必究】未经授权,禁止复制转载。虽然是官方,但并没有一味夸自己好,而是进转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】行较为客观的比较,值得一读,可以读到一些【作者:唐霜】【本文首发于唐霜的博客】vue团队对其他框架的优缺点如何吸取和摒【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】弃。本文进行了重点摘抄,如果想看完整版,原创内容,盗版必究。本文作者:唐霜,转载请注明出处。请点链接进入。

未经授权,禁止复制转载。【未经授权禁止转载】转载请注明出处:www.tangshua【转载请注明来源】本文版权归作者所有,未经授权不得转载。ng.net【原创内容,转载请注明出处】

react

React 和 Vue 有许多相似之处,本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。它们都有:

【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。

React 比 Vue 生态系统和丰富的【版权所有,侵权必究】【本文首发于唐霜的博客】自定义渲染器更好。

【版权所有,侵权必究】【访问 www.tangshuang.n【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】未经授权,禁止复制转载。

在渲染用户界面的时候,DOM 的操作成本本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】是最高的,不幸的是没有库可以让这些原始操【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】作变得更快。我们能做到的最好效果就是:

【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】et 获取更多精彩内容】【本文受版权保护】
  1. 把必须的 Dom 更新降到最小。Reac【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.nett 和 Vue 都是通过 Virtual【作者:唐霜】【原创内容,转载请注明出处】 Dom 抽象层来实现这一要求,而且他们本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】都实现得一样赞。
  2. 本文作者:唐霜,转载请注明出处。【未经授权禁止转载】未经授权,禁止复制转载。
  3. 在这些 Dom 操作之上,则尽可能少地添【作者:唐霜】本文版权归作者所有,未经授权不得转载。加额外性能开销(即:纯 JavaScri【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。pt 运算)。这是 Vue 和 Reac著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】t 产生分歧之处。
  4. 著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。

JavaScript 开销直接与求算必要【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】 DOM 操作的机制相关。尽管 Vue 【作者:唐霜】【未经授权禁止转载】和 React 都使用了 Virtual【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】 Dom 实现这一点,但 Vue 的 V本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。irtual Dom 实现(复刻自 snabbdom)是更加轻量化的,因此也就比 React转载请注明出处:www.tangshuang.net【未经授权禁止转载】 的实现更高效。

【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。ang.net【版权所有】唐霜 www.tangshu【本文受版权保护】原创内容,盗版必究。ang.net

编者按:我的建议是vue和react都去【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。学,从职业角度讲,两者都有可能是未来几年【本文受版权保护】原创内容,盗版必究。风靡一时的应用级产品,各大小公司都会上相【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】应的项目;从编程的角度讲,vue更代表时原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】代的集大成者,react更代表未来。学习【版权所有,侵权必究】【本文受版权保护】而言,其实只要掌握了学习方法,其实学什么【作者:唐霜】【版权所有】唐霜 www.tangshuang.net都很快。谁先谁后?这取决于你当前的紧迫性【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】,如果你的项目中马上要用react,那就著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net先学react,但请尽量读完本书。

【访问 www.tangshuang.n未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】本文作者:唐霜,转载请注明出处。【本文受版权保护】

angular

Vue 的一些语法和 Angular 的本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。很相似(例如 v-if vs ng-if)。因为 Angular 是 Vue 早本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】期开发的灵感来源。然而,Angular 本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。中存在的许多问题,在 Vue 中已经得到【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。解决。

【关注微信公众号:wwwtangshua【本文受版权保护】【原创不易,请尊重版权】ngnet】未经授权,禁止复制转载。

在 Angular 1 中,当 watc【本文受版权保护】【未经授权禁止转载】her 越来越多时会变得越来越慢,因为作著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net用域内的每一次变化,所有 watcher【版权所有,侵权必究】【本文受版权保护】 都要重新计算。并且,如果一些 watc【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】her 触发另一个更新,脏检查循环(di【转载请注明来源】未经授权,禁止复制转载。gest cycle)可能要运行多次。A本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】ngular 用户常常要使用深奥的技术,著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。以解决脏检查循环的问题。有时没有简单的办【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】法来优化有大量 watcher 的作用域【原创内容,转载请注明出处】【作者:唐霜】

著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。

Vue 则根本没有这个问题,因为它使用基【未经授权禁止转载】【作者:唐霜】于依赖追踪的观察系统并且异步队列更新,所【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。有的数据变化都是独立触发,除非它们之间有【作者:唐霜】本文作者:唐霜,转载请注明出处。明确的依赖关系。

【本文受版权保护】【版权所有,侵权必究】【作者:唐霜】未经授权,禁止复制转载。

有意思的是,Angular 2 和 Vu【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。e 用相似的设计解决了一些 Angula未经授权,禁止复制转载。【未经授权禁止转载】r 1 中存在的问题。

【未经授权禁止转载】【未经授权禁止转载】

Angular 1 面向的是较小的应用程本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。序,Angular 2 已转移焦点,面向【未经授权禁止转载】【本文首发于唐霜的博客】的是大型企业应用。在这一点上 TypeS【本文首发于唐霜的博客】【本文首发于唐霜的博客】cript 经常会被引用,它对那些喜欢用本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。 Java 或者 C# 等类型安全的语言【关注微信公众号:wwwtangshuangnet】【作者:唐霜】的人是非常有用的。

【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】ngnet】【转载请注明来源】【原创内容,转载请注明出处】

编者按:总之,如果你以前学过使用过ang原创内容,盗版必究。本文作者:唐霜,转载请注明出处。ular,那么学vue会很快,并且觉得v本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ue非常简单。如果你以前没有学过angu原创内容,盗版必究。【原创内容,转载请注明出处】lar,直接跳过,马上学vue,等你使用本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】vue开发半年之后再去理解angular未经授权,禁止复制转载。原创内容,盗版必究。,会轻松很多。

【版权所有,侵权必究】转载请注明出处:www.tangshua【本文受版权保护】【本文首发于唐霜的博客】ng.net

Ember

编者按:不用学了,既复杂,又死板。虽然它【未经授权禁止转载】未经授权,禁止复制转载。是一个齐备的框架,里面什么都有了,但是正【转载请注明来源】本文版权归作者所有,未经授权不得转载。是因为它这样,导致它很难跟上时代。

原创内容,盗版必究。【访问 www.tangshuang.n【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】【本文受版权保护】

Knockout

Knockout 是 MVVM 领域内的转载请注明出处:www.tangshuang.net原创内容,盗版必究。先驱,并且追踪依赖。它的响应系统和 Vu【作者:唐霜】转载请注明出处:www.tangshuang.nete 也很相似。它在浏览器支持以及其他方面的表现也是让人印象深刻的。它【本文受版权保护】【作者:唐霜】最低能支持到 IE6,而 Vue 最低只【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】能支持到 IE9。

【原创内容,转载请注明出处】【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【本文首发于唐霜的博客】【本文首发于唐霜的博客】ng.net

随着时间的推移,Knockout 的发展【版权所有】唐霜 www.tangshuang.net【转载请注明来源】已有所放缓,并且略显有点老旧了。比如,它未经授权,禁止复制转载。【作者:唐霜】的组件系统缺少完备的生命周期事件方法,尽【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】管这些在现在是非常常见的。以及相比于 Vue 调用子组件的接口它的方法显得有点笨重。

【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【本文受版权保护】ngnet】【本文首发于唐霜的博客】【原创不易,请尊重版权】【原创内容,转载请注明出处】

Polymer

Polymer 是另一个由谷歌赞助的项目著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】,事实上也是 Vue 的一个灵感来源。V【版权所有,侵权必究】【原创不易,请尊重版权】ue 的组件可以粗略的类比于 Polym原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】er 的自定义元素,并且两者具有相似的开【作者:唐霜】转载请注明出处:www.tangshuang.net发风格。最大的不同之处在于,Polyme转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netr 是基于最新版的 Web Compon未经授权,禁止复制转载。原创内容,盗版必究。ents 标准之上,并且需要重量级的 p未经授权,禁止复制转载。【作者:唐霜】olyfills 来帮助工作(性能下降)【未经授权禁止转载】【本文受版权保护】,浏览器本身并不支持这些功能。相比而言,本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netVue 在支持到 IE9 的情况下并不需原创内容,盗版必究。转载请注明出处:www.tangshuang.net要依赖 polyfills 来工作。

【关注微信公众号:wwwtangshua【版权所有,侵权必究】原创内容,盗版必究。ngnet】【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【原创不易,请尊重版权】ngnet】转载请注明出处:www.tangshua未经授权,禁止复制转载。未经授权,禁止复制转载。ng.net【原创内容,转载请注明出处】

Polymer 自定义的元素是用 HTM【未经授权禁止转载】原创内容,盗版必究。L 文件来创建的,这会限制使用 Java本文版权归作者所有,未经授权不得转载。【本文受版权保护】Script/CSS(和被现代浏览器普遍【版权所有,侵权必究】【作者:唐霜】支持的语言特性)。相比之下,Vue 的单本文作者:唐霜,转载请注明出处。【转载请注明来源】文件组件允许你非常容易的使用 ES201转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】5 和你想用的 CSS 预编译处理器。

转载请注明出处:www.tangshua【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。ng.net【版权所有,侵权必究】

而 Vue 和 Web Componen本文版权归作者所有,未经授权不得转载。【本文受版权保护】t 标准进行深层次的整合也是完全可行的,未经授权,禁止复制转载。【原创内容,转载请注明出处】比如使用 Custom Elements【作者:唐霜】【本文受版权保护】、Shadow DOM 的样式封装。然而【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。在我们做出严肃的实现承诺之前,我们目前仍【版权所有,侵权必究】【作者:唐霜】在等待相关标准成熟,进而再广泛应用于主流未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。的浏览器中。

【未经授权禁止转载】【版权所有】唐霜 www.tangshu【转载请注明来源】未经授权,禁止复制转载。ang.net本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。

编者按:读者应该学习一下polymer,【关注微信公众号:wwwtangshuangnet】【本文受版权保护】主要学习它的思想,如果没有必要,可以不深著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】入学习进行开发。

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。

Riot

Riot 2.0 提供了一个类似于基于组【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net件的开发模型(在 Riot 中称之为 T著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ag),它提供了小巧精美的 API。Ri本文作者:唐霜,转载请注明出处。【作者:唐霜】ot 和 Vue 在设计理念上可能有许多【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。相似处。尽管相比 Riot ,Vue 要【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】显得重一点。

【版权所有,侵权必究】转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。ng.net【原创内容,转载请注明出处】

编者按:按照尤小右的说法,riot是很不【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net错的,但是因为它用的技术不够fashio未经授权,禁止复制转载。【原创内容,转载请注明出处】n,我也不建议花太多时间学习,除非你有一【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】个东西很需要一个更小的框架,你想更有个性本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。一点。

原创内容,盗版必究。原创内容,盗版必究。【原创内容,转载请注明出处】【原创不易,请尊重版权】

Vue实例

首先,你必须掌握一个概念,就是“vue实【关注微信公众号:wwwtangshuangnet】【本文受版权保护】例”。什么意思呢?所有的vue程序都需要转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net实例化之后使用,实例主要有两种,一个是V【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】ue实例,一个是组件实例。当然,如果你把本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】router和resource加进来,它【转载请注明来源】【关注微信公众号:wwwtangshuangnet】们也有实例,我们可以称之为插件实例。

【未经授权禁止转载】【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。

构造器

每个 Vue.js 应用都是通过构造函数【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net Vue 创建一个 Vue 的根实例 启动的:

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【未经授权禁止转载】【作者:唐霜】
var vm = new Vue({
  // 选项
})

在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net生命周期钩子等选项。全部的选项可以在 API 文档中查看。

【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】ang.net本文版权归作者所有,未经授权不得转载。

组件构造器

可以扩展 Vue 构造器,从而用预定义选项创建可复用的组件构造器。所谓组件构造器,就是创建一个组件的原型【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】类。

【未经授权禁止转载】转载请注明出处:www.tangshua【本文受版权保护】【作者:唐霜】ng.net未经授权,禁止复制转载。【本文首发于唐霜的博客】
var MyComponent = Vue.extend({
  // 扩展选项
})
// 所有的 `MyComponent` 实例都将以预定义的扩展选项被创建
var myComponentInstance = new MyComponent()

尽管可以命令式地创建扩展实例,不过在多数转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net情况下建议将组件构造器注册为一个自定义元【原创不易,请尊重版权】原创内容,盗版必究。素,然后声明式地用在模板中。我们将在后面【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】详细说明组件系统。现在你只需知道所有的 【作者:唐霜】【未经授权禁止转载】Vue.js 组件其实都是被扩展的 Vu未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.nete 实例。

本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】未经授权,禁止复制转载。

编者按:组件是vue里面重要的话题。但是原创内容,盗版必究。【本文受版权保护】对于开发者而言,其实只需要关心上面那个红【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。色的大括号里面的开发即可。组件的使用有好转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net几种,但是开发者要写的,都在这个大括号身【版权所有,侵权必究】【未经授权禁止转载】上。另外,Vue.extend之后,就是【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。一个组件构造器,实例化以后,就是一个组件【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。,下文会有一章详细介绍组件,这里暂且跳过转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。

本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】转载请注明出处:www.tangshua【转载请注明来源】【版权所有,侵权必究】ng.net【本文受版权保护】

实例属性(数据代理和响应)

每个 Vue 实例都会代理其 data 对象里所有的属性:

著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】【本文首发于唐霜的博客】
var data = { a: 1 }var app = new Vue({
  data: data
}) 

app.a === data.a // -> true // 设置属性也会影响到原始数据
app.a = 2data.a // -> 2 // ... 反之亦然
data.a = 3app.a // -> 3

注意只有这些被代理的属性是响应的。如果在实例创建之后添加新的属性到实例上著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。,它不会触发视图更新。

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】

编者按:也就是说,你得在new之前,就把【未经授权禁止转载】转载请注明出处:www.tangshuang.net所有的data都传进去。实例创建之后,其【原创不易,请尊重版权】未经授权,禁止复制转载。实可以使用$set来加入属性,也可以实现【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net响应功能。

转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】ng.net本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n原创内容,盗版必究。原创内容,盗版必究。et 获取更多精彩内容】【原创内容,转载请注明出处】

除了 data 属性, Vue 实例暴露【本文受版权保护】著作权归作者所有,禁止商业用途转载。了一些有用的实例属性与方法。这些属性与方【未经授权禁止转载】【原创内容,转载请注明出处】法都有前缀 $,以便与代理的 data 属性区分。例如【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】

【作者:唐霜】原创内容,盗版必究。
var data = { a: 1 }
var app = new Vue({
  el: '#example',
  data: data
}) 
app.$data === data // -> true
app.$el === document.getElementById('example') // -> true

实例方法

在实例里面可以自己传进去一些方法进行调用原创内容,盗版必究。原创内容,盗版必究。

【未经授权禁止转载】【原创内容,转载请注明出处】【作者:唐霜】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。ng.net
var app = new Vue({
  methods: {
    myMethod() {},
    otherMethod() {
      // 这里就可以使用this.myMethod()了
    },
  },
})
app.otherMethod() // 可以在外面调用

和this.$data一样,vue也有一著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】些以$开头的方法,比如app.$watc转载请注明出处:www.tangshuang.net【版权所有,侵权必究】h等,这些都是vue内置的方法。

著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【未经授权禁止转载】ngnet】原创内容,盗版必究。【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【本文受版权保护】ngnet】

实例属性和方法的完整列表中查阅 API 参考

本文作者:唐霜,转载请注明出处。【本文受版权保护】【原创内容,转载请注明出处】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【本文受版权保护】ng.net

模板和数据绑定

Vue的模板语法

Vue.js 使用了基于 HTML 的模【本文受版权保护】【版权所有】唐霜 www.tangshuang.net版语法,允许开发者声明式地将 DOM 绑【本文首发于唐霜的博客】【原创内容,转载请注明出处】定至底层 Vue 实例的数据。所有 Vu【转载请注明来源】【版权所有,侵权必究】e.js 的模板都是合法的 HTML ,【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。所以能被遵循规范的浏览器和 HTML 解转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】析器解析。

【版权所有,侵权必究】【未经授权禁止转载】

在底层的实现上, Vue 将模板编译成虚【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net拟 DOM 渲染函数。结合响应系统,在应【本文首发于唐霜的博客】【原创内容,转载请注明出处】用状态改变时, Vue 能够智能地计算出未经授权,禁止复制转载。【原创内容,转载请注明出处】重新渲染组件的最小代价并应用到 DOM 本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。操作上。

【版权所有,侵权必究】【未经授权禁止转载】

如果你熟悉虚拟 DOM 并且偏爱 Jav【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】aScript 的原始力量,你也可以不用【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】模板,直接写渲染(render)函数,使用可选的 JSX 语法。

【转载请注明来源】原创内容,盗版必究。

编者按:这里说的render函数和rea【未经授权禁止转载】本文作者:唐霜,转载请注明出处。ct里面是一模一样的。在上面实例化vue【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】的时候,如果你传入了一个template【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。参数,就会使用template,如果你传转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。入了一个render参数(函数),则会使转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】用这个函数来作为模板的渲染。

转载请注明出处:www.tangshua【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.netng.net【版权所有,侵权必究】【作者:唐霜】

插值

文本

数据绑定最常见的形式就是使用 “Must【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】ache” 语法(双大括号)的文本插值:

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ng.net【转载请注明来源】未经授权,禁止复制转载。
<span>Message: {{ msg }}</span>

Mustache 标签将会被替代为对应数【原创不易,请尊重版权】【原创不易,请尊重版权】据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。

【转载请注明来源】【原创不易,请尊重版权】【原创内容,转载请注明出处】

msg和你传入的data.msg是绑定的【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】,当你在操作实例的时候,把实例的data【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】.msg改变了,那么视图上的这个msg也【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。会改变。

本文作者:唐霜,转载请注明出处。【未经授权禁止转载】
var app = new Vue({
  template: '<span>Message: {{msg}}</span>',
  data: {
    msg: 'Welcome!',
  },
})
setTimeout(() => app.msg = 'Let us go!', 1000)

上面你要知道一个事实:app.$data著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。.msg === app.msg,而且由【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】于vue的响应系统,所以你直接app.msg = 'Let us go!'app.$set(app.$data, 'msg', 'Let us go')是一样的。总之,因为javascript【作者:唐霜】本文作者:唐霜,转载请注明出处。的对象是引用型数据,所以你只要使用对了引【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】用,怎么搞都是一样的。

【本文首发于唐霜的博客】【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。

纯 HTML

双大括号会将数据解释为纯文本,而非 HT【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。ML 。为了输出真正的 HTML ,你需【版权所有】唐霜 www.tangshuang.net【作者:唐霜】要使用 v-html 指令:

原创内容,盗版必究。【本文受版权保护】【版权所有】唐霜 www.tangshu【作者:唐霜】【版权所有,侵权必究】ang.net【转载请注明来源】
<div v-html="rawHtml"></div>

被插入的内容都会被当做 HTML —— 【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。数据绑定会被忽略。注意,你不能使用 v-html 来复合局部模板,因为 Vue 不是基于【本文受版权保护】转载请注明出处:www.tangshuang.net字符串的模板引擎。组件更适合担任 UI 著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。重用与复合的基本单元。

【本文受版权保护】本文版权归作者所有,未经授权不得转载。

你的站点上动态渲染的任意 HTML 可能未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容插值。

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。

属性

Mustache 不能在 HTML 属性【版权所有,侵权必究】【作者:唐霜】中使用,应使用 v-bind 指令(下文未经授权,禁止复制转载。原创内容,盗版必究。指令一章详细说):

【未经授权禁止转载】【版权所有,侵权必究】【版权所有】唐霜 www.tangshu【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netang.net
<div v-bind:id="dynamicId"></div>

这对布尔值的属性也有效 —— 如果条件被转载请注明出处:www.tangshuang.net【未经授权禁止转载】求值为 false 的话该属性会被移除:

未经授权,禁止复制转载。【访问 www.tangshuang.n【原创不易,请尊重版权】【版权所有,侵权必究】et 获取更多精彩内容】
<button v-bind:disabled="someDynamicCondition">Button</button>

使用 JavaScript 表达式

迄今为止,在我们的模板中,我们一直都只绑【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。定简单的属性键值。但实际上,对于所有的数【本文受版权保护】【本文受版权保护】据绑定, Vue.js 都提供了完全的 未经授权,禁止复制转载。【原创内容,转载请注明出处】JavaScript 表达式支持。

【版权所有】唐霜 www.tangshu【原创内容,转载请注明出处】【原创不易,请尊重版权】ang.net【未经授权禁止转载】【本文首发于唐霜的博客】
{{ number + 1 }}{{ ok ? 'YES' : 'NO' }}{{ message.split('').reverse().join('') }}<div v-bind:id="'list-' + id"></div>

这些表达式会在所属 Vue 实例的数据作【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。用域下作为 JavaScript 被解析原创内容,盗版必究。原创内容,盗版必究。。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。

【作者:唐霜】未经授权,禁止复制转载。【关注微信公众号:wwwtangshua【本文首发于唐霜的博客】原创内容,盗版必究。ngnet】
<!-- 这是语句,不是表达式 -->{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->{{ if (ok) { return message } }}

模板表达式都被放在沙盒中,只能访问全局变【原创不易,请尊重版权】原创内容,盗版必究。量的一个白名单,如 MathDate 。你不应该在模板表达式中试图访问用户定转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。义的全局变量。

原创内容,盗版必究。原创内容,盗版必究。

计算属性

什么是计算属性

模板内的表达式是非常便利的,但是它们实际【转载请注明来源】本文版权归作者所有,未经授权不得转载。上只用于简单的运算。在模板中放入太多的逻【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。辑会让模板过重且难以维护。例如:

【未经授权禁止转载】【转载请注明来源】
<div id="example">{{ message.split('').reverse().join('') }}</div>

在这种情况下,模板不再简单和清晰。在意识【本文受版权保护】【原创不易,请尊重版权】到这是反向显示 message 之前,你【作者:唐霜】【版权所有】唐霜 www.tangshuang.net不得不再次确认第二遍。当你想要在模板中多【本文受版权保护】【版权所有,侵权必究】次反向显示 message 的时候,问题本文作者:唐霜,转载请注明出处。【转载请注明来源】会变得更糟糕。

【未经授权禁止转载】转载请注明出处:www.tangshua【原创不易,请尊重版权】【本文受版权保护】ng.net

这就是对于任何复杂逻辑,你都应当使用计算属性的原因。

未经授权,禁止复制转载。转载请注明出处:www.tangshua未经授权,禁止复制转载。【本文首发于唐霜的博客】ng.net【转载请注明来源】【本文受版权保护】

所谓计算属性,就是跟ES5的getter转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net一样的,用function来定义个属性,转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。当你获取这个属性的时候,实际上是要执行这【作者:唐霜】【本文受版权保护】个function,执行function【本文首发于唐霜的博客】【版权所有,侵权必究】的过程就是计算过程,所以也就叫计算属性。未经授权,禁止复制转载。【原创内容,转载请注明出处】所有的计算属性被放在computed里面【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】,computed和data, meth转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。ods同级,如下:

转载请注明出处:www.tangshua原创内容,盗版必究。【作者:唐霜】ng.net【访问 www.tangshuang.n【原创不易,请尊重版权】【原创内容,转载请注明出处】et 获取更多精彩内容】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。ng.net
var app = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // a computed getter
    reversedMessage: function () {
      // `this` points to the vm instance
      return this.message.split('').reverse().join('')
    }
  }
})

在使用reversedMessage的时【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。候,把它当做一个属性,app.reversedMessage就可以了,在模板中:

【本文首发于唐霜的博客】【版权所有,侵权必究】【原创不易,请尊重版权】
<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

Vue模板中的变量,都是实例的属性,比如【作者:唐霜】【本文受版权保护】这里面的message -> ap著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。p.message,还记得上面的数据代理著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。吗?app.message === ap【版权所有,侵权必究】【作者:唐霜】p.$data.message === 【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】传入的data.message。

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。

你可以像绑定普通属性一样在模板中绑定计算【作者:唐霜】转载请注明出处:www.tangshuang.net属性。 Vue 知道 vm.reversedMessage 依赖于 vm.message ,因此vm.message 发生改变时,所有依赖于 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了【本文受版权保护】【关注微信公众号:wwwtangshuangnet】这种依赖关系:计算属性的 getter 著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。是没有副作用,这使得它易于测试和推理。

【作者:唐霜】转载请注明出处:www.tangshua【本文受版权保护】【本文受版权保护】ng.net

计算缓存 vs Methods

你可能已经注意到我们可以通过调用表达式中著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。的 method 来达到同样的效果:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【本文受版权保护】ngnet】
<p>Reversed message: "{{ reversedMessage() }}"</p>
// in component -------------------------------------
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

我们可以将同一函数定义为一个 metho转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。d 而不是一个计算属性。对于最终的结果,本文作者:唐霜,转载请注明出处。原创内容,盗版必究。两种方式确实是相同的。然而,不同的是计算【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net属性是基于它们的依赖进行缓存的。计算属性【原创不易,请尊重版权】【原创内容,转载请注明出处】只有在它的相关依赖发生改变时才会重新求值【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】。这就意味着只要 message 还没有【本文受版权保护】【原创内容,转载请注明出处】发生改变,多次访问 reversedMe本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netssage 计算属性会立即返回之前的计算未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】结果,而不必再次执行函数。

【关注微信公众号:wwwtangshua【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。ngnet】转载请注明出处:www.tangshua【原创不易,请尊重版权】【版权所有,侵权必究】ng.net转载请注明出处:www.tangshua【转载请注明来源】【版权所有,侵权必究】ng.net【版权所有,侵权必究】

这也同样意味着下面的计算属性将不再更新,【转载请注明来源】【未经授权禁止转载】因为 Date.now() 不是响应式依【未经授权禁止转载】原创内容,盗版必究。赖:

本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。ngnet】【版权所有,侵权必究】
computed: {
  now: function () {
    return Date.now()
  }
}

相比而言,只要发生重新渲染,method未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】 调用总会执行该函数。

【转载请注明来源】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】

我们为什么需要缓存?假设我们有一个性能开【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。销比较大的的计算属性 A ,它需要遍历一【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。个极大的数组和做大量的计算。然后我们可能著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】有其他的计算属性依赖于 A 。如果没有缓【本文首发于唐霜的博客】【版权所有,侵权必究】存,我们将不可避免的多次执行 A 的 g【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】etter!如果你不希望有缓存,请用 m【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】ethod 替代。

【版权所有,侵权必究】【原创不易,请尊重版权】【本文首发于唐霜的博客】

计算 setter

计算属性默认只有 getter ,不过在【版权所有,侵权必究】【原创不易,请尊重版权】需要时你也可以提供一个 setter :

本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.netet 获取更多精彩内容】【访问 www.tangshuang.n【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】
// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

现在在运行 vm.fullName = 未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。‘John Doe̵转载请注明出处:www.tangshuang.net【版权所有,侵权必究】7; 时, setter 会被调用, v未经授权,禁止复制转载。【未经授权禁止转载】m.firstName 和 vm.las【本文首发于唐霜的博客】【转载请注明来源】tName 也相应地会被更新。

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu原创内容,盗版必究。【转载请注明来源】ang.net

观察 Watchers

在Vue里面有个方法,可以用来监听实例属【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。性的变化,就是watcher,如果你用过【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。angular的话,肯定知道watche著作权归作者所有,禁止商业用途转载。【转载请注明来源】r是什么。

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【转载请注明来源】

什么是watch

watch是和data, methods【本文首发于唐霜的博客】未经授权,禁止复制转载。, computed同级的一个参数,你可【本文受版权保护】本文作者:唐霜,转载请注明出处。以在watch里面规定你要watch的属本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】性,当这些属性发生变化的时候,它会执行对本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。应的那个函数。栗子:

【本文首发于唐霜的博客】未经授权,禁止复制转载。【版权所有,侵权必究】【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。ang.net
var app = new Vue({
  data: {
    message: '',
    msg: '',
  },
  watch: {
    message: function() { // 当app.$data.message发生变化的时候,执行这个函数
      this.msg = 'Changed!'
    },
  },
})

虽然计算属性在大多数情况下更合适,但有时未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net也需要一个自定义的 watcher 。这原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。是为什么 Vue 提供一个更通用的方法通转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。过 watch 选项,来响应数据的变化。本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。当你想要在数据变化响应时,执行异步操作或【原创不易,请尊重版权】【本文首发于唐霜的博客】开销较大的操作,这是很有用的。

【原创内容,转载请注明出处】未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu原创内容,盗版必究。【未经授权禁止转载】ang.net

例如:

【原创不易,请尊重版权】【原创内容,转载请注明出处】【版权所有,侵权必究】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。ng.net
<div id="watch-example">
  <p>Ask a yes/no question:<input v-model="question"></p><p>{{ answer }}</p>
</div>
<!-- Since there is already a rich ecosystem of ajax libraries -->
<!-- and collections of general-purpose utility methods, Vue core -->
<!-- is able to remain small by not reinventing them. This also -->
<!-- gives you the freedom to just use what you're familiar with. -->
<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: { 
    // 如果 question 发生改变,这个函数就会运行
    question: function (newQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.getAnswer()
    }
  },
  methods: { 
   // _.debounce 是一个通过 lodash 限制操作频率的函数。 
   // 在这个例子中,我们希望限制访问yesno.wtf/api的频率 
   // ajax请求直到用户输入完毕才会发出 
   // 学习更多关于 _.debounce function (and its cousin
   // _.throttle), 参考: https://lodash.com/docs#debounce
   getAnswer: _.debounce(function () {
     var vm = this
     if (this.question.indexOf('?') === -1) {
       vm.answer = 'Questions usually contain a question mark. ;-)'
       return
     }
     vm.answer = 'Thinking...'
     axios.get('https://yesno.wtf/api')
       .then(function (response) {
         vm.answer = _.capitalize(response.data.answer)
       })
       .catch(function (error) {
         vm.answer = 'Error! Could not reach the API. ' + error
       })
    },500)// 这是我们为用户停止输入等待的毫秒数
  }
})</script>

在这个示例中,使用 watch 选项允许【转载请注明来源】著作权归作者所有,禁止商业用途转载。我们执行异步操作(访问一个 API),限【转载请注明来源】【作者:唐霜】制我们执行该操作的频率,并在我们得到最终本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】结果前,设置中间状态。这是计算属性无法做著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net到的。

【访问 www.tangshuang.n【本文受版权保护】【原创不易,请尊重版权】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。ang.net【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【作者:唐霜】ang.net转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】ng.net

除了 watch 选项之外,您还可以使用 vm.$watch API 命令。

转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】ng.net转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。ng.net

Computed 属性 vs Watched 属性

Vue 确实提供了一种更通用的方式来观察【本文首发于唐霜的博客】【本文首发于唐霜的博客】和响应 Vue 实例上的数据变动:wat转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ch 属性。当你有一些数据需要随着其它数本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。据变动而变动时,你很容易滥用 watch【版权所有】唐霜 www.tangshuang.net【作者:唐霜】——特别是如果你之前使用过 Angula【原创不易,请尊重版权】【作者:唐霜】rJS。然而,通常更好的想法是使用 co【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】mputed 属性而不是命令式的 wat【原创内容,转载请注明出处】【未经授权禁止转载】ch 回调。细想一下这个例子:

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。et 获取更多精彩内容】【未经授权禁止转载】
<div id="demo">{{ fullName }}</div>var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

上面代码是命令式的和重复的。将它与 co【原创内容,转载请注明出处】原创内容,盗版必究。mputed 属性的版本进行比较:

【原创不易,请尊重版权】未经授权,禁止复制转载。未经授权,禁止复制转载。【原创内容,转载请注明出处】
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

好得多了,不是吗?

【本文首发于唐霜的博客】未经授权,禁止复制转载。【本文受版权保护】

指令

什么是指令?

指令(Directives)是带有 v-著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】 前缀的特殊属性。指令属性的值预期是单一【转载请注明来源】【作者:唐霜】 JavaScript 表达式(除了 v未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】-for,之后再讨论)。指令的职责就是当【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。其表达式的值改变时相应地将某些行为应用到【版权所有】唐霜 www.tangshuang.net【转载请注明来源】 DOM 上。让我们回顾一下在介绍里的例【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】子:

【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
<p v-if="seen">Now you see me</p>

这里, v-if 指令将根据表达式 se【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.neten 的值的真假来移除/插入 <p【作者:唐霜】【本文首发于唐霜的博客】> 元素。而v-if就是指令。vu著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。e里面有很多内置的指令,你还可以自定义指原创内容,盗版必究。原创内容,盗版必究。令。

【原创内容,转载请注明出处】未经授权,禁止复制转载。原创内容,盗版必究。【未经授权禁止转载】

Vue2提供的所有指令可以在这里看到,主要有v-text,v-html,v-show,v-if,v-else,v-else-if,v-for,v-on,v-bind,v-model,v-pre,v-cloak,v-once。因为指令还挺重要的,所以本书会全部解释未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。一遍。

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。

指令怎么用?

只需要直接将指令作为html元素的属性来原创内容,盗版必究。未经授权,禁止复制转载。使用就可以了,例如<div v-if="hasChild"></div>。指令只对当前所在的这个元素起作用,它在本文作者:唐霜,转载请注明出处。【转载请注明来源】哪个元素上,就哪个元素做出对应的动作。

原创内容,盗版必究。【未经授权禁止转载】

该属性的值被称为指令的“表达式”,例如v【未经授权禁止转载】【原创不易,请尊重版权】-if=”isExists&【转载请注明来源】【未经授权禁止转载】#8221;,isExists对应thi【转载请注明来源】【未经授权禁止转载】s.isExists,既然是表达式,就有本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。返回值,它的值被传给指令,指令根据表达式【本文首发于唐霜的博客】【作者:唐霜】的返回结果来决定所在的元素进行怎样的操作转载请注明出处:www.tangshuang.net【本文受版权保护】。表达式里面的变量,都是来自vue实例的【原创不易,请尊重版权】未经授权,禁止复制转载。属性。

【转载请注明来源】【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【本文首发于唐霜的博客】ngnet】著作权归作者所有,禁止商业用途转载。

指令也可以有参数,主要是指v-on和v-【作者:唐霜】本文作者:唐霜,转载请注明出处。bind这两个指令,它们后面跟上一个冒号未经授权,禁止复制转载。【原创不易,请尊重版权】,冒号和等号之间的内容就是参数,例如v-【本文受版权保护】【未经授权禁止转载】bind:src=”src”,红【作者:唐霜】【原创内容,转载请注明出处】色的src就是参数。

著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

一些指令还有修饰符,用.符号连接,主要是【转载请注明来源】【关注微信公众号:wwwtangshuangnet】绑定型指令会有。

【原创不易,请尊重版权】原创内容,盗版必究。原创内容,盗版必究。

内容型指令

v-text

<span v-text="msg"></span><!-- 和下面的一样 --><span>{{msg}}</span>

v-html

<div v-html="html"></div>

和v-text不一样,v-html真的是【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】完完全全innerHTML。为了安全起见【原创内容,转载请注明出处】【原创内容,转载请注明出处】,不要用。

著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

条件判断型指令

v-if

<div v-if="is"></div>

如果this.is值为真,则当前元素会被【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。插入到dom中,如果is为假,当前元素会转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net被从dom中移除。因此,v-if是有do本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】m消耗的,使用时不应该反复更改is值。

【原创不易,请尊重版权】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。ng.net

v-show

<div v-show="is"></div>

v-show和v-if是一样的用法,但是著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net相对于v-if不一样。v-if是会把这个【转载请注明来源】【作者:唐霜】元素从dom中移走或者插入的,但是v-s本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。how是不会的,is为false的时候,【转载请注明来源】本文作者:唐霜,转载请注明出处。会给这个元素加一个display:non本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】e,仅仅是隐藏这个元素,所以不会有dom【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】的消耗。

转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netng.net转载请注明出处:www.tangshua【未经授权禁止转载】【本文受版权保护】ng.net本文版权归作者所有,未经授权不得转载。

v-else

必须跟v-if一起用。并且不需要表达式,【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】还记得上面说的“表达式”是什么意思吗?

转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。【作者:唐霜】ng.net【转载请注明来源】原创内容,盗版必究。
<div v-if="Math.random() > 0.5"> Now you see me</div><div v-else> Now you don't</div>

v-else-if

2.1.0版本新增的指令,所以2.0版本著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。是没有的,使用的时候注意。前一兄弟元素必【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。须有 v-if 或 v-else-if。【本文首发于唐霜的博客】【本文受版权保护】表示 v-if 的 “else if 块本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】”。可以链式调用。

本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。
<div v-if="type === 'A'">A</div><div v-else-if="type === 'B'">B</div><div v-else-if="type === 'C'">C</div><div v-else>Not A/B/C</div>

循环调用型指令

v-for

基于源数据多次渲染元素或模板块。也就是说转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】,跟前面的指令不一样,上面的指令当前元素转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。只会出现0次或1次,而v-for可以让当【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net前元素重复渲染。此指令之值,必须使用特定【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net语法 alias in expressi【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。on ,为当前遍历的元素提供别名:

【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【转载请注明来源】ang.net【版权所有,侵权必究】
<div v-for="item in items">{{ item.text }}</div>

另外也可以为数组索引指定别名(或者用于对【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】象的键):

本文作者:唐霜,转载请注明出处。【未经授权禁止转载】【转载请注明来源】
<div v-for="(item, index) in items"></div><div v-for="(val, key) in object"></div><div v-for="(val, key, index) in object"></div>

v-for 默认行为试着不改变整体,而是【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。替换元素。迫使其重新排序的元素,您需要提本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】供一个 key 的特殊属性:

原创内容,盗版必究。原创内容,盗版必究。【作者:唐霜】
<div v-for="item in items" :key="item.id">{{ item.text }}</div>

关于这个key,Vue为了确保在virt未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】ual dom里面,更新的时候用来做对比著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net用的。如果不使用key,Vue会使用一种【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】最大限度减少动态元素并且尽可能的尝试修复【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。/再利用相同类型元素的算法。使用key,本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。它会基于key的变化重新排列元素顺序,并转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。且会移除key不存在的元素。具体可以阅读这里。下文“特殊属性”一节会讲到。

【未经授权禁止转载】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【作者:唐霜】ng.net未经授权,禁止复制转载。【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】

绑定型指令

绑定型指令会有参数,也就是有冒号,参数是【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。绑定的属性或事件。绑定型指令还有修饰符。

未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

v-bind

动态地绑定一个或多个attr或prop属未经授权,禁止复制转载。【作者:唐霜】性。简单的说就是,通过v-bind绑定一原创内容,盗版必究。本文作者:唐霜,转载请注明出处。个属性,这个属性可以是html原本有的,【本文受版权保护】未经授权,禁止复制转载。也可以是某些特殊的,绑定的表达式的值赋值【版权所有,侵权必究】【本文受版权保护】给这个属性。例如:<img v-bind:src="imgSrc">,imgSrc是实例的imgSrc属性t本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。his.imgSrc,它的值将会作为字符本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。串作为属性src的值。绑定之后,如果th【版权所有,侵权必究】转载请注明出处:www.tangshuang.netis.imgSrc更改,那么src的值也【本文首发于唐霜的博客】【本文受版权保护】随着更改,图片也就会换成另外一幅。

【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】et 获取更多精彩内容】

在绑定 class 或 style 特性【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】时,支持其它类型的值,如数组或对象。下文未经授权,禁止复制转载。原创内容,盗版必究。会详细讲class和style属性的问题【作者:唐霜】本文版权归作者所有,未经授权不得转载。

未经授权,禁止复制转载。原创内容,盗版必究。【未经授权禁止转载】

在绑定 prop 时,prop 必须在子原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】组件中声明,这你得读到组件那一章才会了解转载请注明出处:www.tangshuang.net【版权所有,侵权必究】什么是自组件,以及自组件的props。

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】

没有参数时,可以绑定到一个包含键值对的对著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net象。注意此时 class 和 style【版权所有,侵权必究】【版权所有,侵权必究】 绑定不支持数组和对象。

【原创内容,转载请注明出处】【作者:唐霜】【关注微信公众号:wwwtangshua【作者:唐霜】【版权所有】唐霜 www.tangshuang.netngnet】

v-bind:可以缩写成单独的一个冒号:【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】

【原创内容,转载请注明出处】【原创内容,转载请注明出处】

修饰符:

【版权所有】唐霜 www.tangshu【原创不易,请尊重版权】【本文受版权保护】ang.net【作者:唐霜】【本文受版权保护】

示例:

【原创不易,请尊重版权】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。原创内容,盗版必究。ng.net原创内容,盗版必究。
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
<!-- with inline string concatenation -->
<img :src="'/path/to/images/' + fileName">
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 绑定一个有属性的对象 --><div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- 通过 prop 修饰符绑定 DOM 属性 --><div v-bind:text-content.prop="text"></div>
<!-- prop 绑定. “prop” 必须在 my-component 中声明。 -->
<my-component :prop="someThing"></my-component>
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>

.camel 修饰符允许在使用 DOM 【本文受版权保护】【未经授权禁止转载】模板时将 v-bind 属性名称驼峰化,【本文受版权保护】本文版权归作者所有,未经授权不得转载。例如 SVG 的 viewBox 属性:

本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【转载请注明来源】本文版权归作者所有,未经授权不得转载。
<svg :view-box.camel="viewBox"></svg>

v-on

绑定事件监听器。事件类型由参数指定。表达原创内容,盗版必究。原创内容,盗版必究。式可以是一个方法的名字或一个内联语句,如本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】果没有修饰符也可以省略。
【原创内容,转载请注明出处】 用在普通元素上时,只能监听 原生 DO本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】M 事件。用在自定义元素组件上时,也可以【原创不易,请尊重版权】原创内容,盗版必究。监听子组件触发的自定义事件。关于这个“子未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net组件的自定义事件”也可以在下文的“组件”【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。一章学到。

【转载请注明来源】【本文受版权保护】【本文受版权保护】

在监听原生 DOM 事件时,方法以事件为【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net唯一的参数。如果使用内联语句,语句可以访未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。问一个 $event 属性: v-on:【未经授权禁止转载】未经授权,禁止复制转载。click=”handle(本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net‘ok’, $e【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。vent)”。

未经授权,禁止复制转载。【版权所有,侵权必究】【原创不易,请尊重版权】

v-on:可以缩写成@。

转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。ng.net原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【原创内容,转载请注明出处】ang.net

修饰符:

未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。ngnet】

示例:

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【版权所有,侵权必究】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。ng.net
<!-- 方法处理器 -->
<button v-on:click="doThis"></button>
<!-- 内联语句 -->
<button v-on:click="doThat('hello', $event)"></button>
<!-- 缩写 -->
<button @click="doThis"></button>
<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">
<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
<!-- 点击回调只会触发一次 -->
<button v-on:click.once="doThis"></button>

还有更多的修饰符:

【作者:唐霜】【原创内容,转载请注明出处】

这些修饰符是跟键盘相关的,主要是在一些输本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。入相关的元素上可以使用。

原创内容,盗版必究。【版权所有,侵权必究】

v-model

在表单控件或者组件上创建双向绑定。它会根未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net据控件类型自动选取正确的方法来更新元素。著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】尽管有些神奇,但 v-model 本质上【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。不过是语法糖,它负责监听用户的输入事件以本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net更新数据,并特别处理一些极端的例子。

【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】【原创内容,转载请注明出处】

v-model 并不关心表单控件初始化所未经授权,禁止复制转载。【原创不易,请尊重版权】生成的值。因为它会选择 Vue 实例数据【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】来作为具体的值。

【本文首发于唐霜的博客】未经授权,禁止复制转载。未经授权,禁止复制转载。

对于要求 IME (如中文、 日语、 韩未经授权,禁止复制转载。【原创不易,请尊重版权】语等) 的语言,你会发现那v-model著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net不会在 ime 构成中得到更新。如果你也【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】想实现更新,请使用 input事件。

未经授权,禁止复制转载。【作者:唐霜】未经授权,禁止复制转载。

编者按:这个指令超级复杂,它一定会跟表单原创内容,盗版必究。原创内容,盗版必究。控件联系在一起。所以要事先认真解释一下。【转载请注明来源】【本文首发于唐霜的博客】首先,要理解双向绑定的概念。非常简单的说转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】,就是包含了两种绑定。第一种就是v-bi【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。nd的绑定,v-bind绑定之后,如果v【版权所有,侵权必究】【本文首发于唐霜的博客】ue实例对应的属性变化了,视图也会跟着改【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。变。第二种是反过来的,是视图上的改变会导未经授权,禁止复制转载。【本文受版权保护】致vue实例对应的属性的变化。视图怎么变未经授权,禁止复制转载。【本文首发于唐霜的博客】呢?比如在input, textarea转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net中输入内容,通过点击,切换radio, 【本文受版权保护】本文作者:唐霜,转载请注明出处。checkbox, select的选项。【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】这就是双向绑定。

原创内容,盗版必究。【版权所有】唐霜 www.tangshu【转载请注明来源】本文作者:唐霜,转载请注明出处。ang.net

v-model因为只会用在表单控件上,所【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。以有关内容都在下面的《表单控件绑定》一章【本文首发于唐霜的博客】【转载请注明来源】中详解。

【本文受版权保护】【本文受版权保护】

为了区别v-bind和v-model,我【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net还专门写了一篇文章,你可以在看完这里之后再读一下。

【本文首发于唐霜的博客】【版权所有,侵权必究】

补充:<input v-model转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net=”something原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。221;>其实是<input【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。 v-bind:value=”【作者:唐霜】【原创不易,请尊重版权】;something” v-【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.neton:input=”some【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。thing = $event.targe本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】t.value”>的语著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】法糖,也就是说v-model本身就已经包本文作者:唐霜,转载请注明出处。原创内容,盗版必究。含了v-bind,所以当v-bind:v【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netalue, v-on:input和v-m著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。odel同时出现在一个input上时,这【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】个v-bind, v-on会失效。这在下未经授权,禁止复制转载。【转载请注明来源】文会反复出现,如果你此刻没有理解,可以等【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。到下面阅读到相关内容之后再反过来思考。

【本文受版权保护】转载请注明出处:www.tangshua【作者:唐霜】【版权所有,侵权必究】ng.net【本文首发于唐霜的博客】
原创内容,盗版必究。转载请注明出处:www.tangshua未经授权,禁止复制转载。【原创内容,转载请注明出处】ng.net未经授权,禁止复制转载。【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ngnet】

控制型指令

还有内置指令可以实现在渲染过程中暂时挂起未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。当前指令所在的元素,或者改变vue默认的【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】渲染机制。

【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。【未经授权禁止转载】ang.net【原创内容,转载请注明出处】【原创内容,转载请注明出处】

v-pre

不进行模板编译的部分。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。
<span v-pre>{{ this will not be compiled }}</span>

里面的{{}}不会被认为是js表达式编译【作者:唐霜】著作权归作者所有,禁止商业用途转载。成html,而是原模原样的展示出来。

【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【作者:唐霜】ngnet】本文作者:唐霜,转载请注明出处。

v-once

只渲染元素和组件一次。随后的重新渲染,元本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。素/组件及其所有的子节点将被视为静态内容著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】并跳过。这可以用于优化更新性能。

【访问 www.tangshuang.n【版权所有,侵权必究】原创内容,盗版必究。et 获取更多精彩内容】【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ngnet】
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once><h1>comment</h1><p>{{msg}}</p></div>
<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>
<!-- v-for 指令-->
<ul><li v-for="i in list" v-once>{{i}}</li></ul>

也就是说,once让渲染失去了数据绑定机【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net制,只有在第一次渲染的时候,会获取当时的【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】变量对应的数据进行渲染,渲染结束之后,将【转载请注明来源】未经授权,禁止复制转载。不再跟着数据变化而变化。

原创内容,盗版必究。【原创不易,请尊重版权】转载请注明出处:www.tangshua【本文受版权保护】原创内容,盗版必究。ng.net原创内容,盗版必究。

这个指令有的时候非常有用。比如一些组件并【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。不需要跟着数据变化而变化的时候。

【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。

v-cloak

这个指令保持在元素上直到关联实例结束编译【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】。和 CSS 规则如 [v-cloak]本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】 { display: none } 一【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】起用时,这个指令可以隐藏未编译的 Mus【原创内容,转载请注明出处】【本文首发于唐霜的博客】tache 标签直到实例准备完毕。

【本文受版权保护】本文作者:唐霜,转载请注明出处。
[v-cloak] {  display: none;}

<div v-cloak>
  {{ message }}
</div>

其实也就是一个普通的属性,当编译结束的时【未经授权禁止转载】【版权所有,侵权必究】候,就把这个属性移除掉。所以上面那个cs【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。s,使得这些有v-cloak属性的元素全本文作者:唐霜,转载请注明出处。【转载请注明来源】部先隐藏起来,最后当v-cloak被移除【本文受版权保护】【版权所有,侵权必究】的时候,这些元素就显示出来了。为什么要有【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】这么一个奇怪的属性呢?因为你要知道,{{【本文受版权保护】【原创内容,转载请注明出处】message}}在原始的html中是字【原创不易,请尊重版权】【未经授权禁止转载】符串,是会显示在界面中的。如果你的浏览器原创内容,盗版必究。【转载请注明来源】编译模板速度慢,或者用户网速慢,vue代【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】码半天没加载完,那么用户就会看到这些奇怪转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。的{{}},而如果使用一个v-cloak转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】属性,就可以把这些内容事先隐藏起来,不让未经授权,禁止复制转载。【作者:唐霜】用户看到。

【作者:唐霜】本文作者:唐霜,转载请注明出处。【未经授权禁止转载】【原创内容,转载请注明出处】

自定义指令

vue里你还可以自定义指令,它们和内置指【未经授权禁止转载】未经授权,禁止复制转载。令一样,以v-开头。开发自己的指令之前,【本文受版权保护】本文作者:唐霜,转载请注明出处。你需要理解指令到底是拿来干什么的,而不要未经授权,禁止复制转载。【本文受版权保护】把所有的功能都开发成指令来用。

【原创不易,请尊重版权】【本文受版权保护】

创建指令

让我们来创建一个指令:当页面加载时,元素原创内容,盗版必究。【转载请注明来源】将获得焦点。事实上,你访问后还没点击任何【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net内容,input 就获得了焦点。我们希望本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net使用的时候用v-focus来作为标识符。

本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】ang.net【关注微信公众号:wwwtangshua【作者:唐霜】【本文受版权保护】ngnet】
new Vue({
  directives: {
    focus: {
      inserted(el) {
        el.focus()
      },
    },
  },
})

这样我们我们就创建了v-focus指令,【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。在模板中,就可以这样使用:

【本文首发于唐霜的博客】【本文首发于唐霜的博客】
<input v-focus>

这样当页面打开的时候,这个input就会原创内容,盗版必究。原创内容,盗版必究。自动获取焦点。

【本文首发于唐霜的博客】【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【转载请注明来源】ngnet】【版权所有】唐霜 www.tangshu【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。ang.net著作权归作者所有,禁止商业用途转载。

钩子函数

你可以看到上面的定义一个指令的结构:在实著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】力参数中传入directives,在di【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。rectives里面就是所有的自定义指令【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。,focus就是指令的名称,focus里【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。面会加入多个方法函数,这些函数就是钩子函本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net数,每一个钩子函数都会在不同的时刻执行,【本文受版权保护】【关注微信公众号:wwwtangshuangnet】从而实现你想要的功能。

本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】【本文首发于唐霜的博客】ngnet】本文作者:唐霜,转载请注明出处。

指令定义函数提供了几个钩子函数(可选):

【版权所有】唐霜 www.tangshu原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】ang.net本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n原创内容,盗版必究。原创内容,盗版必究。et 获取更多精彩内容】

钩子函数的参数

钩子函数被赋予了以下参数:

【原创内容,转载请注明出处】未经授权,禁止复制转载。

除了 el 之外,其它参数都应该是只读的【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。,尽量不要修改他们。如果需要在钩子之间共【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。享数据,建议通过元素的 dataset 来进行。

【版权所有】唐霜 www.tangshu原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netang.net【原创不易,请尊重版权】【版权所有,侵权必究】
<div id="hook-arguments-example" v-demo:hello.a.b="message"></div>
Vue.directive('demo', {  bind: function (el, binding, vnode) {    var s = JSON.stringify    el.innerHTML =      'name: '       + s(binding.name) + '<br>' +      'value: '      + s(binding.value) + '<br>' +      'expression: ' + s(binding.expression) + '<br>' +      'argument: '   + s(binding.arg) + '<br>' +      'modifiers: '  + s(binding.modifiers) + '<br>' +      'vnode keys: ' + Object.keys(vnode).join(', ')  }})new Vue({  el: '#hook-arguments-example',  data: {    message: 'hello!'  }})

函数简写

大多数情况下,我们可能想在 bind 和【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】 update 钩子上做重复动作,并且不转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net想关心其它的钩子函数。可以这样写:

【本文受版权保护】【本文受版权保护】【原创不易,请尊重版权】【作者:唐霜】
Vue.directive('color-swatch', function (el, binding) {  el.style.backgroundColor = binding.value})

对象字面量

如果指令需要多个值,可以传入一个 Jav本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】aScript 对象字面量。记住,指令函未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net数能够接受所有合法类型的 JavaScr未经授权,禁止复制转载。【原创不易,请尊重版权】ipt 表达式。

【作者:唐霜】著作权归作者所有,禁止商业用途转载。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>Vue.directive('demo', function (el, binding) {  console.log(binding.value.color) // => "white"  console.log(binding.value.text)  // => "hello!"})

编者按:
【转载请注明来源】 本书到目前为止,所有的方法都是在局部进未经授权,禁止复制转载。【本文首发于唐霜的博客】行定义,而没有进行全局定义,在vue里面【本文受版权保护】【作者:唐霜】,指令可以通过全局方法Vue.direc未经授权,禁止复制转载。原创内容,盗版必究。tives()来定义,也可以在实例参数、未经授权,禁止复制转载。原创内容,盗版必究。组件参数中加入directives来进行原创内容,盗版必究。【原创不易,请尊重版权】局部定义。局部定义就是说只有在当前这个实本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net例的模板内可以使用指令,而全局定义则可以【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。让所有模板都可以使用这个指令。除了指令,本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。还有下文要提的过滤器也有这两种定义方式。【转载请注明来源】【未经授权禁止转载】但为了增加学习曲线的平滑度,在前面几章都【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】是主要提到局部定义。后面会有专门的章节来【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net阐述全局和局部问题。

本文版权归作者所有,未经授权不得转载。【转载请注明来源】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【作者:唐霜】ang.net【原创内容,转载请注明出处】
本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

过滤器

什么是过滤器?

什么是过滤器呢?你用过一些模板引擎的话可【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net能知道,比如{{name | toUpp未经授权,禁止复制转载。未经授权,禁止复制转载。erCase}},通过一个管道符号,后面【版权所有,侵权必究】【本文受版权保护】跟上一个函数,对前面的变量进行输出前的处本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net理。

【作者:唐霜】【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【本文首发于唐霜的博客】ang.net

Vue 2.x 中,过滤器只能在 mus转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。tache 绑定和 v-bind 表达式著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。(从 2.1.0 开始支持)中使用,因为【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。过滤器设计目的就是用于文本转换。为了在其转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】他指令中实现更复杂的数据变换,你应该使用【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。计算属性。

【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】ang.net原创内容,盗版必究。【作者:唐霜】【作者:唐霜】
<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div v-bind:id="rawId | formatId"></div>

过滤器可以串联:

【访问 www.tangshuang.n【本文受版权保护】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【作者:唐霜】ang.net
{{ message | filterA | filterB }}

过滤器是 JavaScript 函数,因【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】此可以接受参数:

【本文受版权保护】本文作者:唐霜,转载请注明出处。
{{ message | filterA('arg1', arg2) }}

这里,字符串 ‘arg1&#【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net8217; 将传给过滤器作为第二个参数,【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】 arg2 表达式的值将被求值然后传给过【未经授权禁止转载】【版权所有,侵权必究】滤器作为第三个参数。

【原创内容,转载请注明出处】【作者:唐霜】

自定义过滤器

从vue2.0开始,vue不再内置过滤器【本文首发于唐霜的博客】【版权所有,侵权必究】,以前很多过滤器可以直接使用,比如upp【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netercase等。现在不能直接用了,但是我本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net们可以自己自定义。过滤器函数总接受表达式【原创不易,请尊重版权】【本文受版权保护】的值作为第一个参数。

【原创内容,转载请注明出处】【版权所有,侵权必究】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。ang.net
new Vue({
  // ...
  filters: {
    capitalize: function (value) { // 注意,这里的参数上面说过了,可以新增其他参数的
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})

使用很简单,和上面一样。

【原创内容,转载请注明出处】【版权所有,侵权必究】原创内容,盗版必究。
{{userName | capitalize}}

总之,把你自己的过滤器放在filters【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。变量中。

转载请注明出处:www.tangshua【作者:唐霜】【原创内容,转载请注明出处】ng.net著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】

Vue2.0把过滤器这块移除是有道理的,转载请注明出处:www.tangshuang.net【未经授权禁止转载】他们希望你更多使用computed,而不【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。是过滤器。

【版权所有,侵权必究】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【转载请注明来源】ng.net【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netngnet】原创内容,盗版必究。

表单控件绑定

在前面的v-model一节中已经说了,这未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net一章,其实就是对v-model的展开说明【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】。当然,也不完全就是v-model,这章著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。会全面的讲解跟表单相关的所有开发相关内容【本文受版权保护】转载请注明出处:www.tangshuang.net

【转载请注明来源】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。

数据的双向绑定

前面说了,v-model是双向绑定的秘诀著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。。那么到底怎么实现呢?

未经授权,禁止复制转载。【转载请注明来源】【未经授权禁止转载】

文本 input text

<input v-model="message">
<p>Message is: {{ message }}</p>
new Vue({
  data: {
    message: 'placeholder',
  },
})

这里的双向绑定包括两个绑定,一个是dat【原创不易,请尊重版权】【转载请注明来源】a.message被绑定到input控件【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net上,被作为input的value值。当然本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net,{{message}}也是被绑定好的。【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net当data.message发生变化的时候转载请注明出处:www.tangshuang.net【本文受版权保护】,视图里面会跟着变。

【本文受版权保护】【作者:唐霜】【本文受版权保护】【版权所有,侵权必究】

现在,在input里面输入自己的字符串。【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。由于v-model的作用,data.me【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】ssage也随之发生变化,data.me【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】ssage这次反过来等于输入的值。于此同【本文受版权保护】【版权所有】唐霜 www.tangshuang.net时,由于data.message变了,{未经授权,禁止复制转载。【本文受版权保护】{message}}也跟着变了。

著作权归作者所有,禁止商业用途转载。【本文受版权保护】【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net原创内容,盗版必究。ngnet】著作权归作者所有,禁止商业用途转载。

这个过程就是v-model的双向绑定的结【转载请注明来源】【版权所有】唐霜 www.tangshuang.net果。

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】ngnet】

编者按:关于v-model是v-bind【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net和v-on的语法糖的问题,你此刻可能不是本文作者:唐霜,转载请注明出处。原创内容,盗版必究。很懂,因为你还没有阅读事件绑定这一章,下【版权所有,侵权必究】【未经授权禁止转载】一章会专门讲事件绑定,阅读完下一章你再回【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net头阅读这一章,就会有不一样的理解。

【原创不易,请尊重版权】【未经授权禁止转载】【本文首发于唐霜的博客】
原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n【原创不易,请尊重版权】未经授权,禁止复制转载。et 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。

多行文本 textarea

<span>Multiline message is:</span>
<p style="white-space: pre">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

在文本区域插值( <textare著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。a>{{message}}<【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】/textarea> ) 并不会生著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。效,应用 v-model 来代替。

【版权所有,侵权必究】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【作者:唐霜】ng.net【作者:唐霜】

textarea和上面的input te【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。xt是一样的,效果也和我们想象的一样。

【版权所有】唐霜 www.tangshu【本文受版权保护】原创内容,盗版必究。ang.net【原创内容,转载请注明出处】未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。

复选框 input checkbox

单个勾选框

<input type="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

这里的v-model绑定了checked著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。,但是checked这个变量应该是一个b【未经授权禁止转载】【未经授权禁止转载】oolean值,表示这个checkbox【转载请注明来源】【转载请注明来源】是否被选中,是绑定到了prop属性。

本文作者:唐霜,转载请注明出处。【本文受版权保护】【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】et 获取更多精彩内容】

这个时候,你会问,当复选框选中了,那么我【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。怎么知道要用什么值呢?这里有两种解释,一【未经授权禁止转载】【转载请注明来源】种是你不需要知道它要用什么值,你只需要知【本文受版权保护】原创内容,盗版必究。道它的结果是选中还是不选中即可,至于选中【原创不易,请尊重版权】【本文首发于唐霜的博客】了怎么办,不选中又怎么办,请自己来决定。

本文作者:唐霜,转载请注明出处。【作者:唐霜】

另一种是给两个绑定值,如下:

本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】
<input type="checkbox" v-model="checked" :true-value="a" :false-value="b">

这里的a和b都是变量,选中的时候chec【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】ked值等于a,即app.checked【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。 = app.a,否则app.check著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。ed = app.b。这样checked【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】就不是boolean值了。

【原创不易,请尊重版权】【访问 www.tangshuang.n未经授权,禁止复制转载。【未经授权禁止转载】et 获取更多精彩内容】【未经授权禁止转载】【版权所有,侵权必究】

注意:checkbox单个复选框的时候,【原创内容,转载请注明出处】【未经授权禁止转载】不能使用:value="xxx"绑定值,即使绑定了也没用,会被舍弃,读过本文版权归作者所有,未经授权不得转载。【本文受版权保护】我前面那篇文章的就知道。

未经授权,禁止复制转载。转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。ng.net

多个勾选框

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<span>Checked names: {{ checkedNames }}</span>// 这可以checkedNames直接显示成JSON.stringify()的结果
new Vue({
  el: '...',
  data: {
    checkedNames: [],
  }
})

这里,要求type=”che【本文受版权保护】本文版权归作者所有,未经授权不得转载。ckbox”是一定要有的,如【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net果没有type=”check本文作者:唐霜,转载请注明出处。【转载请注明来源】box”,会报错,type值【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。必须是字符串,不能通过v-bind进行绑【原创内容,转载请注明出处】【原创内容,转载请注明出处】定使用动态值,否则vue会报错。

【版权所有,侵权必究】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netang.net【转载请注明来源】

data.checkedNames一定要【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net是数组,当用户勾选了上面checkbox本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】的其中一个时,它的value值会被丢到d本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】ata.checkedNames这个数组【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net中来。而它的value值则可以通过v-b【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。ind绑定一个动态数据。

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。【本文受版权保护】ng.net著作权归作者所有,禁止商业用途转载。

在HTML中,通过相同的一个name值来【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】确定这组checkbox是一个组的,而在【作者:唐霜】【作者:唐霜】这里,则是通过v-model的值是同一个著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】值来确定是一个组的。

【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。【转载请注明来源】转载请注明出处:www.tangshua【转载请注明来源】本文版权归作者所有,未经授权不得转载。ng.net

这个时候就可以使用:value来动态绑定著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。value值了,这和单个复选框不一样。

【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】ang.net【作者:唐霜】【本文受版权保护】【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net原创内容,盗版必究。ngnet】

单选按钮 input radio

<div id="example-4" class="demo">
 <input type="radio" id="one" value="One" v-model="picked">
 <label for="one">One</label>
 <br>
 <input type="radio" id="two" value="Two" v-model="picked">
 <label for="two">Two</label>
 <br>
 <span>Picked: {{ picked }}</span>
</div>
new Vue({
  el: '#example-4',
  data: {
    picked: '',
  }
})

单选框组跟多个checkbox复选框组是【本文受版权保护】【本文受版权保护】一样的。包括:value绑定。唯一不同的原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】是picked是一个单选值,所以是一个值本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net,而不是数组。

本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】【本文首发于唐霜的博客】

选择列表 select

单选列表

【原创内容,转载请注明出处】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】
<div id="example-5" class="demo">
 <select v-model="selected">
 <option>A</option>
 <option>B</option>
 <option>C</option>
 </select>
 <span>Selected: {{ selected }}</span>
</div>
new Vue({
  el: '#example-5',
  data: {
    selected: null
  }
})

多选列表(绑定到一个数组)

未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。
<div id="example-6" class="demo">
 <select v-model="selected" multiple style="width: 50px">
 <option>A</option>
 <option>B</option>
 <option>C</option>
 </select>
 <br>
 <span>Selected: {{ selected }}</span>
</div>
new Vue({
  el: '#example-6',
  data: {
    selected: []
  }
})

因为multiple要选择的值是一组,因【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net此selected是一个数组。

【版权所有】唐霜 www.tangshu【转载请注明来源】【版权所有】唐霜 www.tangshuang.netang.net未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu【作者:唐霜】未经授权,禁止复制转载。ang.net

动态选项,用 v-for 渲染:

【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。ang.net【版权所有】唐霜 www.tangshu【作者:唐霜】【本文受版权保护】ang.net【转载请注明来源】
<select v-model="selected">
 <option v-for="option in options" v-bind:value="option.value">
 {{ option.text }}
 </option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})

绑定 value

对于单选按钮,勾选框及选择列表选项, v著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。-model 绑定的 value 通常是【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net静态字符串(对于勾选框是逻辑值):

【原创不易,请尊重版权】原创内容,盗版必究。
<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">
<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">
<!-- 当选中时,`selected` 为字符串 "abc" -->
<select v-model="selected">
 <option value="abc">ABC</option>
</select>

但是有时我们想绑定 value 到 Vu【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】e 实例的一个动态属性上,这时可以用 v本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。-bind 实现,并且这个属性的值可以不著作权归作者所有,禁止商业用途转载。【本文受版权保护】是字符串。

原创内容,盗版必究。【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】ang.net【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【本文受版权保护】et 获取更多精彩内容】

当我们通过v-bind:value对va转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】lue进行绑定时,应该要注意,v-bin转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。d就是一个单向绑定操作,你有没有必要对这未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net个value进行单向绑定?你应该怎么绑定著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。呢?准备写表单之前,先想好你的表单逻辑再【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。开始写代码。在这之前,一定要先读一下我的这篇文章。

【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】ang.net【原创不易,请尊重版权】原创内容,盗版必究。【版权所有,侵权必究】

补充:<input v-model【未经授权禁止转载】【版权所有,侵权必究】=”something【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。221;>其实是<input【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。 v-bind:value=”【转载请注明来源】著作权归作者所有,禁止商业用途转载。;something” v-转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】on:input=”some【本文受版权保护】著作权归作者所有,禁止商业用途转载。thing = $event.targe【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。t.value”>的语【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net法糖,也就是说v-model本身就已经包【转载请注明来源】未经授权,禁止复制转载。含了v-bind,所以当v-bind和v【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net-model同时出现在一个input上时【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】,这个v-bind会失效。

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。
【本文受版权保护】【版权所有,侵权必究】【原创不易,请尊重版权】【关注微信公众号:wwwtangshua【本文受版权保护】本文版权归作者所有,未经授权不得转载。ngnet】

修饰符

.lazy

在默认情况下, v-model 在 in【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netput 事件中同步输入框的值与数据 (除【未经授权禁止转载】【转载请注明来源】了 上述 IME 部分),但你可以添加一本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。个修饰符 lazy ,从而转变为在 ch【本文首发于唐霜的博客】【本文受版权保护】ange 事件中同步:

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】【原创不易,请尊重版权】
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

.number

如果想自动将用户的输入值转为 Numbe【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。r 类型(如果原值的转换结果为 NaN 著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。则返回原值),可以添加一个修饰符 num【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】ber 给 v-model 来处理输入值本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net

【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。ang.net
<input v-model.number="age" type="number">

这通常很有用,因为在 type=R本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】21;number” 时 H【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。TML 中输入的值也总是会返回字符串类型【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。

【本文受版权保护】本文版权归作者所有,未经授权不得转载。

.trim

如果要自动过滤用户输入的首尾空格,可以添本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。加 trim 修饰符到 v-model 转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】上过滤输入:

【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ngnet】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。【作者:唐霜】
<input v-model.trim="msg">

表单验证:vue-validator

这一章是插入的一章,在实际开发中,你不一【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。定需要vue-validator来验证你【本文受版权保护】转载请注明出处:www.tangshuang.net的表单选项。但是本章可以给你一些启示,帮【本文受版权保护】【原创不易,请尊重版权】助你设计自己的验证思路。vue-vali【原创内容,转载请注明出处】【作者:唐霜】dator也不是vue官方的插件,而是一原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。个个人项目。不过插件作者比较早的开发了完本文作者:唐霜,转载请注明出处。原创内容,盗版必究。善的验证机制,所以插件也得到广泛使用。v【作者:唐霜】本文作者:唐霜,转载请注明出处。ue-validator目前对vue2.【作者:唐霜】原创内容,盗版必究。2+是不支持的,v3版本支持vue2.0【原创不易,请尊重版权】【本文受版权保护】。它也有自己的完整中文文档,你可以点击这里进入阅读。但是这个中文文档是v2.x的,【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。v2.x版本不支持vue2.0,但是大部转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】分接口都是一样的,所以也可以看。但是因为【本文受版权保护】本文作者:唐霜,转载请注明出处。vue-validator对vue2.0【作者:唐霜】【原创不易,请尊重版权】的支持还不稳定,所以,本书也更多的只介绍【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】一些常用功能,以及验证思路。

未经授权,禁止复制转载。【关注微信公众号:wwwtangshua【未经授权禁止转载】本文作者:唐霜,转载请注明出处。ngnet】【版权所有,侵权必究】

安装和开始

vue的插件都使用use方法来安装。我们【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net使用npm来安装vue-validato未经授权,禁止复制转载。【版权所有,侵权必究】r:

原创内容,盗版必究。【作者:唐霜】【版权所有,侵权必究】【本文受版权保护】
npm install --save vue-validator

安装好之后,在你的项目中使用它:

【转载请注明来源】【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。【转载请注明来源】
import Vue from 'vue'import VueValidator form 'vue-validator'
Vue.use(VueValidator)

在这之后,你就可以使用vue-valid原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】ator进行表单验证了。

【原创内容,转载请注明出处】原创内容,盗版必究。
<div id="app">
  <validator name="validation1">
    <form novalidate>
    <div class="username-field">
      <label for="username">username:</label>
      <input id="username" type="text" v-validate:username="['required']">
    </div>
    <div class="comment-field">
      <label for="comment">comment:</label>
      <input id="comment" type="text" v-validate:comment="{ maxlength: 256 }">
    </div>
    <div class="errors">
      <p v-if="$validation1.username.required">Required your name.</p>
      <p v-if="$validation1.comment.maxlength">Your comment is too long.</p>
    </div>
    <input type="submit" value="send" v-if="$validation1.valid">
    </form>
  </validator>
</div>

验证结果会关联到验证器元素上。在上例中,原创内容,盗版必究。转载请注明出处:www.tangshuang.net验证结果保存在 $validation1【本文首发于唐霜的博客】【本文受版权保护】 下,$validation1 是由 v未经授权,禁止复制转载。转载请注明出处:www.tangshuang.netalidator 元素的 name 属性著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net值加 $ 前缀组成。

著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】

验证结果结构

验证结果(也就是上面的$validati【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.neton1)有如下结构:

本文版权归作者所有,未经授权不得转载。【作者:唐霜】【原创不易,请尊重版权】
{
  // top-level validation properties
  valid: true,
  invalid: false,
  touched: false,
  undefined: true,
  dirty: false,
  pristine: true,
  modified: false,
  errors: [{
      field: 'field1', validator: 'required', message: 'required field1'
    },
    ...
    {
      field: 'fieldX', validator: 'customValidator', message: 'invalid fieldX'
  }],
  // field1 validation
  field1: {
    required: false, // build-in validator, return `false` or `true`
    email: true, // custom validator
    url: 'invalid url format', // custom validator, if specify the error message in validation rule, set it
    ...
    customValidator1: false, // custom validator
    // field validation properties
    valid: false,
    invalid: true,
    touched: false,
    undefined: true,
    dirty: false,
    pristine: true,
    modified: false,
    errors: [{
      validator: 'required', message: 'required field1'
    }]
  },
  ...
  // fieldX validation
  fieldX: {
    min: false, // validator
    ...
    customValidator: true,
    // fieldX validation properties
    valid: false,
    invalid: true,
    touched: true,
    undefined: false,
    dirty: true,
    pristine: false,
    modified: true,
    errors: [{
      validator: 'customValidator', message: 'invalid fieldX'
    }]
  },
}

全局结果可以直接从验证结果中获取到,字段【本文受版权保护】转载请注明出处:www.tangshuang.net验证结果保存在以字段名命名的键下。

【作者:唐霜】【本文受版权保护】

字段验证结果

全局结果

验证器语法

v-validate 指令用法如下:

著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】【作者:唐霜】
v-validate[:field]="array literal | object literal | binding"

字段

2.0-alpha以前的版本中,验证器是【原创不易,请尊重版权】【本文首发于唐霜的博客】依赖于 v-model 的。从2.0-a【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】lpha版本开始,v-model 是可选未经授权,禁止复制转载。【版权所有,侵权必究】的。

未经授权,禁止复制转载。原创内容,盗版必究。原创内容,盗版必究。

~v1.4.4:

【访问 www.tangshuang.n【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】【转载请注明来源】本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】
<form novalidate>
  <input type="text" v-model="comment" v-validate="minLength: 16, maxLength: 128">
  <div>
    <span v-show="validation.comment.minLength">Your comment is too short.</span>
    <span v-show="validation.comment.maxLength">Your comment is too long.</span>
  </div>
  <input type="submit" value="send" v-if="valid">
</form>

v2.0-alpha后:

【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】ang.net【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。
<validator name="validation">
  <form novalidate>
    <input type="text" v-validate:comment="{ minlength: 16, maxlength: 128 }">
    <div>
      <span v-show="$validation.comment.minlength">Your comment is too short.</span>
      <span v-show="$validation.comment.maxlength">Your comment is too long.</span>
    </div>
    <input type="submit" value="send" v-if="valid">
  </form>
</validator>

上面的蓝色comment使得$valid【转载请注明来源】【原创不易,请尊重版权】ation多了一个comment属性,也【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】就是红色的comment。蓝色的大括号里著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】面是规则,其中minlength的规则是著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】16,而当你输入内容之后,验证结果怎么样转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】呢?$validation.commen原创内容,盗版必究。原创内容,盗版必究。t.minlength就可以得到验证的结转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。果。

【本文受版权保护】【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu【本文受版权保护】原创内容,盗版必究。ang.net

Caml-case 属性

同 Vue.js一样, v-valida本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】te 指令中的字段名可以使用 kebab【版权所有,侵权必究】原创内容,盗版必究。-case:

【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。ngnet】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】
<validator name="validation">
  <form novalidate>
    <input type="text" v-validate:user-name="{ minlength: 16 }">
    <div>
      <span v-if="$validation.userName.minlength">Your user name is too short.</span>
    </div>
  </form>
</validator>

属性

可以通过 field 属性来指定字段名。本文作者:唐霜,转载请注明出处。【未经授权禁止转载】这在动态定义包含验证功能的表单时有用:

【原创不易,请尊重版权】【作者:唐霜】

注意: 当使用 field 属性指定字段著作权归作者所有,禁止商业用途转载。【本文受版权保护】名时不需要在 v-validate 指令【关注微信公众号:wwwtangshuangnet】【本文受版权保护】中再次指定。

【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。【未经授权禁止转载】【转载请注明来源】
著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】【转载请注明来源】【转载请注明来源】
<div id="app">
  <validator name="validation">
    <form novalidate>
      <p class="validate-field" v-for="field in fields">
        <label :for="field.id">{{field.label}}</label>
        <input type="text" :id="field.id" :placeholder="field.placeholder" :field="field.name" v-validate="field.validate">
      </p>
      <pre>{{ $validation | json }}</pre>
    </form>
  </validator>
</div>
new Vue({
  el: '#app',
  data: {
    fields: [{
      id: 'username',
      label: 'username',
      name: 'username',
      placeholder: 'input your username',
      validate: { required: true, maxlength: 16 }
    },
    {
      id: 'message',
      label: 'message',
      name: 'message',
      placeholder: 'input your message',
      validate: { required: true, minlength: 8 }
    }]
  }
})

数组

下例中使用了数组型字面量:

【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【转载请注明来源】ang.net【原创内容,转载请注明出处】
<validator name="validation">
  <form novalidate>
    Zip: <input type="text" v-validate:zip="['required']">
    <br />
    <div>
      <span v-if="$validation.zip.required">Zip code is required.</span>
    </div>
  </form>
</validator>

因为 required 验证器不要额外的未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】参数,这样写更简洁。

【访问 www.tangshuang.n未经授权,禁止复制转载。【原创内容,转载请注明出处】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【转载请注明来源】ang.net

对象

下例中使用了对象型字面量:

转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【转载请注明来源】ng.net【原创内容,转载请注明出处】【原创内容,转载请注明出处】【本文受版权保护】
<validator name="validation">
  <form novalidate>
    ID: <input type="text" v-validate:id="{ required: true, minlength: 3, maxlength: 16 }"><br />
    <div>
      <span v-if="$validation.id.required">ID is required</span>
      <span v-if="$validation.id.minlength">Your ID is too short.</span>
      <span v-if="$validation.id.maxlength">Your ID is too long.</span>
    </div>
  </form>
</validator>

使用对象型字面量允许你为验证器指定额外的【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net参数。对于 required,因为它不需【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】要参数,如上例中随便指定一个值即可。

【原创不易,请尊重版权】【原创不易,请尊重版权】【未经授权禁止转载】

或者可以像下例一样使用严苛模式对象:

本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】【本文受版权保护】【原创不易,请尊重版权】
<validator name="validation">
  <form novalidate>
    ID: <input type="text" v-validate:id="{ minlength: { rule: 3 }, maxlength: { rule: 16 } }"><br />
    <div>
      <span v-if="$validation.id.minlength">Your ID is too short.</span>
      <span v-if="$validation.id.maxlength">Your ID is too long.</span>
    </div>
  </form>
</validator>

实例中绑定

下例中展现了动态绑定:

【未经授权禁止转载】【未经授权禁止转载】
new Vue({
  el: '#app',
  data: {
    rules: {
      minlength: 3,
      maxlength: 16
    }
  }
})
<div id="app">
  <validator name="validation">
  <form novalidate>
    ID: <input type="text" v-validate:id="rules"><br />
    <div>
      <span v-if="$validation.id.minlength">Your ID is too short.</span>
      <span v-if="$validation.id.maxlength">Your ID is too long.</span>
    </div>
  </form>
  </validator>
</div>

除数据属性外,也可以使用计算属性或事例方本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】法来指定验证规则。

【原创内容,转载请注明出处】【原创不易,请尊重版权】

Terminal 指令问题

请注意,当你想要使用如 v-if 和 v本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】-for 这些 terminal 指令时【原创内容,转载请注明出处】未经授权,禁止复制转载。,应把可验证的目标元素包裹在 <t著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。emplate> 之类的不可见标签原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】内。因为 v-validate 指令不能【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】与这些 terminal 指令使用在同一【转载请注明来源】【版权所有】唐霜 www.tangshuang.net元素上。
【未经授权禁止转载】 下例中使用了 <div> 【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。标签:

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu原创内容,盗版必究。原创内容,盗版必究。ang.net
new Vue({
  el: '#app',
  data: {
    enable: true
  }
})
<div id="app">
  <validator name="validation">
  <form novalidate>
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" @valid="this.enable = true" @invalid="this.enable = false"
      v-validate:username="['required']">
  </div>
  <div v-if="enable" class="password">
    <label for="password">password:</label>
    <input id="password" type="password" v-validate:password="{
      required: { rule: true }, minlength: { rule: 8 }
    }"/>
  <div>
  </form>
  </validator>
</div>

内置验证规则

vue-validator内置了一些验证著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】规则,也就是上面v-validate:后未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。面的表达式内容中的东西。这些内置规则包括著作权归作者所有,禁止商业用途转载。【本文受版权保护】

【访问 www.tangshuang.n【作者:唐霜】【版权所有,侵权必究】et 获取更多精彩内容】【本文受版权保护】

required

这个字段必须有值。举个例子:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【未经授权禁止转载】【本文受版权保护】ng.net【原创内容,转载请注明出处】
<input v-validate:fieldx="{required: true}">

那么当你在提交表单时,如果这个input【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net没有输入值,那么$validation.转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】fieldx.required就会返回f【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.netalse。

【转载请注明来源】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】ang.net

pattern

正则匹配校验器,校验元素值是否跟patt未经授权,禁止复制转载。【原创内容,转载请注明出处】ern所表示的正则表达式匹配。

【原创不易,请尊重版权】【原创不易,请尊重版权】原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

minlength

最小长度,如果元素的值的最小长度小于mi【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。nlength规定的值,就会返回fals【作者:唐霜】本文版权归作者所有,未经授权不得转载。e。

著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】【版权所有,侵权必究】

maxlength

最大长度,如果元素中输入的值大于这个设定【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】值,就会返回false。

本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu【版权所有,侵权必究】原创内容,盗版必究。ang.net

min

最小值校验器,当你输入的值比这个值还小(【版权所有,侵权必究】未经授权,禁止复制转载。<=)的时候,返回false。

【转载请注明来源】本文版权归作者所有,未经授权不得转载。

max

最大值校验器,当你输入的值比这个值还大(【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。>=),那返回false。

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

结合 v-model

可以验证通过 v-model 指令进行数未经授权,禁止复制转载。【本文受版权保护】据绑定的字段:

【转载请注明来源】【本文首发于唐霜的博客】
<div id="app">
  <validator name="validation1">
  <form novalidate>
    message: <input type="text" v-model="msg" v-validate:message="{ required: true, minlength: 8 }"><br />
  <div>
    <p v-if="$validation1.message.required">Required your message.</p>
    <p v-if="$validation1.message.minlength">Too short message.</p>
  </div>
  </form>
  </validator>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    msg: ''
  }
})
setTimeout(function () {
  vm.msg = 'hello world!!'
}, 2000)

重置验证结果

可以通过 Vue 实例的 $resetV【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。alidation() 方法重置验证结果【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net,该方法是由验证器安装时动态定义的。使用【本文受版权保护】【未经授权禁止转载】方法见下例:

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n【原创内容,转载请注明出处】未经授权,禁止复制转载。et 获取更多精彩内容】
<div id="app">
  <validator name="validation1">
  <form novalidate>
  <div class="username-field">
    <label for="username">username:</label>
    <input id="username" type="text" v-validate:username="['required']">
  </div>
  <div class="comment-field">
    <label for="comment">comment:</label>
    <input id="comment" type="text" v-validate:comment="{ maxlength: 256 }">
  </div>
  <div class="errors">
    <p v-if="$validation1.username.required">Required your name.</p>
    <p v-if="$validation1.comment.maxlength">Your comment is too long.</p>
  </div>
  <input type="submit" value="send" v-if="$validation1.valid">
  <button type="button" @click="onReset">Reset Validation</button>
  </form>
  
  <pre>{{ $validation1 | json }}</pre>
  </validator>
</div>
new Vue({
  el: '#app',
  methods: {
    onReset: function () {
      this.$resetValidation()
    }
  }
})

可验证的表单元素

复选框

支持复选框验证:

【转载请注明来源】原创内容,盗版必究。原创内容,盗版必究。
<div id="app">
  <validator name="validation1">
  <form novalidate>
  <h1>Survey</h1>
  <fieldset>
    <legend>Which do you like fruit ?</legend>
    <input id="apple" type="checkbox" value="apple" v-validate:fruits="{
      required: { rule: true, message: requiredErrorMsg },
      minlength: { rule: 1, message: minlengthErrorMsg },
      maxlength: { rule: 2, message: maxlengthErrorMsg }
    }">
    <label for="apple">Apple</label>
    <input id="orange" type="checkbox" value="orange" v-validate:fruits>
    <label for="orange">Orage</label>
    <input id="grape" type="checkbox" value="grape" v-validate:fruits>
    <label for="grape">Grape</label>
    <input id="banana" type="checkbox" value="banana" v-validate:fruits>
    <label for="banana">Banana</label>
    <ul class="errors">
      <li v-for="msg in $validation1.fruits.errors">
        <p>{{msg.message}}</p>
      </li>
    </ul>
  </fieldset>
  </form>
  </validator>
</div>
new Vue({
  el: '#app',
  computed: {
    requiredErrorMsg: function () {
      return 'Required fruit !!'
    },
    minlengthErrorMsg: function () {
      return 'Please chose at least 1 fruit !!'
    },
    maxlengthErrorMsg: function () {
      return 'Please chose at most 2 fruits !!'
    }
  }
})

单选按钮

支持单选按钮验证:

【版权所有】唐霜 www.tangshu【转载请注明来源】本文作者:唐霜,转载请注明出处。ang.net【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】本文作者:唐霜,转载请注明出处。原创内容,盗版必究。
<div id="app">
  <validator name="validation1">
  <form novalidate>
    <h1>Survey</h1>
    <fieldset>
      <legend>Which do you like fruit ?</legend>
      <input id="apple" type="radio" name="fruit" value="apple" v-validate:fruits="{
        required: { rule: true, message: requiredErrorMsg }
      }">
      <label for="apple">Apple</label>
      <input id="orange" type="radio" name="fruit" value="orange" v-validate:fruits>
      <label for="orange">Orage</label>
      <input id="grape" type="radio" name="fruit" value="grape" v-validate:fruits>
      <label for="grape">Grape</label>
      <input id="banana" type="radio" name="fruit" value="banana" v-validate:fruits>
      <label for="banana">Banana</label>
      <ul class="errors">
        <li v-for="msg in $validation1.fruits.errors">
          <p>{{msg.message}}</p>
        </li>
      </ul>
    </fieldset>
  </form>
  </validator>
</div>
new Vue({
  el: '#app',
  computed: {
    requiredErrorMsg: function () {
      return 'Required fruit !!'
    }
  }
})

下拉列表

支持下拉列表验证:

转载请注明出处:www.tangshua【未经授权禁止转载】未经授权,禁止复制转载。ng.net【未经授权禁止转载】
<div id="app">
  <validator name="validation1">
  <form novalidate>
    <select v-validate:lang="{ required: true }">
      <option value="">----- select your favorite programming language -----</option>
      <option value="javascript">JavaScript</option>
      <option value="ruby">Ruby</option>
      <option value="python">Python</option>
      <option value="perl">Perl</option>
      <option value="lua">Lua</option>
      <option value="go">Go</option>
      <option value="rust">Rust</option>
      <option value="elixir">Elixir</option>
      <option value="c">C</option>
      <option value="none">Not a nothing here</option>
    </select>
    <div class="errors">
      <p v-if="$validation1.lang.required">Required !!</p>
    </div>
  </form>
  </validator>
</div>
new Vue({ el: '#app' })

验证结果类

v2.1+的功能。有时,我们需要为不同验著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。证结果显示不同的样式以达到更好的交互效果未经授权,禁止复制转载。【版权所有,侵权必究】。vue-validator 在验证完表未经授权,禁止复制转载。【转载请注明来源】单元素后会自动插入相应的类来指示验证结果【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。,如下例所示:

本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。
<input id="username" type="text" v-validate:username="{
  required: { rule: true, message: 'required you name !!' }
}">

上例会输出如下 HTML:

原创内容,盗版必究。【原创不易,请尊重版权】
<input id="username" type="text" class="invalid untouched pristine">

验证结果类列表

验证类型 类名 (默认) 描述
valid valid 当目标元素变为 valid 时
invalid invalid 当目标元素变为 invalid 时
touched touched 当 touched 目标元素时
untouched untouched 当目标元素还未被 touched 时
pristine pristine 当目标元素还未 dirty 时
dirty dirty 当目标元素 dirty 时
modified modified 当目标元素 modified 时

使用自定义验证结果类

当默认的验证结果类名不方便使用时,你可以【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】使用 classes 属性自定义相应的类【本文受版权保护】转载请注明出处:www.tangshuang.net名,如下所示:

【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】ang.net本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】
<validator name="validation1" :classes="{ touched: 'touched-validator', dirty: 'dirty-validator' }">
  <label for="username">username:</label>
  <input id="username" type="text" :classes="{ valid: 'valid-username', invalid: 'invalid-username' }"
    v-validate:username="{ required: { rule: true, message: 'required you name !!' } }"
  >
</validator>

classes 属性需要使用在 v-va未经授权,禁止复制转载。【转载请注明来源】lidate 或 validator 指本文版权归作者所有,未经授权不得转载。【转载请注明来源】令上,值必须为对象。

【原创内容,转载请注明出处】【转载请注明来源】【版权所有,侵权必究】

在非目标元素上使用验证结果类

通常情况下验证结果类会插入到定义 v-v【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。alidate 指令的元素上。然而有时候【原创内容,转载请注明出处】【本文受版权保护】我们需要把这些类插入到其他元素上。这时我转载请注明出处:www.tangshuang.net【本文受版权保护】们可以使用 v-validate-cla【关注微信公众号:wwwtangshuangnet】【作者:唐霜】ss 来实现,如下所示:

【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。et 获取更多精彩内容】【原创内容,转载请注明出处】未经授权,禁止复制转载。
<validator name="validation1" :classes="{ touched: 'touched-validator', dirty: 'dirty-validator' }">
  <div v-validate-class class="username">
  <label for="username">username:</label>
  <input id="username" type="text" :classes="{ valid: 'valid-username', invalid: 'invalid-username' }"
    v-validate:username="{ required: { rule: true, message: 'required you name !!' }
  }">
  </div>
</validator>

上例会输出如下 HTML:

【作者:唐霜】【转载请注明来源】本文作者:唐霜,转载请注明出处。
<div class="username invalid-username untouched pristine">
  <label for="username">username:</label>
  <input id="username" type="text">
</div>

分组

支持把验证字段分组:

【转载请注明来源】【版权所有,侵权必究】
<validator name="validation1" :groups="['user', 'password']">
  username: <input type="text" group="user" v-validate:username="['required']"><br />
  password: <input type="password" group="password" v-validate:password1="{ minlength: 8, required: true }"/><br />
  password (confirm): <input type="password" group="password" v-validate:password2="{ minlength: 8, required: true }"/>
  <div class="user">
    <span v-if="$validation1.user.invalid">Invalid yourname !!</span>
  </div>
  <div class="password">
    <span v-if="$validation1.password.invalid">Invalid password input !!</span>
  </div>
</validator>

错误消息

错误消息可以直接在验证规则中指定,同时可【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】以在 v-show 和 v-if 中使用未经授权,禁止复制转载。【未经授权禁止转载】错误消息:

【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ngnet】【关注微信公众号:wwwtangshua【作者:唐霜】【转载请注明来源】ngnet】【本文受版权保护】
<validator name="validation1">
  <div class="username">
  <label for="username">username:</label>
  <input id="username" type="text" v-validate:username="{
    required: { rule: true, message: 'required you name !!' }
  }">
  <span v-if="$validation1.username.required">{{ $validation1.username.required }}</span>
  </div>
  <div class="password">
    <label for="password">password:</label>
    <input id="password" type="password" v-validate:password="{
      required: { rule: true, message: 'required you password !!' },
      minlength: { rule: 8, message: 'your password short too !!' }
    }">
    <span v-if="$validation1.password.required">{{ $validation1.password.required }}</span>
    <span v-if="$validation1.password.minlength">{{ $validation1.password.minlength }}</span>
  </div>
</validator>

也可以在 v-for 指令中使用错误消息著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】
<validator name="validation1">
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" v-validate:username="{
      required: { rule: true, message: 'required you name !!' }
    }">
  </div>
  <div class="password">
  <label for="password">password:</label>
  <input id="password" type="password" v-validate:password="{
    required: { rule: true, message: 'required you password !!' },
    minlength: { rule: 8, message: 'your password short too !!' }
  }">
  </div>
  <div class="errors">
  <ul>
    <li v-for="error in $validation1.errors">
      <p>{{error.field}}: {{error.message}}</p>
    </li>
  </ul>
  </div>
</validator>

使用数据属性或计算属性来指定验证规则比使本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。用内联验证规则更简洁。

【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ang.net【访问 www.tangshuang.n【未经授权禁止转载】【未经授权禁止转载】et 获取更多精彩内容】

错误消息枚举组件

在上例中,我们使用 v-for 指令来枚【原创不易,请尊重版权】【本文受版权保护】举验证器的 errors。但是,我们可以【未经授权禁止转载】【原创内容,转载请注明出处】让它更简单。本验证器提供了非常易用的 v【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。alidator-errors 组件来枚【原创不易,请尊重版权】【本文首发于唐霜的博客】举错误消息,如下例所示:

【作者:唐霜】【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【版权所有,侵权必究】ngnet】
<validator name="validation1">
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" v-validate:username="{
      required: { rule: true, message: 'required you name !!' }
    }">
  </div>
  <div class="password">
    <label for="password">password:</label>
    <input id="password" type="password" v-validate:password="{
      required: { rule: true, message: 'required you password !!' },
      minlength: { rule: 8, message: 'your password short too !!' }
    }"/>
  </div>
  <div class="errors">
    <validator-errors :validation="$validation1"></validator-errors>
  </div>
</validator>

上例的代码渲染出的界面如下:

转载请注明出处:www.tangshua【作者:唐霜】【本文首发于唐霜的博客】ng.net【原创内容,转载请注明出处】【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。ngnet】本文版权归作者所有,未经授权不得转载。
<div class="username">
  <label for="username">username:</label>
  <input id="username" type="text"></div><div class="password">
  <label for="password">password:</label>
  <input id="password" type="password"></div><div class="errors">
  <div>
    <p>password: your password short too !!</p>
  </div>
  <div>
    <p>password: required you password !!</p>
  </div>
  <div>
    <p>username: required you name !!</p>
  </div>
</div>

如果你不喜欢 validator-err原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】ors 默认的错误消息格式,可以指定自定【本文首发于唐霜的博客】【本文受版权保护】义的组件或 partial 作为消息模版转载请注明出处:www.tangshuang.net【转载请注明来源】

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】

自定义组件模版

下例中展示了使用组件作为模版:

【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。【转载请注明来源】et 获取更多精彩内容】【转载请注明来源】著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】
<div id="app">
  <validator name="validation1">
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" v-validate:username="{
      required: { rule: true, message: 'required you name !!' }
    }">
  </div>
  <div class="password">
    <label for="password">password:</label>
    <input id="password" type="password" v-validate:password="{
      required: { rule: true, message: 'required you password !!' },
      minlength: { rule: 8, message: 'your password short too !!' }
    }"/>
  </div>
  <div class="errors">
    <validator-errors :component="'custom-error'" :validation="$validation1">
  </validator-errors>
  </div>
  </validator>
</div>
// register the your component with Vue.component
Vue.component('custom-error', {
  props: ['field', 'validator', 'message'],
  template: '<p class="error-{{field}}-{{validator}}">{{message}}</p>'
})
new Vue({ el: '#app' })

自定义Partial模版

下例中展示了使用 partial 作为模本文作者:唐霜,转载请注明出处。【未经授权禁止转载】版:

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshua【本文受版权保护】【关注微信公众号:wwwtangshuangnet】ngnet】
<div id="app">
  <validator name="validation1">
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" v-validate:username="{
      required: { rule: true, message: 'required you name !!' }
    }">
  </div>
  <div class="password">
    <label for="password">password:</label>
    <input id="password" type="password" v-validate:password="{
      required: { rule: true, message: 'required you password !!' },
      minlength: { rule: 8, message: 'your password short too !!' }
    }"/>
  </div>
  <div class="errors">
    <validator-errors partial="myErrorTemplate" :validation="$validation1">
    </validator-errors>
  </div>
  </validator>
</div>
// register custom error template
Vue.partial('myErrorTemplate', '<p>{{field}}: {{validator}}: {{message}}</p>')
new Vue({ el: '#app' })

自定义指定错误消息

有时候你只需要输出部分错误消息,此时你可【本文受版权保护】著作权归作者所有,禁止商业用途转载。以通过 group 或 field 属性【版权所有,侵权必究】【转载请注明来源】来指定这部分验证结果。

【未经授权禁止转载】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【作者:唐霜】ng.net【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。

下例中展示了 group 属性的使用:

【版权所有,侵权必究】【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】
<div id="app">
  <validator :groups="['profile', 'password']" name="validation1">
  <div class="username">
  <label for="username">username:</label>
  <input id="username" type="text" group="profile" v-validate:username="{
    required: { rule: true, message: 'required you name !!' }
  }">
  </div>
  <div class="url">
    <label for="url">url:</label>
    <input id="url" type="text" group="profile" v-validate:url="{
      required: { rule: true, message: 'required you name !!' },
      url: { rule: true, message: 'invalid url format' }
    }">
  </div>
  <div class="old">
    <label for="old">old password:</label>
    <input id="old" type="password" group="password" v-validate:old="{
      required: { rule: true, message: 'required you old password !!' },
      minlength: { rule: 8, message: 'your old password short too !!' }
    }"/>
  </div>
  <div class="new">
    <label for="new">new password:</label>
    <input id="new" type="password" group="password" v-validate:new="{
      required: { rule: true, message: 'required you new password !!' },
      minlength: { rule: 8, message: 'your new password short too !!' }
    }"/>
  </div>
  <div class="confirm">
    <label for="confirm">confirm password:</label>
    <input id="confirm" type="password" group="password" v-validate:confirm="{
      required: { rule: true, message: 'required you confirm password !!' },
      minlength: { rule: 8, message: 'your confirm password short too !!' }
    }"/>
  </div>
  <div class="errors">
    <validator-errors group="profile" :validation="$validation1">
    </validator-errors>
  </div>
  </validator>
</div>
Vue.validator('url', function (val) {
  return /^(http\:\/\/|https\:\/\/)(.{4,})$/.test(val)
})
new Vue({ el: '#app' })

事件

可以使用 vue 中的事件绑定方法绑定验【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net证器产生的事件。

【原创内容,转载请注明出处】【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【本文受版权保护】ngnet】

字段验证事件

对于每一个字段,你都可以监听如下事件:

【未经授权禁止转载】本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。ngnet】转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netng.net
<div id="app">
  <validator name="validation1">
  <div class="comment-field">
    <label for="comment">comment:</label>
    <input type="text" @valid="onValid" @invalid="onInvalid" @touched="onTouched" @dirty="onDirty"
      @modified="onModified"
      v-validate:comment="['required']"/>
  </div>
  <div>
    <p>{{occuredValid}}</p>
    <p>{{occuredInvalid}}</p>
    <p>{{occuredTouched}}</p>
    <p>{{occuredDirty}}</p>
    <p>{{occuredModified}}</p>
  </div>
  </validator>
</div>
new Vue({
  el: '#app',
  data: {
    occuredValid: '',
    occuredInvalid: '',
    occuredTouched: '',
    occuredDirty: '',
    occuredModified: ''
  },
  methods: {
    onValid: function () {
      this.occuredValid = 'occured valid event'
      this.occuredInvalid = ''
    },
    onInvalid: function () {
      this.occuredInvalid = 'occured invalid event'
      this.occuredValid = ''
    },
    onTouched: function () {
      this.occuredTouched = 'occured touched event'
    },
    onDirty: function () {
      this.occuredDirty = 'occured dirty event'
    },
    onModified: function (e) {
      this.occuredModified = 'occured modified event: ' + e.modified
    }
  }
})

顶级验证事件

可以监听如下顶级验证结果的变化事件:

本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】未经授权,禁止复制转载。
<div id="app">
  <validator name="validation1" @valid="onValid" @invalid="onInvalid"
    @touched="onTouched"
    @dirty="onDirty"
    @modified="onModified">
  <div class="comment-field">
    <label for="username">username:</label>
    <input type="text" v-validate:username="['required']"/>
  </div>
  <div class="password-field">
    <label for="password">password:</label>
    <input type="password" v-validate:password="{ required: true, minlength: 8 }"/>
  </div>
  <div>
    <p>{{occuredValid}}</p>
    <p>{{occuredInvalid}}</p>
    <p>{{occuredTouched}}</p>
    <p>{{occuredDirty}}</p>
    <p>{{occuredModified}}</p>
  </div>
  </validator>
</div>
new Vue({
  el: '#app',
  data: {
    occuredValid: '',
    occuredInvalid: '',
    occuredTouched: '',
    occuredDirty: '',
    occuredModified: ''
  },
  methods: {
    onValid: function () {
      this.occuredValid = 'occured valid event'
      this.occuredInvalid = ''
    },
    onInvalid: function () {
      this.occuredInvalid = 'occured invalid event'
      this.occuredValid = ''
    },
    onTouched: function () {
      this.occuredTouched = 'occured touched event'
    },
    onDirty: function () {
      this.occuredDirty = 'occured dirty event'
    },
    onModified: function (modified) {
      this.occuredModified = 'occured modified event: ' + modified
    }
  }
})

手动设置错误消息

有时候你需要手动设置验证错误的消息,如从转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】服务器端得到的验证错误消息。这时你可以通原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。过 $setValidationErro【未经授权禁止转载】转载请注明出处:www.tangshuang.netrs 方法设置错误消息,如下例:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。
<div id="app">
  <validator name="validation">
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" v-model="username" v-validate:username="{
      required: { rule: true, message: 'required you name !!' }
    }">
  </div>
  <div class="old">
    <label for="old">old password:</label>
    <input id="old" type="password" v-model="passowrd.old" v-validate:old="{
      required: { rule: true, message: 'required you old password !!' }
    }"/>
  </div>
  <div class="new">
    <label for="new">new password:</label>
    <input id="new" type="password" v-model="password.new" v-validate:new="{
      required: { rule: true, message: 'required you new password !!' },
      minlength: { rule: 8, message: 'your new password short too !!' }
    }"/>
  </div>
  <div class="confirm">
    <label for="confirm">confirm password:</label>
    <input id="confirm" type="password" v-validate:confirm="{
      required: { rule: true, message: 'required you confirm password !!' },
      confirm: { rule: passowd.new, message: 'your confirm password incorrect !!' }
    }"/>
  </div>
  <div class="errors">
    <validator-errors :validation="$validation"></validator-errors>
  </div>
  
  <button type="button" v-if="$validation.valid" @click.prevent="onSubmit">update</button>
  </validator>
</div>
new Vue({
  el: '#app',
  data: {
    id: 1,
    username: '',
    password: {
      old: '',
      new: ''
    }
  },
  validators: {
    confirm: function (val, target) {
      return val === target
    }
  },
  methods: {
    onSubmit: function () {
      var self = this
      var resource = this.$resource('/user/:id')
      resource.save({ id: this.id }, {
        username: this.username,
        passowrd: this.new
      }, function (data, stat, req) {
        // something handle success ...
        // ...
      }).error(function (data, stat, req) {
        // handle server error
        self.$setValidationErrors([
          { field: data.field, message: data.message }
        ])
      })
    }
  }
})

延迟初始化

如果在 validator 元素上设置了【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。 lazy 属性,那么验证器直到 $ac【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。tivateValidator() 被调转载请注明出处:www.tangshuang.net【本文受版权保护】用时才会进行初始化。这在待验证的数据需要【版权所有】唐霜 www.tangshuang.net【作者:唐霜】异步加载时有用,避免了在得到数据前出现错【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。误提示。

著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】

下例中在得到评论内容后验证器才开始工作;未经授权,禁止复制转载。【版权所有,侵权必究】如果不设置 lazy 属性,在得到评论内本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。容前会显示错误提示。

【作者:唐霜】【访问 www.tangshuang.n【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】
<!-- comment component -->
<div>
  <h1>Preview</h1>
  <p>{{comment}}</p>
  <validator lazy name="validation1">
    <input type="text" :value="comment" v-validate:comment="{ required: true, maxlength: 256 }"/>
    <span v-if="$validation1.comment.required">Required your comment</span>
    <span v-if="$validation1.comment.maxlength">Too long comment !!</span>
    <button type="button" value="save" @click="onSave" v-if="valid">
  </validator>
</div>
Vue.component('comment', {
  props: {
    id: Number,
  },
  data: function () {
    return { comment: '' }
  },
  activate: function (done) {
    var resource = this.$resource('/comments/:id');
    resource.get({ id: this.id }, function (comment, stat, req) {
      this.comment = comment.body
      // activate validator
      this.$activateValidator()
      done()
    }.bind(this)).error(function (data, stat, req) {
      // handle error ...
      done()
    })
  },
  methods: {
    onSave: function () {
      var resource = this.$resource('/comments/:id');
      resource.save({ id: this.id }, { body: this.comment }, function (data, stat, req) {
        // handle success
      }).error(function (data, sta, req) {
        // handle error
      })
    }
  }
})

自定义验证器

全局注册

可以使用 Vue.validator 方转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】法注册自定义验证器。

【版权所有,侵权必究】【版权所有】唐霜 www.tangshu【转载请注明来源】【版权所有】唐霜 www.tangshuang.netang.net原创内容,盗版必究。原创内容,盗版必究。

提示: Vue.validator as【作者:唐霜】原创内容,盗版必究。set 继承自 Vue.js 的 ass未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】et 管理系统.

【版权所有,侵权必究】【原创不易,请尊重版权】
【版权所有】唐霜 www.tangshu【本文受版权保护】本文版权归作者所有,未经授权不得转载。ang.net【本文首发于唐霜的博客】

通过下例中的 email 自定义验证器详【转载请注明来源】【原创不易,请尊重版权】细了解 Vue.validator 的使未经授权,禁止复制转载。【原创内容,转载请注明出处】用方法:

【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。【转载请注明来源】ang.net本文版权归作者所有,未经授权不得转载。
// Register email validator function. 
Vue.validator('email', function (val) {
  return /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)
})
new Vue({
  el: '#app'
  data: {
    email: ''
  }
})
<div id="app">
  <validator name="validation1">
    address: <input type="text" v-validate:address="['email']"><br />
    <div>
      <p v-show="$validation1.address.email">Invalid your mail address format.</p>
    </div>
  <validator>
</div>

局部注册

可以通过组件的 validators 选【未经授权禁止转载】【原创内容,转载请注明出处】项注册只能在组件内使用的自定义验证器。

【版权所有】唐霜 www.tangshu【原创内容,转载请注明出处】【未经授权禁止转载】ang.net【转载请注明来源】本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】

自定义验证器是通过在组件的 valida未经授权,禁止复制转载。【原创内容,转载请注明出处】tors 下定义验证通过返回真不通过返回【版权所有】唐霜 www.tangshuang.net【作者:唐霜】假的回调函数来实现。

著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

下例中注册了 numeric 和 url转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。 两个自定义验证器:

【作者:唐霜】【原创不易,请尊重版权】
new Vue({
  el: '#app',
  validators: { // `numeric` and `url` custom validator is local registration
    numeric: function (val/*,rule*/) {
      return /^[-+]?[0-9]+$/.test(val)
    },
    url: function (val) {
      return /^(http\:\/\/|https\:\/\/)(.{4,})$/.test(val)
    }
  },
  data: {
    email: ''
  }
})
<div id="app">
  <validator name="validation1">
    username: <input type="text" v-validate:username="['required']"><br />
    email: <input type="text" v-validate:address="['email']"><br />
    age: <input type="text" v-validate:age="['numeric']"><br />
    site: <input type="text" v-validate:site="['url']"><br />
    <div class="errors">
      <p v-if="$validation1.username.required">required username</p>
      <p v-if="$validation1.address.email">invalid email address</p>
      <p v-if="$validation1.age.numeric">invalid age value</p>
      <p v-if="$validation1.site.url">invalid site uril format</p>
    </div>
  <validator>
</div>

错误消息

可以为自定义验证器指定默认的错误消息:

【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。未经授权,禁止复制转载。
// `email` custom validator global registration
Vue.validator('email', {
  message: 'invalid email address', // error message with plain string
  check: function (val) { // define validator
    return /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)
  }
})
// build-in `required` validator customization
Vue.validator('required', {
  message: function (field) { // error message with function
    return 'required "' + field + '" field'
  },
  check: Vue.validator('required') // re-use validator logic
})
new Vue({
  el: '#app',
  validators: {
    numeric: { // `numeric` custom validator local registration
      message: 'invalid numeric value',
      check: function (val) {
        return /^[-+]?[0-9]+$/.test(val)
      }
    },
    url: { // `url` custom validator local registration
      message: function (field) {
        return 'invalid "' + field + '" url format field'
      },
      check: function (val) {
        return /^(http\:\/\/|https\:\/\/)(.{4,})$/.test(val)
      }
    }
  },
  data: {
    email: ''
  }
})
<div id="app">
  <validator name="validation1">
    username: <input type="text" v-validate:username="['required']"><br />
    email: <input type="text" v-validate:address="['email']"><br />
    age: <input type="text" v-validate:age="['numeric']"><br />
    site: <input type="text" v-validate:site="['url']"><br />
    <div class="errors">
      <validator-errors :validation="$validation1"></validator-errors>
    </div>
  <validator>
</div>

自定义验证时机

默认情况下,vue-validator 【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。会根据 validator 和 v-va未经授权,禁止复制转载。【本文首发于唐霜的博客】lidate 指令自动进行验证。然而有时原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】候我们需要关闭自动验证,在有需要时手动触【本文受版权保护】著作权归作者所有,禁止商业用途转载。发验证。

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n【转载请注明来源】【作者:唐霜】et 获取更多精彩内容】

initial

当 vue-validator 完成初始原创内容,盗版必究。转载请注明出处:www.tangshuang.net编译后,会根据每一条 v-validat【作者:唐霜】【原创不易,请尊重版权】e 指令自动进行验证。如果你不需要自动验本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。证,可以通过 initial 属性或 v著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】-validate 验证规则来关闭自动验【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。证,如下所示:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【原创内容,转载请注明出处】【作者:唐霜】ng.net
<div id="app">
  <validator name="validation1">
    <form novalidate>
      <div class="username-field">
        <label for="username">username:</label>
        <!-- 'inital' attribute is applied the all validators of target element (e.g. required, exist) -->
        <input id="username" type="text" initial="off" v-validate:username="['required', 'exist']">
      </div>
      <div class="password-field">
        <label for="password">password:</label>
        <!-- 'initial' optional is applied with `v-validate` validator (e.g. required only) -->
        <input id="password" type="password" v-validate:passowrd="{ required: { rule: true, initial: 'off' }, minlength: 8 }">
      </div>
      <input type="submit" value="send" v-if="$validation1.valid">
    </form>
  </validator>
</div>

这在使用服务器端验证等异步验证方式时有用原创内容,盗版必究。转载请注明出处:www.tangshuang.net,具体可见后文例子。

【转载请注明来源】【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】【版权所有,侵权必究】【作者:唐霜】

detect-blur and detect-change

vue-validator 会在检测到表【原创内容,转载请注明出处】未经授权,禁止复制转载。单元素(input, checkbox,【本文受版权保护】【未经授权禁止转载】 select 等)上的 DOM 事件(【作者:唐霜】本文作者:唐霜,转载请注明出处。input, blur, change)【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net时自动验证。此时,可以使用 detect著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。-change 和 detect-blu【转载请注明来源】【版权所有】唐霜 www.tangshuang.netr 属性:

【本文首发于唐霜的博客】【转载请注明来源】著作权归作者所有,禁止商业用途转载。
<div id="app">
  <validator name="validation">
    <form novalidate @submit="onSubmit">
      <h1>user registration</h1>
      <div class="username">
      <label for="username">username:</label>
      <input id="username" type="text" detect-change="off" detect-blur="off" v-validate:username="{
        required: { rule: true, message: 'required you name !!' }
      }" />
      </div>
      <div class="password">
        <label for="password">password:</label>
        <input id="password" type="password" v-model="password" detect-change="off" detect-blur="off" v-validate:password="{
          required: { rule: true, message: 'required you new password !!' },
          minlength: { rule: 8, message: 'your new password short too !!' }
        }" />
      </div>
      <div class="confirm">
        <label for="confirm">confirm password:</label>
        <input id="confirm" type="password" detect-change="off" detect-blur="off" v-validate:confirm="{
          required: { rule: true, message: 'required you confirm password !!' },
          confirm: { rule: password, message: 'your confirm password incorrect !!' }
        }" />
      </div>
      <div class="errors" v-if="$validation.touched">
        <validator-errors :validation="$validation"></validator-errors>
      </div>
      <input type="submit" value="register" />
    </form>
  </validator>
</div>
new Vue({
  el: '#app',
  data: {
    password: ''
  },
  validators: {
    confirm: function (val, target) {
      return val === target
    }
  },
  methods: {
    onSubmit: function (e) {
      // validate manually
      var self = this
      this.$validate(true, function () {
        if (self.$validation.invalid) {
          e.preventDefault()
        }
      })
    }
  }
})

异步验证

当在需要进行服务器端验证,可以使用异步验未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net证,如下例:

本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】
<template>
  <validator name="validation">
  <form novalidate>
  <h1>user registration</h1>
  <div class="username">
    <label for="username">username:</label>
    <input id="username" type="text" detect-change="off" v-validate:username="{
      required: { rule: true, message: 'required your name !!' },
      exist: { rule: true, initial: 'off' }
    }" />
    <span v-if="checking">checking ...</span>
  </div>
  <div class="errors">
    <validator-errors :validation="$validation"></validator-errors>
  </div>
  <input type="submit" value="register" :disabled="!$validation.valid" />
  </form>
  </validator>
</template>
function copyOwnFrom(target, source) {
  Object.getOwnPropertyNames(source).forEach(function (propName) {
    Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName))
  })
  return target
}
function ValidationError() {
  copyOwnFrom(this, Error.apply(null, arguments))
}
ValidationError.prototype = Object.create(Error.prototype)
ValidationError.prototype.constructor = ValidationError
// exmpale with ES2015
export default {
  data () {
    return { checking: false }
  },
  validators: {
    exist (val) {
      this.vm.checking = true // spinner on
      return fetch('/validations/exist', {
        method: 'post',
        headers: {
         'Accept': 'application/json',
         'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          username: val
        })
      }).then((res) => {
        this.vm.checking = false // spinner off
        return res.json()
      }).then((json) => {
        return Object.keys(json).length > 0 ? Promise.reject(new ValidationError(json.message)) : Promise.resolve()
      }).catch((error) => {
        if (error instanceof ValidationError) {
          return Promise.reject(error.message)
        } else {
          return Promise.reject('unexpected error')
        }
      })
    }
  }
}

异步验证接口

在异步验证时,可以使用如下两类接口:

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【作者:唐霜】

1. 函数

需要实现一个返回签名为 function【本文受版权保护】【原创不易,请尊重版权】 (resolve, reject) 如【转载请注明来源】【本文受版权保护】同 promise 一样的函数的自定义验【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。证器。函数参数解释如下:

【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】未经授权,禁止复制转载。

2. promise

需要实现一个返回 promise 的自定【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。义验证器。根据验证结果来 resolve【版权所有,侵权必究】未经授权,禁止复制转载。 或 reject。

原创内容,盗版必究。【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【作者:唐霜】ang.net【版权所有,侵权必究】【版权所有】唐霜 www.tangshu原创内容,盗版必究。【本文首发于唐霜的博客】ang.net

使用错误消息

如上例所示,在服务器端验证错误发生时,可【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net以使用服务器端返回的错误消息。

【本文首发于唐霜的博客】【本文首发于唐霜的博客】【原创内容,转载请注明出处】

验证器函数 context

验证器函数 context 是绑定到 V【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。alidation 对象上的。Valid著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。ation 对象提供了一些属性,这些属性未经授权,禁止复制转载。【作者:唐霜】在实现特定的验证器时有用。

【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。【作者:唐霜】ang.net【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。【版权所有,侵权必究】ang.net【转载请注明来源】

vm 属性

暴露了当前验证所在的 vue 实例。
【原创内容,转载请注明出处】 the following ES201【本文首发于唐霜的博客】原创内容,盗版必究。5 example:

转载请注明出处:www.tangshua原创内容,盗版必究。原创内容,盗版必究。ng.net【本文首发于唐霜的博客】【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】ngnet】
new Vue({
  data () { 
    return { checking: false }
  },
  validators: {
    exist (val) {
      this.vm.checking = true // spinner on
      return fetch('/validations/exist', {
        // ...
      }).then((res) => { // done
        this.vm.checking = false // spinner off
        return res.json()
      }).then((json) => {
        return Promise.resolve()
      }).catch((error) => {
        return Promise.reject(error.message)
      })
    }
  }
})

el 属性

暴露了当前验证器的目标 DOM 元素。下【原创不易,请尊重版权】【版权所有,侵权必究】面展示了结合 International Teleph【原创不易,请尊重版权】【未经授权禁止转载】one Input jQuery 插件使用的例子:

著作权归作者所有,禁止商业用途转载。【转载请注明来源】本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】
new Vue({
  validators: {
    phone: function (val) {
      return $(this.el).intlTelInput('isValidNumber')
    }
  }
})

全局 API

Vue.validator( id, [definition] )

注册或获取全局验证器。

【版权所有,侵权必究】原创内容,盗版必究。
/*
 * Register custom validator
 *
 * Arguments:
 * - first argument: field value
 * - second argument: rule value (optional). this argument is being passed from specified validator rule with v-validate
 * Return:
 * `true` if valid, else return `false`
 */
Vue.validator('zip', function (val, rule) {
  return /^\d{3}-\d{4}$/.test(val)
})
/*
 * Register custom validator for async
 *
 * You can use the `Promise` or promise like `function (resolve, reject)`
 */
Vue.validator('exist', function (val) {
  return fetch('/validations/exist', {
    method: 'post',
    // ...
  }).then(function (json) {
    return Promise.resolve() // valid
  }).catch(function (error) {
    return Promise.reject(error.message) // invalid
  })
})
/*
 * Register validator definition object
 *
 * You need to specify the `check` custom validator function.
 * If you need to error message, you can specify the `message` string or function together.
 */
Vue.validator('email', {
  message: 'invalid email address', // error message
  check: function (val) { // custome validator
    return /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)
  }
})

构造器选项

validators

实例元方法

$activateValidator()

Vue.component('comment', {
  props: {
    id: Number,
  },
  data: function () {
    return { comment: '' }
  },
  activate: function (done) {
    var resource = this.$resource('/comments/:id');
    resource.get({ id: this.id }, function (comment, stat, req) {
      this.comment = comment.body
      // activate validator
      this.$activateValidator()
      done()
    }.bind(this)).error(function (data, stat, req) {
      // handle error ...
      done()
    })
  },
  methods: {
    onSave: function () {
      var resource = this.$resource('/comments/:id');
      resource.save({ id: this.id }, { body: this.comment }, function (data, stat, req) {
        // handle success
      }).error(function (data, sta, req) {
        // handle error
      })
    }
  }
})

$resetValidation( [cb] )

new Vue({
  el: '#app',
  methods: {
    onClickReset: function () {
      this.$resetValidation(function () {
        console.log('reset done')
      })
    }
  }
})

$setValidationErrors( errors )

new Vue({
  el: '#app',
  data: {
    id: 1,
    username: '',
    password: {
      old: '',
      new: ''
    }
  },
  validators: {
    confirm: function (val, target) {
      return val === target
    }
  },
  methods: {
    onSubmit: function () {
      var self = this
      var resource = this.$resource('/user/:id')
      resource.save({ id: this.id }, {
        username: this.username,
        passowrd: this.new
      }, function (data, stat, req) {
        // something handle success ...
        // ...
      }).error(function (data, stat, req) {
        // handle server error
        self.$setValidationErrors([
          { field: data.field, message: data.message }
        ])
      })
    }
  }
})

$validate( [field], [touched], [cb] )

new Vue({
  el: '#app',
  data: { password: '' },
  validators: {
    confirm: function (val, target) {
      return val === target
    }
  },
  methods: {
    onSubmit: function (e) {
      // validate the all fields manually with touched
      var self = this
      this.$validate(true, function () {
        console.log('validate done !!')
        if (self.$validation.invalid) {
          e.preventDefault()
        }
      })
    }
  }
})

指令

v-validate

<input type="text" v-validate:username="['required']">
<!-- object syntax -->
<input type="text" v-validate:zip="{ required: true, pattern: { rule: '/^\d{3}-\d{4}$/', message: 'invalid zip pattern' }}">
<!-- binding -->
<input type="text" v-validate:zip="zipRule">
<!-- grouping -->
<input type="text" group="profile" v-validate:user="['required']">
<!-- field -->
<input type="text" field="field1" v-validate="['required']">
<!-- disable validation with DOM event -->
<input type="password" detect-blur="off" detect-change="off" v-validate:password="['required']">
<!-- disable initial auto-validation -->
<input type="text" initial="off" v-validate:message="['required']">

特殊元素

validator

<!-- basic -->
<validator name="validation">
  <input type="text" v-validate:username="['required']">
  <p v-if="$validation.invalid">invalid !!<p>
</validator>
<!-- validation grouping -->
<validator name="validation" :groups="['user', 'password']">
  <label for="username">username:</label>
  <input type="text" group="user" v-validate:username="['required']">
  <label for="password">password:</label>
  <input type="password" group="password" v-validate:password1="{ minlength: 8, required: true }"/>
  <label for="confirm">password (confirm):</label>
  <input type="password" group="password" v-validate:password2="{ minlength: 8, required: true }"/>
  <p v-if="$validation.user.invalid">Invalid yourname !!</p>
  <p v-if="$validation.password.invalid">Invalid password input !!</p>
</validator>
<!-- lazy initialization -->
<validator lazy name="validation">
  <input type="text" :value="comment" v-validate:comment="{ required: true, maxlength: 256 }"/>
  <span v-if="$validation.comment.required">Required your comment</span>
  <span v-if="$validation.comment.maxlength">Too long comment !!</span>
  <button type="button" value="save" @click="onSave" v-if="valid">
</validator>

validator-errors

<!-- basic -->
<validator name="validation">
  ...
  <div class="errors">
  
  <validator-errors :validation="$validation"></validator-errors>
  </div>
</validator>
<!-- render validation error message with component -->
<validator name="validation">
  ...
  <div class="errors">
  
  <validator-errors :component="'custom-error'" :validation="$validation">
  
  </validator-errors>
  </div>
</validator>
<!-- render validation error message with partial -->
<validator name="validation">
  ...
  <div class="errors">
  
  <validator-errors partial="myErrorTemplate" :validation="$validation">
  
  </validator-errors>
  </div>
</validator>
<!-- error message filter with group -->
<validator :groups="['profile', 'password']" name="validation1">
  ...
  <input id="username" type="text" group="profile" v-validate:username="{
  
  required: { rule: true, message: 'required you name !!' }
  }">
  ...
  <input id="old" type="password" group="password" v-validate:old="{
  
  required: { rule: true, message: 'required you old password !!' },
  
  minlength: { rule: 8, message: 'your old password short too !!' }
  }"/>
  ...
  <div class="errors">
  
  <validator-errors group="profile" :validation="$validation1">
  
  </validator-errors>
  </div>
</validator>

事件绑定

在前端领域,事件绑定你应该不陌生,比如c【转载请注明来源】【未经授权禁止转载】lick, hover,已经熟的不能再熟【版权所有】唐霜 www.tangshuang.net【本文受版权保护】悉了。本章就来介绍在vue里面怎么快速实转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。现事件绑定。

未经授权,禁止复制转载。未经授权,禁止复制转载。
<button @click.prevent="say('A word!', $event)">ok</button>

上面这短短一段代码,有4个东西要介绍,下著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】面一一介绍:

转载请注明出处:www.tangshua原创内容,盗版必究。未经授权,禁止复制转载。ng.net著作权归作者所有,禁止商业用途转载。

使用v-on:绑定事件

前面已经对v-on指令讲过了,不讲了。

未经授权,禁止复制转载。【本文首发于唐霜的博客】【未经授权禁止转载】【版权所有】唐霜 www.tangshu【本文受版权保护】著作权归作者所有,禁止商业用途转载。ang.net

方法函数

事件的回调函数可以直接写在methods【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。里面:

本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】【转载请注明来源】
new Vue({
  methods: {
    say(word, e) { alert(word) },
  },
})

$event变量

它是直接被绑定到vue的实例上的属性。相本文作者:唐霜,转载请注明出处。【转载请注明来源】当于this.$event,也是事件信息【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。,比如$event.target等信息。著作权归作者所有,禁止商业用途转载。【转载请注明来源】它和DOM原生事件的event是一样的。

【本文受版权保护】未经授权,禁止复制转载。【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。

修饰符

事件修饰符比较多,前文已经提到了,也不讲【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net了。

未经授权,禁止复制转载。【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【本文受版权保护】ngnet】

自定义事件

vue提供了四个和事件相关的实例方法,分【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】别是$on, $once, $off, 【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。$emit,用过jquery的同学应该非【版权所有】唐霜 www.tangshuang.net【本文受版权保护】常熟悉了。我们来看下具体怎么用:

【本文受版权保护】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。ang.net
var app = new Vue({...})
app.$on('myEvent', (e, value) => console.log(value))
....
app.$emit('myEvent', 'changed')

上面的$on和$emit都是vue实例的【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。方法,所以说,对于事件绑定而言,vue内原创内容,盗版必究。【未经授权禁止转载】部直接提供了非指令的事件系统,跟jque【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】ry的用法几乎一样,v-on主要是在模板本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。中绑定DOM原生的一些事件,而$on, 【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。$once可以绑定自定义的事件,两者互不著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】干扰,$emit能否触发原生的DOM事件【版权所有,侵权必究】【本文首发于唐霜的博客】呢?请注意阅读下文。

【原创不易,请尊重版权】转载请注明出处:www.tangshua原创内容,盗版必究。【转载请注明来源】ng.net【版权所有,侵权必究】【作者:唐霜】

$on

监听当前实例上的自定义事件。事件可以由v【转载请注明来源】原创内容,盗版必究。m.$emit触发。回调函数会接收所有传【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。入事件触发函数的额外参数。

【作者:唐霜】【转载请注明来源】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')// -> "hi"

$once

监听一个自定义事件,但是只触发一次,在第【本文受版权保护】【本文受版权保护】一次触发之后移除监听器。

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。
vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')// -> "hi",同时移除test事件
vm.$emit('test', 'again') // test事件被移除了,所以这个触发不会有任何结果

$on和$once绑定的事件是在实例上,【本文首发于唐霜的博客】原创内容,盗版必究。而非DOM元素上,所以它们跟DOM原生的本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。事件是两回事。DOM原生事件是在触发DO【未经授权禁止转载】转载请注明出处:www.tangshuang.netM元素特定事件时被触发的,比如click【作者:唐霜】【作者:唐霜】。但是对于这里的实例vm而言,click【作者:唐霜】【本文首发于唐霜的博客】没有来源,实例根本不存在被click之说转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。,所以$on和$once跟DOM原生事件转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。扯不上任何关系。同理,$emit也是作用转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。于实例之上,既然实例跟原生的DOM事件扯【未经授权禁止转载】【原创不易,请尊重版权】不上关系,那么$emit也就跟原生DOM【原创内容,转载请注明出处】原创内容,盗版必究。事件扯不上关系了。这就回答了上文提出的那原创内容,盗版必究。【本文首发于唐霜的博客】个问题。

未经授权,禁止复制转载。【本文首发于唐霜的博客】

所以说,$on和$once绑定的是一个自【原创内容,转载请注明出处】【转载请注明来源】定义事件,这些事件是存储在vue内部的事【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net件管理器中,跟DOM事件是两码事,既然如【未经授权禁止转载】【原创不易,请尊重版权】此,跟v-on事件绑定也就是两回事。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。

$off

移除事件监听器。

【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

$emit

触发当前实例上的事件。附加参数都会传给监【原创内容,转载请注明出处】【作者:唐霜】听器回调。参数怎么传前面的代码已经演示过本文作者:唐霜,转载请注明出处。【本文受版权保护】了。

【本文受版权保护】【本文首发于唐霜的博客】

Class和Style的绑定

数据绑定一个常见需求是操作元素的 cla未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】ss 列表和它的内联样式。因为它们都是属【原创内容,转载请注明出处】【原创内容,转载请注明出处】性 ,我们可以用v-bind 处理它们:【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。只需要计算出表达式最终的字符串。不过,字【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。符串拼接麻烦又易错。因此,在 v-bin【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。d 用于 class 和 style 时【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】, Vue.js 专门增强了它。表达式的【本文受版权保护】【关注微信公众号:wwwtangshuangnet】结果类型除了字符串之外,还可以是对象或数未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。组。

本文作者:唐霜,转载请注明出处。【转载请注明来源】本文作者:唐霜,转载请注明出处。

绑定 HTML Class

对象语法

我们可以传给 v-bind:class 【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。一个对象,以动态地切换 class 。

【本文受版权保护】原创内容,盗版必究。
<div v-bind:class="{ active: isActive }"></div>

上面的语法表示 classactive 本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】的更新将取决于数据属性 isActive【作者:唐霜】【原创内容,转载请注明出处】 是否为真值 。

【关注微信公众号:wwwtangshua【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。ngnet】未经授权,禁止复制转载。【原创内容,转载请注明出处】未经授权,禁止复制转载。

我们也可以在对象中传入更多属性用来动态切【未经授权禁止转载】原创内容,盗版必究。换多个 class 。此外, v-bin【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】d:class 指令可以与普通的 cla著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】ss 属性共存。如下模板:

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。
<div class="static"
     v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>

如下 data:

【本文受版权保护】本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】
data: {
  isActive: true,
  hasError: false
}

渲染为:

未经授权,禁止复制转载。【作者:唐霜】本文作者:唐霜,转载请注明出处。
<div class="static active"></div>

当 isActive 或者 hasErr【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netor 变化时,class 列表将相应地更本文作者:唐霜,转载请注明出处。【转载请注明来源】新。例如,如果 hasError 的值为【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net true , class列表将变为 &著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。#8220;static active 转载请注明出处:www.tangshuang.net【版权所有,侵权必究】text-danger”。

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。

你也可以直接绑定数据里的一个对象:

【访问 www.tangshuang.n未经授权,禁止复制转载。未经授权,禁止复制转载。et 获取更多精彩内容】【版权所有,侵权必究】【原创内容,转载请注明出处】
<div v-bind:class="classObject"></div>
data: {
  classObject: {
    active: true,
    'text-danger': false
  }
}

渲染的结果和上面一样。我们也可以在这里绑本文作者:唐霜,转载请注明出处。【本文受版权保护】定返回对象的计算属性。这是一个常用且强大【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net的模式:

【原创内容,转载请注明出处】未经授权,禁止复制转载。
<div v-bind:class="classObject"></div>

data: {
  isActive: true,
  error: null
},
computed: {
  classObject: function () {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal',
    }
  }
}

数组语法

我们可以把一个数组传给 v-bind:c转载请注明出处:www.tangshuang.net【转载请注明来源】lass ,以应用一个 class 列表【关注微信公众号:wwwtangshuangnet】【作者:唐霜】

【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】ngnet】本文版权归作者所有,未经授权不得转载。
<div v-bind:class="[activeClass, errorClass]">

data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

渲染为:

本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】
<div class="active text-danger"></div>

如果你也想根据条件切换列表中的 clas【转载请注明来源】【版权所有】唐霜 www.tangshuang.nets ,可以用三元表达式:

【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。et 获取更多精彩内容】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。
<div v-bind:class="[isActive ? activeClass : '', errorClass]">

此例始终添加 errorClass ,但【转载请注明来源】【作者:唐霜】是只有在 isActive 是 true本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net 时添加 activeClass 。
【关注微信公众号:wwwtangshua【转载请注明来源】【本文受版权保护】ngnet】 不过,当有多个条件 class 时这样未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。写有些繁琐。可以在数组语法中使用对象语法本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。

【访问 www.tangshuang.n【本文受版权保护】本文版权归作者所有,未经授权不得转载。et 获取更多精彩内容】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。
<div v-bind:class="[{ active: isActive }, errorClass]">

用在组件上

这个章节假设你已经对 Vue 组件 有一【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net定的了解。当然你也可以跳过这里,稍后再回【转载请注明来源】【本文受版权保护】过头来看。当你在一个定制的组件上用到 c【作者:唐霜】转载请注明出处:www.tangshuang.netlass 属性的时候,这些类将被添加到根【本文受版权保护】【关注微信公众号:wwwtangshuangnet】元素上面,这个元素上已经存在的类不会被覆未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net盖。

本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。

例如,如果你声明了这个组件:

【未经授权禁止转载】【本文受版权保护】著作权归作者所有,禁止商业用途转载。
Vue.component('my-component', {  template: '<p class="foo bar">Hi</p>'})

然后在使用它的时候添加一些 class:

【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【原创内容,转载请注明出处】ngnet】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。ang.net
<my-component class="baz boo"></my-component>

HTML 最终将被渲染成为:

转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。ng.net【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netngnet】【原创内容,转载请注明出处】
<p class="foo bar baz boo">Hi</p>

同样的适用于绑定 HTML class 【作者:唐霜】【本文受版权保护】:

【本文受版权保护】未经授权,禁止复制转载。【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】
<my-component v-bind:class="{ active: isActive }"></my-component>

当 isActive 为 true 的时【原创内容,转载请注明出处】【原创不易,请尊重版权】候,HTML 将被渲染成为:

【转载请注明来源】【原创不易,请尊重版权】原创内容,盗版必究。【本文受版权保护】
<p class="foo bar active">Hi</p>

绑定内联样式

对象语法

v-bind:style 的对象语法十分【作者:唐霜】转载请注明出处:www.tangshuang.net直观——看着非常像 CSS ,其实它是一未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。个 JavaScript 对象。 CSS【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】 属性名可以用驼峰式(camelCase本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】)或短横分隔命名(kebab-case)【转载请注明来源】【本文受版权保护】

本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【转载请注明来源】ang.net本文作者:唐霜,转载请注明出处。
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

data: {
  activeColor: 'red',
  fontSize: 30
}

直接绑定到一个样式对象通常更好,让模板更未经授权,禁止复制转载。【未经授权禁止转载】清晰:

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu原创内容,盗版必究。【未经授权禁止转载】ang.net【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netang.net
<div v-bind:style="styleObject"></div>

data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

同样的,对象语法常常结合返回对象的计算属本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】性使用。

【本文首发于唐霜的博客】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ng.net

数组语法

v-bind:style 的数组语法可以【原创内容,转载请注明出处】未经授权,禁止复制转载。将多个样式对象应用到一个元素上:

【本文受版权保护】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。
<div v-bind:style="[baseStyles, overridingStyles]">

自动添加前缀

当 v-bind:style 使用需要特【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。定前缀的 CSS 属性时,如 trans【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】form ,Vue.js 会自动侦测并添【作者:唐霜】【未经授权禁止转载】加相应的前缀。

转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。ng.net转载请注明出处:www.tangshua未经授权,禁止复制转载。未经授权,禁止复制转载。ng.net【版权所有】唐霜 www.tangshu【原创内容,转载请注明出处】【作者:唐霜】ang.net【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】ang.net

修饰符

前面两处提到了修饰符,这一章其实主要是要【未经授权禁止转载】【未经授权禁止转载】总结一下,内容是跟前面一样的,如果你已经本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】理解了,就不用看。

本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n【作者:唐霜】【关注微信公众号:wwwtangshuangnet】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu【转载请注明来源】【版权所有】唐霜 www.tangshuang.netang.net

事件修饰符

在事件处理程序中调用 event.pre【转载请注明来源】著作权归作者所有,禁止商业用途转载。ventDefault() 或 even转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.nett.stopPropagation() 【本文首发于唐霜的博客】未经授权,禁止复制转载。是非常常见的需求。尽管我们可以在 met【转载请注明来源】【本文首发于唐霜的博客】hods 中轻松实现这点,但更好的方式是未经授权,禁止复制转载。【版权所有,侵权必究】:methods 只有纯粹的数据逻辑,而【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】不是去处理 DOM 事件细节。

未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。

为了解决这个问题, Vue.js 为 v【原创内容,转载请注明出处】未经授权,禁止复制转载。-on 提供了 事件修饰符。通过由点(.【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。)表示的指令后缀来调用修饰符。

【本文受版权保护】【版权所有,侵权必究】【作者:唐霜】【作者:唐霜】

按键修饰符

在监听键盘事件时,我们经常需要监测常见的【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net键值。 Vue 允许为 v-on 在监听【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】键盘事件时添加按键修饰符。记住所有的 k未经授权,禁止复制转载。【本文首发于唐霜的博客】eyCode 比较困难,所以 Vue 为【本文首发于唐霜的博客】【转载请注明来源】最常用的按键提供了别名。

【版权所有,侵权必究】【转载请注明来源】著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。

全部的按键别名:

未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。未经授权,禁止复制转载。

可以通过全局 config.keyCod【转载请注明来源】【转载请注明来源】es 对象自定义按键修饰符别名。

【本文受版权保护】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。ng.net【原创不易,请尊重版权】【原创内容,转载请注明出处】
Vue.config.keyCodes.f1 = 112
// 这样用
<input v-on:keyup.112="submit">

可以用如下修饰符开启鼠标或键盘事件监听,本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。使在按键按下时发生响应。

【原创内容,转载请注明出处】转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【作者:唐霜】ng.net

组件

终于进入组件这一章。前文多次提到组件是v【作者:唐霜】未经授权,禁止复制转载。ue里面非常核心的概念。但是实际上,组件【原创不易,请尊重版权】【转载请注明来源】在本书中,更多的是提倡作为一种思想,具体原创内容,盗版必究。【原创内容,转载请注明出处】使用的时候跟本书最前面的“vue实例”差【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】别不会太大,除了data()的地方需要着著作权归作者所有,禁止商业用途转载。【转载请注明来源】重强调,如果不涉及其他,组件实例和app未经授权,禁止复制转载。【作者:唐霜】级别实例差距不会有太大理解上的鸿沟。

未经授权,禁止复制转载。未经授权,禁止复制转载。

既然是一种思想,那么组件涉及的问题就不单【版权所有,侵权必究】【未经授权禁止转载】单是编程问题。比如组件之间如何通信,父子【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。组件之间的问题,数据流等问题。这些只有当【版权所有,侵权必究】【原创内容,转载请注明出处】我们探讨组件才会提出来的问题,需要你更多【作者:唐霜】本文作者:唐霜,转载请注明出处。的进行思考,想通之后,这些问题在实践中怎【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】么处理就迎刃而解了。

未经授权,禁止复制转载。【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshu【转载请注明来源】本文作者:唐霜,转载请注明出处。ang.net【本文受版权保护】

这一章也是所有入门级别知识的最后一章,从原创内容,盗版必究。转载请注明出处:www.tangshuang.net这一章之后,就要进入到更加深入的学习,这【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net些深入学习是必须的,不然无法认识vue的【本文受版权保护】本文版权归作者所有,未经授权不得转载。原貌。但是深入学习之前,前面几章的基础学【未经授权禁止转载】未经授权,禁止复制转载。习可以帮助你快速理解vue的基本使用方法【本文受版权保护】原创内容,盗版必究。,掌握之后,算是入门了。

本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。

什么是组件?

组件(Component)是 Vue.j【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】s 最强大的功能之一。组件可以扩展 HT【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netML 元素,封装可重用的代码。在较高层面转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】上,组件是自定义元素, Vue.js 的【版权所有,侵权必究】未经授权,禁止复制转载。编译器为它添加特殊功能。在有些情况下,组【本文首发于唐霜的博客】【未经授权禁止转载】件也可以是原生 HTML 元素的形式,以【作者:唐霜】【关注微信公众号:wwwtangshuangnet】 is 特性扩展。

原创内容,盗版必究。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【作者:唐霜】

简单的说,vue组件就是一个js类,使用【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】的时候new一下,得到一个组件的实例,组【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】件实例有很多接口,app层面就可以调用这著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】些接口来把组件的功能集成到app中。

未经授权,禁止复制转载。原创内容,盗版必究。

在开发层面上,你只需要使用Vue.ext【转载请注明来源】未经授权,禁止复制转载。end({…})就可以得到一未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。个组件。而开发的大部分工作,就是写好大括转载请注明出处:www.tangshuang.net【未经授权禁止转载】号里面的内容。

【转载请注明来源】【原创不易,请尊重版权】

创建一个组件

上面说过了,开发层面上,创建一个组件只需本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。要使用Vue.extend,如下:

本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netngnet】
var MyComponent = Vue.extend({
  template: '<div>OK</div>',
})

这样就创建了一个组件构造器MyCompo转载请注明出处:www.tangshuang.net【版权所有,侵权必究】nent。实际上,Vue.extend的【作者:唐霜】本文作者:唐霜,转载请注明出处。结果是Vue的一个子类。既然是一个类,就著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net可以被实例化,通过实例化得到一个组件实例【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。,“组件实例”这个称呼在前面已经提到过了【版权所有】唐霜 www.tangshuang.net【本文受版权保护】。组件构造器是一个类,可以被实例化为组件【原创不易,请尊重版权】【本文受版权保护】实例。

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。ng.net
var component1 = new MyComponent()

关于Vue.extend,我们会在后文继【原创内容,转载请注明出处】【本文受版权保护】续深入,这里就不赘述了。组件实例有一些方本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。法可以用,例如$mount方法,这也在后原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。面的Vue.extend部分去解释。本章【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。主要是要让你学会组件的思想和主要开发方式【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。

原创内容,盗版必究。【作者:唐霜】未经授权,禁止复制转载。【本文受版权保护】

注册一个组件

创建好了组件,接下来要在vue中注册它。【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。注册组件也有全局和局部两种。注册是什么概【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。念呢?其实注册是创建一个组件构造器的引用原创内容,盗版必究。未经授权,禁止复制转载。,并可以形式化的进行实例化。所谓形式化,【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net简单的说,就是把组件注册成一个html元【本文受版权保护】转载请注明出处:www.tangshuang.net素,这样可以直接在模板中使用这个跟组件等【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net价的元素来实例化组件。

原创内容,盗版必究。【转载请注明来源】【本文受版权保护】本文作者:唐霜,转载请注明出处。
// 局部注册
new Vue({
  el: '#app',
  template: '<div><my-component></my-component></div>',
  components: {
    'my-component': MyComponent,
  },
})
// 全局注册Vue.component('my-component', MyComponent)

全局注册有一个好处,就是可以在任何一个v【本文首发于唐霜的博客】原创内容,盗版必究。ue实例中去使用。

【原创内容,转载请注明出处】【转载请注明来源】【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。【版权所有,侵权必究】ang.net

使用一个注册好的组件

组件注册好之后,就可以在模板中使用注册的本文作者:唐霜,转载请注明出处。原创内容,盗版必究。组件名称,像一个html元素一样调用它,【本文首发于唐霜的博客】【本文首发于唐霜的博客】而且这个元素还支持指令,比如v-for之【本文受版权保护】【原创不易,请尊重版权】类的。基本的使用方法是在app的模板中使【版权所有,侵权必究】【未经授权禁止转载】用它:

【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】【作者:唐霜】et 获取更多精彩内容】【未经授权禁止转载】
<div>
  <my-component></my-component>
</div>

因为在创建组件的时候,传入了templa【原创内容,转载请注明出处】【未经授权禁止转载】te值,所以<my-compone【本文受版权保护】著作权归作者所有,禁止商业用途转载。nt>的地方就会替换为组件的模板编本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】译后的html,所以最终看到的结果是:

本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】【原创内容,转载请注明出处】
<div>
  <div>OK</div>
</div>

这是最简单的情况,就是模板替换一下而已。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。如果再把指令加进来,把数据绑定加进来,组【本文受版权保护】【版权所有】唐霜 www.tangshuang.net件和app的互动就非常复杂了。
【关注微信公众号:wwwtangshua【原创不易,请尊重版权】未经授权,禁止复制转载。ngnet】 使用一个组件(比如在模板中插入<【作者:唐霜】【版权所有,侵权必究】my-component>元素)的【未经授权禁止转载】【转载请注明来源】本质,是创建一个组件实例。也就是说,一个原创内容,盗版必究。【原创不易,请尊重版权】<my-component>【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net就是一个组件实例,它们共享一个组件构造器本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net(一个js类)。

【访问 www.tangshuang.n【作者:唐霜】本文版权归作者所有,未经授权不得转载。et 获取更多精彩内容】【转载请注明来源】【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netang.net【本文首发于唐霜的博客】

简易注册

上面我的做法是先创建一个组件构造器,然后著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net把组件构造器传入实例构造器。实际上,在实本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net践开发中,我们基本不会这样干,我们大部分本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】都会使用简易方式直接注册,跳过创建步骤:

【转载请注明来源】本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】
Vue.component('my-component', {
  template: '<div>OK</div>',
})

包括在创建vue实例的时候也是这样,直接【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。传对象字面量进去即可。相当于注册过程会自原创内容,盗版必究。转载请注明出处:www.tangshuang.net动创建一个匿名的组件构造器。
【转载请注明来源】 在开发中,如果不涉及组件实例复用问题,原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。这个方法非常好。也是最推荐的做法。

著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【作者:唐霜】ngnet】未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。

data必须是函数

在创建或注册模板的时候,传入一个data转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】属性作为用来绑定的数据。但是在组件中,d本文作者:唐霜,转载请注明出处。【作者:唐霜】ata必须是一个函数,而不能直接把一个对著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。象赋值给它。

【作者:唐霜】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】
Vue.component('my-component', {
  template: '<div>OK</div>',
  data() {
    return {} // 返回一个唯一的对象,不要和其他组件共用一个对象进行返回
  },
})

你在前面看到,在new Vue()的时候【原创内容,转载请注明出处】【原创内容,转载请注明出处】,是可以给data直接赋值为一个对象的。【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】这是怎么回事,为什么到了组件这里就不行了【作者:唐霜】【作者:唐霜】

【作者:唐霜】【版权所有】唐霜 www.tangshu【作者:唐霜】转载请注明出处:www.tangshuang.netang.net

你要理解,上面这个操作是一个简易操作,实【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】际上,它首先需要创建一个组件构造器,然后未经授权,禁止复制转载。【本文首发于唐霜的博客】注册组件。注册组件的本质其实就是建立一个本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】组件构造器的引用。使用组件才是真正创建一原创内容,盗版必究。【原创不易,请尊重版权】个组件实例。所以,注册组件其实并不产生新【本文首发于唐霜的博客】【原创不易,请尊重版权】的组件类,但会产生一个可以用来实例化的新【作者:唐霜】未经授权,禁止复制转载。方式。

【版权所有】唐霜 www.tangshu【本文首发于唐霜的博客】【版权所有,侵权必究】ang.net【原创不易,请尊重版权】

理解这点之后,再理解js的原型链:

【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。ang.net转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ng.net
var MyComponent = function() {}MyComponent.prototype.data = {
  a: 1,
  b: 2,
}// 上面是一个虚拟的组件构造器,真实的组件构造器方法很多
var component1 = new MyComponent()
var component2 = new MyComponent()// 上面实例化出来两个组件实例,也就是通过<my-component>调用,创建的两个实例
component1.data.a === component2.data.a // true
component1.data.b = 5component2.data.b // 5

可以看到上面代码中最后三句,这就比较坑爹未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。了,如果两个实例同时引用一个对象,那么当本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】你修改其中一个属性的时候,另外一个实例也本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】会跟着改。这怎么可以,两个实例应该有自己【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】各自的域才对。所以,需要通过下面方法来进【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】行处理:

【本文受版权保护】本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netng.net未经授权,禁止复制转载。
var MyComponent = function() {
  this.data = this.data()}MyComponent.prototype.data = function() {
  return {
    a: 1,
    b: 2,
  }
}

这样每一个实例的data属性都是独立的,本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net不会相互影响了。所以,你现在知道为什么v【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】ue组件的data必须是函数了吧。这都是【转载请注明来源】【版权所有】唐霜 www.tangshuang.net因为js本身的特性带来的,跟vue本身设【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net计无关。其实vue不应该把这个方法名取为【未经授权禁止转载】本文作者:唐霜,转载请注明出处。data(),应该叫setData或其他【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。更容易立即的方法名。

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】

prop

什么是prop?

首先,什么是prop?prop也是属性,【原创不易,请尊重版权】【原创内容,转载请注明出处】但是它和attribution不一样,a【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。ttribution往往是固定的值属性,未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】而prop更多的是动态的状态值属性,最简未经授权,禁止复制转载。未经授权,禁止复制转载。单的例子就是input checkbox【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】的checked属性,checked属性未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。的attr值是它的初始值,而prop值是【本文受版权保护】本文作者:唐霜,转载请注明出处。它的当前值,这对于熟悉jquery的同学著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】而已应该比较好理解。

本文作者:唐霜,转载请注明出处。【作者:唐霜】

为组件声明props属性

vue里面,组件实例的作用域是孤立的。这本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。意味着不能(也不应该)在子组件的模板内直【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】接引用父组件的数据。要让子组件使用父组件【版权所有,侵权必究】【版权所有,侵权必究】的数据,我们需要通过子组件的props选本文作者:唐霜,转载请注明出处。【本文受版权保护】项。

原创内容,盗版必究。转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.netng.net

子组件要显式地用 props 选项声明它期待获得的数据:

【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】ang.net【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netngnet】
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 就像 data 一样,prop 可以用在模板内
  // 同样也可以在 vm 实例中像 “this.message” 这样使用
  template: '<span>{{ message }}</span>'
})

使用prop属性

这样之后,message就变成了一个pr原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。op属性,在模板中,你使用child这个【作者:唐霜】本文版权归作者所有,未经授权不得转载。元素时,就可以给这个元素传一个messa著作权归作者所有,禁止商业用途转载。【转载请注明来源】ge属性进去:

【本文受版权保护】著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua【转载请注明来源】【本文首发于唐霜的博客】ng.net
<child message="hello!"></child>

如果在创建组件的时候没有声明props,【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net那么<child>的mess【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.netage就没用。

【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。未经授权,禁止复制转载。ang.net【关注微信公众号:wwwtangshua【转载请注明来源】本文版权归作者所有,未经授权不得转载。ngnet】原创内容,盗版必究。

prop属性命名注意点

如果你在声明props的时候,属性名是多【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net个单词构成的怎么办?在注册组件的时候使用原创内容,盗版必究。【作者:唐霜】驼峰命名方式:

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【本文首发于唐霜的博客】未经授权,禁止复制转载。
Vue.component('child', {
  // camelCase in JavaScript
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})

但是在使用组件的时候,传入的属性名得是短本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net横线隔开的:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netng.net【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】
<child my-message="hello!"></child>

这是因为html不区分大小写,你写成<child myMessage="hello!"></child>的话,假如有一个属性名是mymessage怎么办?所以,一定要注意这一点。

【原创内容,转载请注明出处】转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】ng.net

动态绑定prop属性值

既然是当做html元素的属性,那么就跟前【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。面讲的模板语法想通,你可以在prop属性【版权所有,侵权必究】【原创内容,转载请注明出处】上尝试使用一些指令,比如v-bind,例本文版权归作者所有,未经授权不得转载。【作者:唐霜】如:

【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ang.net本文作者:唐霜,转载请注明出处。
<child :my-message="msg"></child>

注意,这里的<child>是著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】在父组件,或者app层面的vue实例的模【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net板中使用的,所以这里的msg这个变量也是【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】来自父组件或app。
转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ng.net 这里有一个注意点,如果是普通的传值,不本文版权归作者所有,未经授权不得转载。【转载请注明来源】使用v-bind,那么值的内容是一个字符【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。串,即使你给了一个数字,它传进去还是个字【本文首发于唐霜的博客】原创内容,盗版必究。符串。想要传数字或其他类型的数据,应该用【作者:唐霜】原创内容,盗版必究。v-bind,比如:

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】ng.net本文版权归作者所有,未经授权不得转载。
<child :my-message="1"></child>

这个时候组件内获取的才是number,而本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】不是string。

【未经授权禁止转载】【版权所有,侵权必究】

单向数据绑定

prop 是单向绑定的:当父组件的属性变未经授权,禁止复制转载。原创内容,盗版必究。化时,将传导给子组件,但是不会反过来。这【未经授权禁止转载】【版权所有,侵权必究】是为了防止子组件无意修改了父组件的状态。

【未经授权禁止转载】转载请注明出处:www.tangshua【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】ng.net

另外,每次父组件更新时,子组件的所有 p【版权所有,侵权必究】【作者:唐霜】rop 都会更新为最新值。这意味着你不应【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net该在子组件内部改变 prop 。如果你这本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。么做了,Vue 会在控制台给出警告。

著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】【关注微信公众号:wwwtangshua【未经授权禁止转载】未经授权,禁止复制转载。ngnet】【作者:唐霜】

这一点非常好理解:JavaScript的【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net对象是引用类型数据,它的每一个属性都指向转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。同一个内存空间,所以不同的变量引用同一个原创内容,盗版必究。【本文受版权保护】对象的话,其中一个的属性一改,另一个也会转载请注明出处:www.tangshuang.net【转载请注明来源】跟着改。父组件和子组件之间的prop也是【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】一样,你修改子组件里面的prop,那么父【原创不易,请尊重版权】【转载请注明来源】组件里面的对应的属性也该了,这会让父组件著作权归作者所有,禁止商业用途转载。【作者:唐霜】或app层面产生混乱,一定会出bug。

【关注微信公众号:wwwtangshua【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】ngnet】未经授权,禁止复制转载。

正确的处理方法是,在创建组件时,保证组件原创内容,盗版必究。【作者:唐霜】只是接收prop数据,接收到以后马上放在未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】自己的私有属性中去:

【未经授权禁止转载】【未经授权禁止转载】
props: ['initialCounter'],data: function () {
  return { counter: this.initialCounter }
}
props: ['size'],computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

上面一个是通过data直接挂在一个属性上【原创内容,转载请注明出处】【版权所有,侵权必究】,一个是通过计算属性,把prop只当做计原创内容,盗版必究。原创内容,盗版必究。算的一个依赖。总之,这两种方式都可以解决【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。上面说的不允许子组件修改prop原始值的【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net问题。

【作者:唐霜】本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】

如果你使用data,你在组件内修改了这个【未经授权禁止转载】转载请注明出处:www.tangshuang.net属性值,那就跟prop没关系了,后期父组著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】件的prop值改变,也不会影响data了【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。

Prop 验证

我们可以为组件的 props 指定验证规【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】格。如果传入的数据不符合规格,Vue 会【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】发出警告。当组件给其他人使用时,这很有用未经授权,禁止复制转载。原创内容,盗版必究。
转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。ng.net 要指定验证规格,需要用对象的形式,而不【本文受版权保护】【本文受版权保护】能用字符串数组:

原创内容,盗版必究。未经授权,禁止复制转载。
Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    propA: Number,
    // 多种类型
    propB: [String, Number],
    // 必传且是字符串
    propC: {
      type: String,
      required: true
    },
    // 数字,有默认值
    propD: {
      type: Number,
      default: 100
    },
    // 数组/对象的默认值应当由一个工厂函数返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

type 可以是下面原生构造器:

【原创不易,请尊重版权】【本文受版权保护】【作者:唐霜】【本文受版权保护】

type 也可以是一个自定义构造器函数,【未经授权禁止转载】【本文首发于唐霜的博客】使用 instanceof 检测。

本文版权归作者所有,未经授权不得转载。【作者:唐霜】本文作者:唐霜,转载请注明出处。

当 prop 验证失败,Vue会在抛出警转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net告 (如果使用的是开发版本)。

【转载请注明来源】本文作者:唐霜,转载请注明出处。

事件反馈

前面一节指出,子组件不能自己主动修改pr【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netop,以防改变了父组件或app的值导致b本文作者:唐霜,转载请注明出处。【本文受版权保护】ug。那么如果子组件确实需要上级应用修改【未经授权禁止转载】转载请注明出处:www.tangshuang.net这些变量,让自己更好的适应新情况怎么办?未经授权,禁止复制转载。原创内容,盗版必究。那就让父组件或app自己来改。可是父组件【原创不易,请尊重版权】原创内容,盗版必究。怎么知道自己要改?通过子组件的事件就可以本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net做到了。

未经授权,禁止复制转载。【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netngnet】

前文我们已经学过事件绑定的知识了,组件的未经授权,禁止复制转载。【本文首发于唐霜的博客】实例也具有事件绑定的能力。所以我们可以在【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。子组件里面触发事件,在父组件里面监听这个本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】事件,当事件被触发时,父组件通过绑定的回【本文受版权保护】未经授权,禁止复制转载。调函数来执行prop的更改。当然除了更改【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。prop,还可以做其他的事情。

【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.netngnet】【本文受版权保护】

只能使用v-on绑定自定义事件

前文我们指出,直接用实例的$on方法来绑【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】定自定义事件。但是在这里不行,不能直接在【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】父组件里面直接用$on,因为我们使用&l原创内容,盗版必究。原创内容,盗版必究。t;my-component>实例本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】化组件时,没有得到一个变量用来存储实例化本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。对象,它相当于是匿名的,所以我们找不到它【本文受版权保护】【原创内容,转载请注明出处】,当然也找不到它的$on。

【本文受版权保护】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。ng.net【原创内容,转载请注明出处】

那怎么办?只能使用v-on来进行事件绑定【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

【原创内容,转载请注明出处】【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【本文受版权保护】ngnet】
<child @clicked="showSomething"></child>

这里的clicked是事件名,在子组件里【原创内容,转载请注明出处】【本文首发于唐霜的博客】面,通过this.$emit(̵本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】6;clicked’)触发事转载请注明出处:www.tangshuang.net原创内容,盗版必究。件。父组件里面,通过上面代码中的@cli【原创不易,请尊重版权】【本文首发于唐霜的博客】cked=”showSome转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】thing”监听这个事件,而【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。showSomething就是事件回调函转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。数,是父组件methods方法之一。

转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】ng.net【原创不易,请尊重版权】【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。

使用v-model实现input双向绑定

上面不是说只能使用v-on绑定事件吗?是【版权所有,侵权必究】【未经授权禁止转载】的,但是你是否还记得前文提到过v-mod【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。el其实是v-bind和v-on的语法糖【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。?上一节我们说过了,<child&【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。gt;可以使用v-bind,而这里又说可著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】以使用v-on,所以只要情况允许,就可以【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net使用v-model。

原创内容,盗版必究。【作者:唐霜】【本文首发于唐霜的博客】

所谓情况允许,是指符合下面条件:

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。

所以,只有下面这种<child&g本文作者:唐霜,转载请注明出处。【未经授权禁止转载】t;才可以使用v-model实现双向绑定【作者:唐霜】【转载请注明来源】

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。
Vue.component('child', {
  template: '<input :value="value" @keyup="update($event.target.value)">', //
   props: ['value'],
  methods: {
    update(value) {
      this.$emit('input', value)
    },
  },
})

这样,在父组件中才可以这样使用:

【关注微信公众号:wwwtangshua【本文首发于唐霜的博客】未经授权,禁止复制转载。ngnet】【版权所有,侵权必究】【转载请注明来源】【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。【本文受版权保护】et 获取更多精彩内容】
<child v-model="someData"></child>
// 等价于:
<child :value="someData" @input="someData = $event.target.value"></child>

蓝色部分表示的是v-bind部分,红褐色【作者:唐霜】原创内容,盗版必究。部分表示v-on部分。组件内部,绿色的k【本文受版权保护】转载请注明出处:www.tangshuang.neteyup是input元素的DOM原生事件原创内容,盗版必究。【版权所有,侵权必究】,红色的udpate是回调函数,当key原创内容,盗版必究。【未经授权禁止转载】up的时候执行update(),而upd著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。ate()的时候就$emit(̵【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。6;input’),触发了父【作者:唐霜】本文作者:唐霜,转载请注明出处。组件的v-on:input。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。

基于这种原理,不一定要使用在input输原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。入框上,实际上,任何元素都可以模拟这种方【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。式实现数据双向绑定。当然,如果没有输入,著作权归作者所有,禁止商业用途转载。【作者:唐霜】双向绑定的说法就很奇怪。

转载请注明出处:www.tangshua原创内容,盗版必究。【作者:唐霜】ng.net【作者:唐霜】【访问 www.tangshuang.n【原创内容,转载请注明出处】【转载请注明来源】et 获取更多精彩内容】

使用 Slot 分发内容

在使用组件时,我们常常要像这样组合它们:

【关注微信公众号:wwwtangshua【未经授权禁止转载】未经授权,禁止复制转载。ngnet】【访问 www.tangshuang.n【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】
<app>
  <app-header></app-header>
  <app-footer></app-footer>
</app>

注意两点:

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。
  1. <app> 组件不知道它的挂著作权归作者所有,禁止商业用途转载。【作者:唐霜】载点会有什么内容。挂载点的内容是由<【原创不易,请尊重版权】【未经授权禁止转载】;app>的父组件决定的。
  2. 转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。【未经授权禁止转载】ng.net未经授权,禁止复制转载。未经授权,禁止复制转载。【作者:唐霜】
  3. <app> 组件很可能有它自【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】己的模版。
  4. 著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【访问 www.tangshuang.n未经授权,禁止复制转载。【原创不易,请尊重版权】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】ang.net

为了让组件可以组合,我们需要一种方式来混转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。合父组件的内容与子组件自己的模板。这个过本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。程被称为 内容分发 (或 “transc【版权所有,侵权必究】【原创内容,转载请注明出处】lusion” 如果你熟悉 Angula【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】r)。Vue.js 实现了一个内容分发 本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netAPI ,参照了当前 Web 组件规范草案,使用特殊的 <slot> 【本文首发于唐霜的博客】原创内容,盗版必究。元素作为原始内容的插槽。

【原创内容,转载请注明出处】【本文首发于唐霜的博客】【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。

编译作用域

在深入内容分发 API 之前,我们先明确【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】内容在哪个作用域里编译。假定模板为:

【原创内容,转载请注明出处】【转载请注明来源】著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。
<child-component>{{ message }}</child-component>

message应该绑定到父组件的数据,还【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。是绑定到子组件的数据?答案是父组件。组件本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。作用域简单地说是:
转载请注明出处:www.tangshua【作者:唐霜】转载请注明出处:www.tangshuang.netng.net 父组件模板的内容在父组件作用域内编译;【作者:唐霜】【版权所有】唐霜 www.tangshuang.net子组件模板的内容在子组件作用域内编译。

【本文受版权保护】【转载请注明来源】【原创不易,请尊重版权】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。ng.net

一个常见错误是试图在父组件模板内将一个指【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】令绑定到子组件的属性/方法:

【转载请注明来源】【版权所有,侵权必究】【关注微信公众号:wwwtangshua【未经授权禁止转载】未经授权,禁止复制转载。ngnet】
<!-- 无效 --><child-component v-show="someChildProperty"></child-component>

假定 someChildProperty【作者:唐霜】著作权归作者所有,禁止商业用途转载。 是子组件的属性,上例不会如预期那样工作【原创不易,请尊重版权】未经授权,禁止复制转载。。父组件模板不应该知道子组件的状态。

【原创内容,转载请注明出处】【作者:唐霜】本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】

如果要绑定作用域内的指令到一个组件的根节【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net点,你应当在组件自己的模板上做:

本文版权归作者所有,未经授权不得转载。【转载请注明来源】
Vue.component('child-component', {  // 有效,因为是在正确的作用域内  template: '<div v-show="someChildProperty">Child</div>',  data: function () {    return {      someChildProperty: true    }  }})

类似地,分发内容是在父作用域内编译。

【版权所有】唐霜 www.tangshu【本文首发于唐霜的博客】【本文首发于唐霜的博客】ang.net【作者:唐霜】

单个 Slot

除非子组件模板包含至少一个 <sl【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】ot> 插口,否则父组件的内容将会【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】被丢弃。当子组件模板只有一个没有属性的 原创内容,盗版必究。本文作者:唐霜,转载请注明出处。slot 时,父组件整个内容片段将插入到【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。 slot 所在的 DOM 位置,并替换未经授权,禁止复制转载。未经授权,禁止复制转载。掉 slot 标签本身。

著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【作者:唐霜】【本文受版权保护】

最初在 <slot> 标签中【原创不易,请尊重版权】原创内容,盗版必究。的任何内容都被视为备用内容。备用内容在子本文作者:唐霜,转载请注明出处。【本文受版权保护】组件的作用域内编译,并且只有在宿主元素为原创内容,盗版必究。【原创不易,请尊重版权】空,且没有要插入的内容时才显示备用内容。

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】【版权所有,侵权必究】

假定 my-component 组件有下本文作者:唐霜,转载请注明出处。【转载请注明来源】面模板:

著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【作者:唐霜】ang.net
<div>
  <h2>我是子组件的标题</h2>
  <slot>
    只有在没有要分发的内容时才会显示。
  </slot>
</div>

父组件模版:

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【原创不易,请尊重版权】未经授权,禁止复制转载。ng.net【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net原创内容,盗版必究。et 获取更多精彩内容】【作者:唐霜】
<div>
  <h1>我是父组件的标题</h1>
  <my-component>
    <p>这是一些初始内容</p>
    <p>这是更多的初始内容</p>
  </my-component>
</div>

渲染结果:

未经授权,禁止复制转载。【本文首发于唐霜的博客】
<div>
  <h1>我是父组件的标题</h1>
  <div>
    <h2>我是子组件的标题</h2>
    <p>这是一些初始内容</p>
    <p>这是更多的初始内容</p>
  </div>
</div>

具名 Slot

<slot> 元素可以用一个【未经授权禁止转载】【本文受版权保护】特殊的属性 name 来配置如何分发内容本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】。多个 slot 可以有不同的名字。具名【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。 slot 将匹配内容片段中有对应 sl【本文受版权保护】【关注微信公众号:wwwtangshuangnet】ot 特性的元素。

著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。

仍然可以有一个匿名 slot ,它是默认【本文受版权保护】【作者:唐霜】 slot ,作为找不到匹配的内容片段的著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。备用插槽。如果没有默认的 slot ,这著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。些找不到匹配的内容片段将被抛弃。

原创内容,盗版必究。【本文受版权保护】

例如,假定我们有一个 app-layou本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。t 组件,它的模板为:

原创内容,盗版必究。【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ang.net未经授权,禁止复制转载。【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netet 获取更多精彩内容】
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

父组件模版:

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
<app-layout>
  <h1 slot="header">这里可能是一个页面标题</h1>
  <p>主要内容的一个段落。</p>
  <p>另一个主要段落。</p>
  <p slot="footer">这里有一些联系信息</p>
</app-layout>

渲染结果为:

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua原创内容,盗版必究。【版权所有,侵权必究】ng.net【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】et 获取更多精彩内容】
<div class="container">
  <header>
    <h1>这里可能是一个页面标题</h1>
  </header>
  <main>
    <p>主要内容的一个段落。</p>
    <p>另一个主要段落。</p>
  </main>
  <footer>
    <p>这里有一些联系信息</p>
  </footer>
</div>

在组合组件时,内容分发 API 是非常有【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。用的机制。

转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【转载请注明来源】ng.net未经授权,禁止复制转载。【原创内容,转载请注明出处】

作用域插槽

作用域插槽是一种特殊类型的插槽,用作使用【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。一个(能够传递数据到)可重用模板替换已渲【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】染元素。2.1.0才新增的,因此,如果你原创内容,盗版必究。本文作者:唐霜,转载请注明出处。只是使用2.0版本,还是使用不了。

原创内容,盗版必究。【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】et 获取更多精彩内容】

在子组件中,只需将数据传递到插槽,就像你转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】将 prop 传递给组件一样:

【作者:唐霜】本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【本文受版权保护】ngnet】
<div class="child">
  <slot text="hello from child"></slot>
</div>

在父级中,具有特殊属性 scope 的 【作者:唐霜】【版权所有,侵权必究】<template> 元素,转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】表示它是作用域插槽的模板。scope 的【作者:唐霜】未经授权,禁止复制转载。值对应一个临时变量名,此变量接收从子组件转载请注明出处:www.tangshuang.net【版权所有,侵权必究】中传递的 prop 对象:

【作者:唐霜】未经授权,禁止复制转载。未经授权,禁止复制转载。
<div class="parent">
  <child>
    <template scope="props">
      <span>hello from parent</span>
      <span>{{ props.text }}</span>
    </template>
  </child>
</div>

如果我们渲染以上结果,得到的输出会是:

【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。
<div class="parent">
  <div class="child">
    <span>hello from parent</span>
    <span>hello from child</span>
  </div>
</div>

作用域插槽更具代表性的用例是列表组件,允【版权所有,侵权必究】【本文受版权保护】许组件自定义应该如何渲染列表每一项:

本文作者:唐霜,转载请注明出处。【未经授权禁止转载】本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】
<my-awesome-list :items="items">
  <!-- 作用域插槽也可以是具名的 -->
  <template slot="item" scope="props">
    <li class="my-fancy-item">{{ props.text }}</li>
  </template>
</my-awesome-list>

列表组件的模板:

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。
<ul>
  <slot name="item"
    v-for="item in items"
    :text="item.text"
  >
    <!-- 这里写入备用内容 -->
  </slot>
</ul>

内联模板

如果子组件有 inline-templa著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】te 特性,组件将把它的内容当作它的模板【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。,而不是把它当作分发内容。这让模板更灵活未经授权,禁止复制转载。原创内容,盗版必究。

本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua【转载请注明来源】转载请注明出处:www.tangshuang.netngnet】【作者:唐霜】
<my-component inline-template>
  <div>
    <p>These are compiled as the component's own template.</p>
    <p>Not parent's transclusion content.</p>
  </div>
</my-component>

但是 inline-template 让【作者:唐霜】转载请注明出处:www.tangshuang.net模板的作用域难以理解。最佳实践是使用 t本文版权归作者所有,未经授权不得转载。【本文受版权保护】emplate 选项在组件内定义模板或者【原创不易,请尊重版权】【转载请注明来源】在 .vue 文件中使用 templat【未经授权禁止转载】本文作者:唐霜,转载请注明出处。e 元素。

【关注微信公众号:wwwtangshua【版权所有,侵权必究】【转载请注明来源】ngnet】【关注微信公众号:wwwtangshua原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netngnet】

编者按:关于.vue文件,会在后文详细讲【版权所有,侵权必究】【原创内容,转载请注明出处】解。

【版权所有】唐霜 www.tangshu【作者:唐霜】著作权归作者所有,禁止商业用途转载。ang.net本文版权归作者所有,未经授权不得转载。

动态组件

通过使用保留的 <componen【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】t> 元素,动态地绑定到它的 is著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】 特性,我们让多个组件可以使用同一个挂载【作者:唐霜】本文版权归作者所有,未经授权不得转载。点,并动态切换:

【原创内容,转载请注明出处】【本文受版权保护】【原创不易,请尊重版权】
var vm = new Vue({
  el: '#example',
  data: {
    currentView: 'home'
  },
  components: {
    home: { /* ... */ },
    posts: { /* ... */ },
    archive: { /* ... */ }
  }
})

<component v-bind:is="currentView">
  <!-- 组件在 vm.currentview 变化时改变! -->
</component>

也可以直接绑定到组件对象上:

【访问 www.tangshuang.n【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ang.net【本文受版权保护】
var Home = {
  template: '<p>Welcome home!</p>'
}
var vm = new Vue({
  el: '#example',
  data: {
    currentView: Home
  }
})

在动态组件模式下,你可以使用keep-a【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。live指令实现一个缓存效果:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】未经授权,禁止复制转载。
<keep-alive>
  <component :is="currentView">
    <!-- 非活动组件将被缓存! -->
  </component>
</keep-alive>

API 参考查看更多 <keep-alive&转载请注明出处:www.tangshuang.net【本文受版权保护】gt; 的细节。

【访问 www.tangshuang.n【版权所有,侵权必究】【转载请注明来源】et 获取更多精彩内容】【转载请注明来源】【未经授权禁止转载】

异步创建组件

在大型应用中,我们可能需要将应用拆分为多【版权所有,侵权必究】原创内容,盗版必究。个小模块,按需从服务器下载。为了让事情更【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】简单, Vue.js 允许将组件定义为一【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】个工厂函数,动态地解析组件的定义。Vue著作权归作者所有,禁止商业用途转载。【作者:唐霜】.js 只在组件需要渲染时触发工厂函数,未经授权,禁止复制转载。【版权所有,侵权必究】并且把结果缓存起来,用于后面的再次渲染。

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。ng.net【转载请注明来源】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。ang.net

这里的工厂函数和promise的工厂函数【版权所有,侵权必究】原创内容,盗版必究。是一样的,接受resolve, reje【未经授权禁止转载】原创内容,盗版必究。ct两个参数。resolve的时候,将创原创内容,盗版必究。【本文首发于唐霜的博客】建数组所要用到的对象返回即可。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】【转载请注明来源】
Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    // Pass the component definition to the resolve callback
    resolve({
      template: '<div>I am async!</div>'
    })
  }, 1000)
})

工厂函数接收一个 resolve 回调,【本文首发于唐霜的博客】未经授权,禁止复制转载。在收到从服务器下载的组件定义时调用。也可【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net以调用 reject(reason) 指【未经授权禁止转载】【版权所有,侵权必究】示加载失败。

【作者:唐霜】【本文首发于唐霜的博客】原创内容,盗版必究。【作者:唐霜】

递归和循环引用

递归组件

组件在它的模板内可以递归地调用自己,不过【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net,只有当它有 name 选项时才可以:

本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。et 获取更多精彩内容】
name: 'unique-name-of-my-component'

当你利用Vue.component全局注【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。册了一个组件, 全局的ID作为组件的 n【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。ame 选项,被自动设置.

本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【作者:唐霜】ang.net【原创内容,转载请注明出处】
Vue.component('unique-name-of-my-component', {
  // ...
})

如果你不谨慎, 递归组件可能导致死循环:

【本文受版权保护】本文作者:唐霜,转载请注明出处。
name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'

上面组件会导致一个错误 “max sta【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】ck size exceeded” ,所本文版权归作者所有,未经授权不得转载。【转载请注明来源】以要确保递归调用有终止条件 (比如递归调著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net用时使用 v-if 并让他最终返回 fa【作者:唐霜】【版权所有】唐霜 www.tangshuang.netlse )。

【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】et 获取更多精彩内容】未经授权,禁止复制转载。

组件间的循环引用

假设你正在构建一个文件目录树,像在Fin【作者:唐霜】【未经授权禁止转载】der或文件资源管理器中。你可能有一个 【版权所有,侵权必究】【未经授权禁止转载】tree-folder组件:

【本文受版权保护】【访问 www.tangshuang.n【原创内容,转载请注明出处】【本文受版权保护】et 获取更多精彩内容】
<p>
  <span>{{ folder.name }}</span>
  <tree-folder-contents :children="folder.children"/>
</p>

然后 一个tree-folder-con【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】tents组件:

【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。
<ul>
  <li v-for="child in children">
    <tree-folder v-if="child.children" :folder="child"/>
    <span v-else>{{ child.name }}</span>
  </li>
</ul>

当你仔细看时,会发现在渲染树上这两个组件转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。同时为对方的父节点和子节点–这点是矛盾的【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。。当使用Vue.component将这两未经授权,禁止复制转载。【转载请注明来源】个组件注册为全局组件的时候,框架会自动为【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】你解决这个矛盾,如果你是这样做的,就不用原创内容,盗版必究。【作者:唐霜】继续往下看了。

原创内容,盗版必究。【版权所有,侵权必究】【关注微信公众号:wwwtangshua【本文受版权保护】【作者:唐霜】ngnet】

然而,如果你使用诸如Webpack或者B【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】rowserify之类的模块化管理工具来【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。requiring/importing组【版权所有】唐霜 www.tangshuang.net【转载请注明来源】件的话,就会报错了:

本文版权归作者所有,未经授权不得转载。【本文受版权保护】

Failed to mount comp【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netonent: template or r本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】ender function not d【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。efined.

未经授权,禁止复制转载。【未经授权禁止转载】【版权所有】唐霜 www.tangshu原创内容,盗版必究。转载请注明出处:www.tangshuang.netang.net【访问 www.tangshuang.n【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】
【本文受版权保护】本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【版权所有,侵权必究】【原创不易,请尊重版权】ng.net著作权归作者所有,禁止商业用途转载。

为了解释为什么会报错,简单的将上面两个组本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。件称为 A 和 B ,模块系统看到它需要转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。 A ,但是首先 A 需要 B ,但是 【未经授权禁止转载】【本文首发于唐霜的博客】B 需要 A, 而 A 需要 B,陷入了【未经授权禁止转载】转载请注明出处:www.tangshuang.net一个无限循环,因此不知道到底应该先解决哪转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】个。要解决这个问题,我们需要在其中一个组本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net件中(比如 A )告诉模块化管理系统,“本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。A 虽然需要 B ,但是不需要优先导入 【转载请注明来源】原创内容,盗版必究。B”。

【原创内容,转载请注明出处】【作者:唐霜】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【作者:唐霜】ang.net

在我们的例子中,我们选择在tree-fo转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】lder 组件中来告诉模块化管理系统循环著作权归作者所有,禁止商业用途转载。【本文受版权保护】引用的组件间的处理优先级,我们知道引起矛未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net盾的子组件是tree-folder-co本文版权归作者所有,未经授权不得转载。【作者:唐霜】ntents,所以我们在beforeCr原创内容,盗版必究。【原创内容,转载请注明出处】eate 生命周期钩子中去注册它:

【版权所有,侵权必究】未经授权,禁止复制转载。【访问 www.tangshuang.n【本文首发于唐霜的博客】未经授权,禁止复制转载。et 获取更多精彩内容】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。【作者:唐霜】ng.net
beforeCreate: function () {
  this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue')
}

问题解决了。

【原创内容,转载请注明出处】未经授权,禁止复制转载。【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】ngnet】【版权所有,侵权必究】

X-Templates

另一种定义模版的方式是在 JavaScr本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】ipt 标签里使用 text/x-tem本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】plate 类型,并且指定一个id。例如转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。

【版权所有】唐霜 www.tangshu原创内容,盗版必究。本文作者:唐霜,转载请注明出处。ang.net【本文受版权保护】【原创不易,请尊重版权】
<script type="text/x-template" id="hello-world-template">
  <p>Hello hello hello</p>
</script>
Vue.component('hello-world', {
  template: '#hello-world-template'
})

这在有很多模版或者小的应用中有用,否则应【版权所有,侵权必究】【本文首发于唐霜的博客】该避免使用,因为它将模版和组件的其他定义著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。隔离了。

未经授权,禁止复制转载。【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。【本文受版权保护】et 获取更多精彩内容】

对低开销的静态组件使用v-once

尽管在 Vue 中渲染 HTML 很快,著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】不过当组件中包含大量静态内容时,可以考虑转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】使用 v-once 将渲染结果缓存起来,【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。就像这样:

本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】
Vue.component('terms-of-service', {
  template: `<div v-once>
    <h1>Terms of Service</h1>
    ... a lot of static content ...  
  </div>`
})

小结

这一章介绍了vue的核心理念之一——组件转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net。组件的概念并没有想象的那么复杂,简单的著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】说就是一个相对隔离的vue子类的实例化对【作者:唐霜】原创内容,盗版必究。象。怎么来理解这里的“隔离”呢?主要是两转载请注明出处:www.tangshuang.net【作者:唐霜】个方面:

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【作者:唐霜】
  1. 组件通过props属性获取父组件或app【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net层面传来的数据,这些数据不应该被直接修改本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】,也就是说这些数据仅属于组件的上一层,而原创内容,盗版必究。【未经授权禁止转载】不属于当前组件,组件不能通过修改这些数据著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】来影响上一层;
  2. 【本文受版权保护】著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua【原创内容,转载请注明出处】【转载请注明来源】ng.net
  3. 组件不能直接对父组件或app层产生影响,著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】但是可以通过事件绑定对上一层进行事件通知【作者:唐霜】【未经授权禁止转载】,上一层接收到这些通知时,自己决定是否要【转载请注明来源】【版权所有,侵权必究】进行变化。
  4. 转载请注明出处:www.tangshua【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】ng.net【原创内容,转载请注明出处】转载请注明出处:www.tangshua【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。ng.net

组件的另一个话题就是复用性。基于上面两个未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】方面的特性,组件应该是具备高可复用性的,原创内容,盗版必究。【版权所有,侵权必究】当一个地方需要使用这个组件时,只需要实例本文作者:唐霜,转载请注明出处。【本文受版权保护】化,并给适合的props即可。只要pro【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。ps给的符合要求,组件就可以根据自己的逻转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】辑运行,既不受外界影响,也不影响外界。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。

全局和局部

在前文我多次提到了全局和局部的问题,可以本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。看到,好几个操作,其实都存在全局和局部的【本文受版权保护】【关注微信公众号:wwwtangshuangnet】相同操作。但前文我们大部分时间更专注局部【未经授权禁止转载】【作者:唐霜】,本章其实更多从全局角度出发,把之前从来本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。没提过的全局方法,都提一遍。这样可以帮助【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】你更好的全面了解vue的api。

【关注微信公众号:wwwtangshua【关注微信公众号:wwwtangshuangnet】【本文受版权保护】ngnet】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

全局配置

Vue.config 是一个对象,包含 著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netVue 的全局配置。可以在启动应用之前修【原创不易,请尊重版权】【原创内容,转载请注明出处】改下列属性:

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。ang.net

silent

Vue.config.silent = true

optionMergeStrategies

Vue.config.optionMergeStrategies._my_option = function (parent, child, vm) {
  return child + 1
} 
const Profile = Vue.extend({
  _my_option: 1
}) // Profile.options._my_option = 2

devtools

// 务必在加载 Vue 之后,立即同步设置以下内容
Vue.config.devtools = true

errorHandler

Vue.config.errorHandler = function (err, vm) {
  // handle error
}

ignoredElements

Vue.config.ignoredElements = [
  'my-custom-web-component',
  'another-web-component'
]

keyCodes

Vue.config.keyCodes = {
  v: 86,
  f1: 112,
  mediaPlayPause: 179,
  up: [38, 87]
}

全局 API

Vue.extend( options )

<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

结果如下:

【版权所有,侵权必究】【未经授权禁止转载】【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】ngnet】
<p>Walter White aka Heisenberg</p>

Vue.nextTick([callback, context])

// 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
  // DOM 更新了
})

Vue.set( object, key, value )

Vue.delete( object, key )

Vue.directive( id, [definition] )

// 注册
Vue.directive('my-directive', {
  bind: function () {},
  inserted: function () {},
  update: function () {},
  componentUpdated: function () {},
  unbind: function () {}
})
// 注册(传入一个简单的指令函数)
Vue.directive('my-directive', function () {
  // 这里将会被 `bind` 和 `update` 调用
})
// getter,返回已注册的指令
var myDirective = Vue.directive('my-directive')

Vue.filter( id, [definition] )

// 注册
Vue.filter('my-filter', function (value) {
  // 返回处理后的值
})
// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')

Vue.component( id, [definition] )

// 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({ /* ... */ }))
// 注册组件,传入一个选项对象(自动调用 Vue.extend)
Vue.component('my-component', { /* ... */ })
// 获取注册的组件(始终返回构造器)
var MyComponent = Vue.component('my-component')

Vue.use( plugin )

编者按:关于如何开发一个插件,读者应该要【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。学习一下,因为有的时候你确实需要全局实现【原创不易,请尊重版权】【未经授权禁止转载】某些功能。通过插件,可以给Vue这个全局【转载请注明来源】【本文受版权保护】变量加入一些全局方法,也可以给每一个实例转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net加入原型链方法,在组件内使用this.$原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netyourmethod这种方式来执行某些功本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。能。点击上面的参考链接去学习如何写插件。

转载请注明出处:www.tangshua【作者:唐霜】【原创内容,转载请注明出处】ng.net【转载请注明来源】

Vue.mixin( mixin )

编者按:关于混入,如果你学过react应【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。该知道。简单的说就是把几个类合并为一个类【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。,这样,继承这个混合的类的子类就拥有了多本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】个父类的方法。在vue里面,组件也可以使【版权所有,侵权必究】【本文首发于唐霜的博客】用混入来继承组件,在创建组件的时候就可以【作者:唐霜】【本文首发于唐霜的博客】使用一个mixin参数,这在前面的组件一转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】章没有介绍过:

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。
// 定义一个混合对象
var myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}
// 定义一个使用混合对象的组件
var Component = Vue.extend({
  mixins: [myMixin]
})
var component = new Component() // -> "hello from mixin!"

Vue.compile( template )

var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
  data: {
    msg: 'hello'
  },
  render: res.render,
  staticRenderFns: res.staticRenderFns
})

全局注册

全局注册函数直接挂在Vue这个全局对象上【版权所有,侵权必究】【转载请注明来源】。注意下面的方法,都是复数形式。

本文版权归作者所有,未经授权不得转载。【本文受版权保护】未经授权,禁止复制转载。

Vue.directives

全局注册一个指令。这样你就可以在任何的V原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。ue实例上使用这个指令。

【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net【版权所有,侵权必究】et 获取更多精彩内容】【原创内容,转载请注明出处】
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
  // 当绑定元素插入到 DOM 中。
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

Vue.filters

注册或获取全局过滤器。

【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。
// 注册
Vue.filter('my-filter', function (value) {
  // 返回处理后的值
})
// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')

Vue.components

全局注册一个组件。

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】
// 注册
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

局部配置

所谓局部配置,就是在实例化的时候的配置。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netngnet】

parent

指定实例的父实例,例如:

转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netng.net本文作者:唐霜,转载请注明出处。
var parent = new Vue({...})
var child = new Vue({
  parent,
})

这样,就指定了child的父实例是par【本文受版权保护】未经授权,禁止复制转载。ent。当child被实例化出来之后,c【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。hild.$parent就引用paren【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.nett,而parent.$children是本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。一个数组,里面就包含了child,可以用本文作者:唐霜,转载请注明出处。【未经授权禁止转载】parent.$children.ind【未经授权禁止转载】本文作者:唐霜,转载请注明出处。exOf(child) > -1来【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。判断是否是否包含了某个实例。

本文作者:唐霜,转载请注明出处。【作者:唐霜】

mixin

前面已经讲过全局的mixin,其实它也可【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。以在实例化配置时传入:

本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】
var mixin = {
  created: function () {
    console.log(1)
  }
}
var vm = new Vue({
  created: function () {
    console.log(2)
  },
  mixins: [mixin]
})
// -> 1
// -> 2

mixins 选项接受一个混合对象的数组本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。。这些混合实例对象可以像正常的实例对象一【版权所有,侵权必究】【作者:唐霜】样包含选项,他们将在 Vue.exten【作者:唐霜】本文作者:唐霜,转载请注明出处。d() 里最终选择使用相同的选项合并逻辑本文作者:唐霜,转载请注明出处。【本文受版权保护】合并。举例:如果你混合包含一个钩子而创建【未经授权禁止转载】【本文首发于唐霜的博客】组件本身也有一个,两个函数将被调用。Mi【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。xin钩子按照传入顺序依次调用,并在调用【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。组件自身的钩子之前被调用。

【关注微信公众号:wwwtangshua未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。ngnet】【关注微信公众号:wwwtangshua原创内容,盗版必究。【原创内容,转载请注明出处】ngnet】

name

注意,这个选项只对组件的创建起作用。

【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【转载请注明来源】ngnet】【原创不易,请尊重版权】【转载请注明来源】
var MyComponent = Vue.extend({
  name: 'my-component',
})

允许组件模板递归地调用自身。注意,组件在【原创不易,请尊重版权】【未经授权禁止转载】全局用 Vue.component() 未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】注册时,全局 ID 自动作为组件的 na未经授权,禁止复制转载。【原创内容,转载请注明出处】me。

未经授权,禁止复制转载。【访问 www.tangshuang.n【原创不易,请尊重版权】未经授权,禁止复制转载。et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。

指定 name 选项的另一个好处是便于调【原创内容,转载请注明出处】【转载请注明来源】试。有名字的组件有更友好的警告信息。另外未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。,当在有 vue-devtools, 未命名组件将显示成 <Anon【版权所有,侵权必究】【转载请注明来源】ymousComponent>, 原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。这很没有语义。通过提供 name 选项,【版权所有,侵权必究】【原创不易,请尊重版权】可以获得更有语义信息的组件树。

【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。原创内容,盗版必究。ang.net转载请注明出处:www.tangshua【原创内容,转载请注明出处】【转载请注明来源】ng.net

extend

允许声明扩展另一个组件(可以是一个简单的【转载请注明来源】原创内容,盗版必究。选项对象或构造函数),而无需使用 Vue本文作者:唐霜,转载请注明出处。【转载请注明来源】.extend。这主要是为了便于扩展单文【原创内容,转载请注明出处】原创内容,盗版必究。件组件。
本文作者:唐霜,转载请注明出处。 这和 mixins 类似,区别在于,组【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】件自身的选项会比要扩展的源组件具有更高的【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】优先级。

【转载请注明来源】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。ng.net本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】
var CompA = { ... }
// 在没有调用 Vue.extend 时候继承 CompA
var CompB = {  extends: CompA,  ...}

delimiters

改变纯文本插入分隔符。 这个选择只有在独【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。立构建时才有用。

【关注微信公众号:wwwtangshua【未经授权禁止转载】【本文首发于唐霜的博客】ngnet】未经授权,禁止复制转载。【版权所有,侵权必究】

默认值: [“{{̶【本文受版权保护】【作者:唐霜】0;, “}}”【本文受版权保护】【转载请注明来源】]

【转载请注明来源】【原创内容,转载请注明出处】未经授权,禁止复制转载。
new Vue({  delimiters: ['${', '}']})
// 分隔符变成了 ES6 模板字符串的风格

functional

使组件无状态(没有 data )和无实例本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】(没有 this 上下文)。他们用一个简【作者:唐霜】本文作者:唐霜,转载请注明出处。单的 render 函数返回虚拟节点使他【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】们更容易渲染。

【版权所有,侵权必究】【本文首发于唐霜的博客】【本文首发于唐霜的博客】

参考: 函数式组件

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

实例属性

vm.$data

vm.$el

vm.$options

new Vue({
  customOption: 'foo',
  created: function () {
    console.log(this.$options.customOption) // -> 'foo'
  }
})

vm.$parent

vm.$root

vm.$children

vm.$slots

vm.$scopedSlots

2.1.0新增

【原创内容,转载请注明出处】【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】et 获取更多精彩内容】
本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。

vm.$refs

vm.$isServer

实例的数据方法

vm.$watch( expOrFn, callback, [options] )

// 键路径
vm.$watch('a.b.c', function (newVal, oldVal) {
  // 做点什么
})
// 函数
vm.$watch(
  function () {
    return this.a + this.b
  },
  function (newVal, oldVal) {
    // 做点什么
  }
)
// vm.$watch 返回一个取消观察函数,用来停止触发回调:
var unwatch = vm.$watch('a', cb)
// 之后取消观察unwatch()
vm.$watch('someObject', callback, {
  deep: true
})
vm.someObject.nestedValue = 123
// callback is fired
vm.$watch('a', callback, {
  immediate: true
})
// 立即以 `a` 的当前值触发回调

vm.$set( object, key, value )

vm.$delete( object, key )

Render 函数

Vue 推荐在绝大多数情况下使用 tem【未经授权禁止转载】未经授权,禁止复制转载。plate 来创建你的 HTML。然而在未经授权,禁止复制转载。【转载请注明来源】一些场景中,你真的需要 JavaScri转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。pt 的完全编程的能力,这就是 rend未经授权,禁止复制转载。【未经授权禁止转载】er 函数,它比 template 更接本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net近编译器。

未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】ang.net著作权归作者所有,禁止商业用途转载。【本文受版权保护】

特别是在一些通过v-if来确定使用哪一块本文版权归作者所有,未经授权不得转载。【转载请注明来源】内容的时候,你要写很多个v-if来决定使【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。用哪一块内容。但是如果使用render函未经授权,禁止复制转载。原创内容,盗版必究。数,就可以避免这种重复的工作。

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua【本文受版权保护】未经授权,禁止复制转载。ng.net本文版权归作者所有,未经授权不得转载。

什么是render函数?

如果你使用过react,那么应该完全不陌【作者:唐霜】【版权所有,侵权必究】生。render函数是在模板的编译阶段,转载请注明出处:www.tangshuang.net【本文受版权保护】用来编译模板的。在template和re原创内容,盗版必究。【本文受版权保护】nder同时存在的时候,render具有【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】更高的优先级。也就是说,vue实例化的时本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】候,如果你有render函数,那么当实例著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】化进行渲染DOM的时候,render函数【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】是一个决定性的元素,render的返回结【原创内容,转载请注明出处】【转载请注明来源】果,就是最终的DOM渲染结果。

【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netang.net【版权所有,侵权必究】

简单的说,render函数,就是使用ja【未经授权禁止转载】未经授权,禁止复制转载。vascript编程的方式来创建模板(代著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】替template参数),用render原创内容,盗版必究。【本文首发于唐霜的博客】函数的返回值作为模板编译的基础。

【未经授权禁止转载】【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。et 获取更多精彩内容】

如何使用?

先来看段例子:

未经授权,禁止复制转载。【本文受版权保护】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ng.net
Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,
      // tag name 标签名称
      this.$slots.default
      // 子组件中的阵列
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

直接给一个render参数,并且赋予的值著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】是函数即可。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【原创内容,转载请注明出处】未经授权,禁止复制转载。

createElement

createElement函数

从上面的例子你可以看到,render函数【版权所有,侵权必究】原创内容,盗版必究。接收一个参数createElement。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。它本身就是一个函数,是用来生成真正的模板【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】的。

【本文首发于唐霜的博客】转载请注明出处:www.tangshua【原创不易,请尊重版权】【本文首发于唐霜的博客】ng.net转载请注明出处:www.tangshua【本文受版权保护】【版权所有,侵权必究】ng.net【转载请注明来源】
// @returns {VNode}createElement(
  // {String | Object | Function}
  // 一个 HTML 标签字符串,组件选项对象,或者一个返回值类型为String/Object的函数,必要参数
  'div',
  // {Object}
  // 一个包含模板相关属性的数据对象
  // 这样,您可以在 template 中使用这些属性.可选参数.
  {
    // data Object,下面再述
  },
  // {String | Array}
  // 子节点(VNodes),可以是一个字符串或者一个数组. 可选参数.
  [
    createElement('h1', 'hello world'),
    createElement(MyComponent, {
      props: {
        someProp: 'foo'
      }
    }),
    'bar'
  ]
)

它的返回值是一个Virtual DOM 著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】Node,它只存在于vue的虚拟DOM系【版权所有,侵权必究】未经授权,禁止复制转载。统中,并且和实例是对应的,只有当渲染DO著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。M发生之后,它才会转换为真是的DOM节点【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】

【本文受版权保护】原创内容,盗版必究。【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】【原创内容,转载请注明出处】

data Object

上面代码中,第二个参数是一个object【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net,但是可以有哪些内容可以配置呢?

【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】ngnet】【访问 www.tangshuang.n【本文受版权保护】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】
{
  // 和`v-bind:class`一样的 API
  'class': {
    foo: true,
    bar: false
  },
  // 和`v-bind:style`一样的 API
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 正常的 HTML 特性
  attrs: {
    id: 'foo'
  },
  // 组件 props
  props: {
    myProp: 'bar'
  },
  // DOM 属性
  domProps: {
    innerHTML: 'baz'
  },
  // 事件监听器基于 "on"
  // 所以不再支持如 v-on:keyup.enter 修饰器
  // 需要手动匹配 keyCode。
  on: {
    click: this.clickHandler
  },
  // 仅对于组件,用于监听原生事件,而不是组件内部使用 vm.$emit 触发的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定义指令. 注意事项:不能对绑定的旧值设值
  // Vue 会为您持续追踪
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // Scoped slots in the form of
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => h('span', props.text)
  },
  // 如果组件是其他组件的子组件,需为slot指定名称
  slot: 'name-of-slot',
  // 其他特殊顶层属性
  key: 'myKey',
  ref: 'myRef'
}

VNodes 必须唯一

组件树中的所有 VNodes 必须是唯一【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。的。这意味着,下面的 render fu本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。nction 是无效的:

著作权归作者所有,禁止商业用途转载。【作者:唐霜】原创内容,盗版必究。
render: function (createElement) {
  var myParagraphVNode = createElement('p', 'hi')
  return createElement('div', [
    // 错误-重复的VNodes
    myParagraphVNode, myParagraphVNode
  ])
}

如果你真的需要重复很多次的元素/组件,你【原创不易,请尊重版权】【本文首发于唐霜的博客】可以使用工厂函数来实现。例如,下面这个例【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】子 render 函数完美有效地渲染了 【版权所有,侵权必究】未经授权,禁止复制转载。20 个重复的段落:

【版权所有,侵权必究】【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】et 获取更多精彩内容】【作者:唐霜】
render: function (createElement) {
  return createElement('div',
    Array.apply(null, { length: 20 }).map(function () {
      return createElement('p', 'hi')
    })
  )
}

一旦你开始使用render函数,你就可以【作者:唐霜】本文版权归作者所有,未经授权不得转载。使用createElement函数完全代转载请注明出处:www.tangshuang.net原创内容,盗版必究。替模板,通过javascript逻辑来创【原创不易,请尊重版权】【本文受版权保护】建复杂的模板逻辑。当然,这样做会让模板可【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】读性变得很差,于是,你可以使用jsx。

【关注微信公众号:wwwtangshua【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netngnet】【作者:唐霜】

JSX

如果你写了很多 render 函数,可能【本文受版权保护】原创内容,盗版必究。会觉得痛苦。特别是模板极其简单的情况下。
原创内容,盗版必究。 这就是会有一个 Babel plugin 插件,用于在 Vue 中使用 JSX 【原创内容,转载请注明出处】【本文首发于唐霜的博客】语法的原因,它可以让我们回到于更接近模板未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】的语法上。

【版权所有,侵权必究】【作者:唐霜】【作者:唐霜】
import AnchoredHeading from './AnchoredHeading.vue'
new Vue({
  el: '#demo',
  render (h) {
    return (
      <AnchoredHeading level={1}>
        <span>Hello</span> world!
      </AnchoredHeading>
    )
  }
})

将 h 作为 createElement著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。 的别名是 Vue 生态系统中的一个通用【转载请注明来源】【原创不易,请尊重版权】惯例,实际上也是 JSX 所要求的,如果【本文受版权保护】【作者:唐霜】在作用域中 h 失去作用, 在应用中会触【版权所有】唐霜 www.tangshuang.net【本文受版权保护】发报错。

本文作者:唐霜,转载请注明出处。【转载请注明来源】【未经授权禁止转载】

更多关于 JSX 映射到 JavaScr【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。ipt,阅读 使用文档

【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【未经授权禁止转载】

特殊属性

Vue里面使用了DOM模板,也就是说,所【作者:唐霜】【本文受版权保护】有元素的属性(attr或prop)首先可本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】以被HTML解析识别。而如果不是HTML【本文首发于唐霜的博客】【未经授权禁止转载】本身内置的属性的话,vue可以自己在编译【本文受版权保护】【本文首发于唐霜的博客】模板的时候对这些属性进行解析,主要包括下【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。列属性:

【作者:唐霜】【访问 www.tangshuang.n【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【作者:唐霜】

除了上述这些属性之外,比如,我们给一个元本文作者:唐霜,转载请注明出处。【本文受版权保护】素添加了go属性<div go="-1"></div>,这个属性不会起到任何作用,当然,你可以【转载请注明来源】本文作者:唐霜,转载请注明出处。用css来改变它的样式,但是在元素本身层【作者:唐霜】本文版权归作者所有,未经授权不得转载。面上,真没用。回到主题,本章要讲vue的转载请注明出处:www.tangshuang.net【作者:唐霜】内置的特殊属性。

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。

key

key 的特殊属性主要用在 Vue的虚拟转载请注明出处:www.tangshuang.net【版权所有,侵权必究】DOM算法,在新旧nodes对比时辨识V【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.netNodes。如果不使用key,Vue会使未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。用一种最大限度减少动态元素并且尽可能的尝【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。试修复/再利用相同类型元素的算法。使用k转载请注明出处:www.tangshuang.net原创内容,盗版必究。ey,它会基于key的变化重新排列元素顺原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。序,并且会移除key不存在的元素。

【版权所有,侵权必究】【未经授权禁止转载】【转载请注明来源】原创内容,盗版必究。

有相同父元素的子元素必须有独特的key。【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。重复的key会造成渲染错误。

本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】

最常见的用例是结合 v-for:

转载请注明出处:www.tangshua原创内容,盗版必究。【原创不易,请尊重版权】ng.net【未经授权禁止转载】【本文受版权保护】
<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>

它也可以用于强制替换元素/组件而不是重复转载请注明出处:www.tangshuang.net【本文受版权保护】使用它。当你遇到如下场景时它可能会很有用本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。:

本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu【作者:唐霜】【原创内容,转载请注明出处】ang.net【本文首发于唐霜的博客】【作者:唐霜】

例如:

【原创内容,转载请注明出处】【版权所有,侵权必究】
<transition>
  <span :key="text">{{ text }}</span>
</transition>

当 text 发生改变时,<spa【作者:唐霜】本文版权归作者所有,未经授权不得转载。n> 会随时被更新,因此会触发过渡本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net

【关注微信公众号:wwwtangshua原创内容,盗版必究。【版权所有,侵权必究】ngnet】本文版权归作者所有,未经授权不得转载。【本文受版权保护】【原创不易,请尊重版权】

ref

ref 被用来给元素或子组件注册引用信息【原创不易,请尊重版权】未经授权,禁止复制转载。。引用信息将会注册在父组件的 $refs著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。 对象上。如果在普通的 DOM 元素上使原创内容,盗版必究。【本文受版权保护】用,引用指向的就是 DOM 元素; 如果【作者:唐霜】本文作者:唐霜,转载请注明出处。用在子组件上,引用就指向组件实例:

【作者:唐霜】转载请注明出处:www.tangshua【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】ng.net原创内容,盗版必究。
<!-- vm.$refs.p will be the DOM node -->
<p ref="p">hello</p>
<!-- vm.$refs.child will be the child comp instance -->
<child-comp ref="child"></child-comp>

当 v-for 用于元素或组件的时候,引【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。用信息将是包含 DOM 节点或组件实例的【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】数组。

【版权所有,侵权必究】【转载请注明来源】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

关于ref注册时间的重要说明: 因为re【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netf本身是作为渲染结果被创建的,在初始渲染【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。的时候你不能访问它们 – 它【转载请注明来源】原创内容,盗版必究。们还不存在!$refs 也不是响应式的,本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。因此你不应该试图用它在模版中做数据绑定。

【未经授权禁止转载】【未经授权禁止转载】

slot

用于标记往哪个slot中插入子组件内容。【未经授权禁止转载】【原创内容,转载请注明出处】详细用法,请参考下面指南部分的链接。

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

内置组件

我们新注册一个组件之后,就可以用这个组件本文作者:唐霜,转载请注明出处。原创内容,盗版必究。的名称作为一个html元素插入到你的模板本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】中去。但是,vue保留了几个组件名,而这原创内容,盗版必究。【本文首发于唐霜的博客】几个组件可以直接调用,是vue的内置组件【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net,实现对应的功能。

未经授权,禁止复制转载。【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。

component

<!-- 动态组件由 vm 实例的属性值 `componentId` 控制 -->
<component :is="componentId"></component>
<!-- 也能够渲染注册过的组件或 prop 传入的组件 -->
<component :is="$options.components.child"></component>

transition

<!-- 简单元素 -->
<transition>
  <div v-if="ok">toggled content</div>
</transition>
<!-- 动态组件 -->
<transition name="fade" mode="out-in" appear>
  <component :is="view"></component>
</transition>
<!-- 事件钩子 -->
<div id="transition-demo">
  <transition @after-enter="transitionComplete">
    <div v-show="ok">toggled content</div>
  </transition>
</div>

new Vue({
  ...
  methods: {
    transitionComplete: function (el) {
      // 传入 'el' 这个 DOM 元素作为参数。
    }
  }
  ...
}).$mount('#transition-demo')

transition-group

<transition-group tag="ul" name="slide">
  <li v-for="item in items" :key="item.id">
    {{ item.text }}
  </li>
</transition-group>

keep-alive

<!-- 基本 -->
<keep-alive>
  <component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
  <comp-a v-if="a > 1"></comp-a>
  <comp-b v-else></comp-b>
</keep-alive>
<!-- 和 <transition> 一起使用 -->
<transition>
  <keep-alive>
    <component :is="view"></component>
  </keep-alive>
</transition>
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 v-bind) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

slot

Ajax请求:vue-resource

写前端应用,不可能绕过ajax请求数据。【版权所有】唐霜 www.tangshuang.net【作者:唐霜】现在已经有比较多专门处理数据请求的模块,【未经授权禁止转载】【本文首发于唐霜的博客】比如axio,以及近期火起来的fetch著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。。vue官方也提供了一个插件(后面会有专【原创内容,转载请注明出处】【本文首发于唐霜的博客】门的章节讲插件)vue-resource【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。,它是专门用来为vue提供数据请求的。当【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】然,其实你也可以不用,而使用其他的aja未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。x请求模块,甚至在vue里面混合使用jq原创内容,盗版必究。原创内容,盗版必究。uery。anyway,我们这一章主要介转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。绍vue-resource。

【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】ang.net【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。ang.net

这里有个小故事,vue-resource著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。不是官方开发的,而是vue的一个早期用户未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】开发的,后来官方觉得很好,就作为了官方推本文作者:唐霜,转载请注明出处。【转载请注明来源】荐插件。因为插件的使用非常方便,使用文档【原创内容,转载请注明出处】【转载请注明来源】太少,以至于都没有专门的一个网站来介绍它【作者:唐霜】【未经授权禁止转载】,你可以直接在github上看它的文档和源码。如果你想看中文快速入门的资料,可以看这位作者写的教程,非常简单,但很容易入门。

【作者:唐霜】【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。原创内容,盗版必究。ang.net【未经授权禁止转载】【本文受版权保护】

安装

如果是用<script>引入【原创内容,转载请注明出处】未经授权,禁止复制转载。vue-resource,那就很简单了,【本文受版权保护】【原创不易,请尊重版权】不用说,但是它需要在vue.js引入之后著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。,你的代码开始之前引入vue-resou本文作者:唐霜,转载请注明出处。【未经授权禁止转载】rce.js,这样才能正常使用。
【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】ngnet】 如果使用npm安装,并且使用模块化方式【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net引入,那么应该这样:

本文版权归作者所有,未经授权不得转载。【转载请注明来源】【原创不易,请尊重版权】
import Vue from 'vue'import VueResource from 'vue-resource'
Vue.use(VueResource)

Vue.use就是使用插件的一个方法,使转载请注明出处:www.tangshuang.net【未经授权禁止转载】用之后,全局支持VueResource。本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。下面的一切介绍,都基于这个use,这得你【作者:唐霜】本文作者:唐霜,转载请注明出处。读到后文的插件一章才能完全理解,目前来讲【转载请注明来源】【本文受版权保护】,你只需要这样去操作即可。

未经授权,禁止复制转载。【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。ang.net

配置方式

使用全局配置设置默认值

【原创不易,请尊重版权】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。
Vue.http.options.root = '/root';
Vue.http.headers.common['Authorization'] = 'Basic YXBpOnBhc3N3b3Jk';

在你的Vue组件配置中设置默认值

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【转载请注明来源】ngnet】
new Vue({
  http: {
    root: '/root',
    headers: {
      Authorization: 'Basic YXBpOnBhc3N3b3Jk'
    }
  }
})

调用方式

全局调用

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。
Vue.http(options)

实例内调用

【本文受版权保护】【访问 www.tangshuang.n【转载请注明来源】【版权所有,侵权必究】et 获取更多精彩内容】原创内容,盗版必究。【本文首发于唐霜的博客】
this.$http(options)

便捷方法

选项

参数 类型 描述
url string 请求的目标URL
body Object, FormData, string 作为请求体发送的数据
headers Object 作为请求头部发送的头部对象
params Object 作为URL参数的参数对象
method string HTTP方法 (例如GET,POST,…)
timeout number 请求超时(单位:毫秒) (0表示永不超时)
before function(request) 在请求发送之前修改请求的回调函数
progress function(event) 用于处理上传进度的回调函数 ProgressEvent
credentials boolean 是否需要出示用于跨站点请求的凭据
emulateHTTP boolean 是否需要通过设置X-HTTP-Method-Override头部并且以传统POST方式发送PUT,PATCH和DELETE请求。
emulateJSON boolean 设置请求体的类型为application/x-www-form-urlencoded

响应

vue-resource的请求实际是一个【转载请注明来源】未经授权,禁止复制转载。promise,响应的时候就可以通过.t【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。hen来获取响应结果。

【版权所有,侵权必究】【本文受版权保护】

通过如下属性和方法处理一个请求获取到的响【原创不易,请尊重版权】【本文首发于唐霜的博客】应对象:

【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。
属性 类型 描述
url string 响应的URL源
body Object, Blob, string 响应体数据
headers Header 请求头部对象
ok boolean 当HTTP响应码为200到299之间的数值时该值为true
status number HTTP响应吗
statusText string HTTP响应状态
方法 类型 描述
text() 约定值 以字符串方式返回响应体
json() 约定值 以格式化后的json对象方式返回响应体
blob() 约定值 以二进制Blob对象方式返回响应体

举个栗子:

【原创内容,转载请注明出处】【作者:唐霜】【版权所有,侵权必究】
// POST /someUrl
this.$http.post('/someUrl', {foo: 'bar'}).then((response) => {
  // get status
  response.status;
  // get status text
  response.statusText;
  // get 'Expires' header
  response.headers.get('Expires');
  // set data on vm
  this.$set('someData', response.body);
  // 下面这句厉害了,它让你的下一个then可以得到返回的json数据
  return response.json()
}, (response) => {
  // error callback
})
.then(data => {
  // 因为上面return response.json(),所以这里的data就是服务端返回的json数据
})

使用blob()方法从响应中获取一副图像【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。的内容。你甚至可以用这个blob来直接显【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】示图片,而不是通过图片的src。

【未经授权禁止转载】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。

拦截器

全局定义拦截器后,它可用于前置和后置处理本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。请求。

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。

请求处理

Vue.http.interceptors.push((request, next) => {
  // modify request
  request.method = 'POST';
  // continue to next interceptor
  next();
});

请求与响应处理

Vue.http.interceptors.push((request, next) => {
  // modify request
  request.method = 'POST';
  // continue to next interceptor
  next((response) => {
    // modify response
    response.body = '...';
  });
});

返回一个响应并且停止处理

Vue.http.interceptors.push((request, next) => {
  // modify request ...
  // stop and return response
  next(request.respondWith(body, {
    status: 404,
    statusText: 'Not found'
  }));
});

资源方式

如果你和restful接口交换数据,那么转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。就有一个“资源”的概念,资源对应一个ur本文作者:唐霜,转载请注明出处。原创内容,盗版必究。l,所以vue-resource有一个更【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。加抽象的方法:Vue.resource或【原创不易,请尊重版权】未经授权,禁止复制转载。this.$resource。

【本文受版权保护】转载请注明出处:www.tangshua【本文受版权保护】【转载请注明来源】ng.net本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

方法

let rsrc = this.$resource(url, [params], [actions], [options])

这里的rsrc就是建立的一个资源实例,你【作者:唐霜】本文版权归作者所有,未经授权不得转载。可以对它进行restful的操作,操作方【作者:唐霜】【版权所有】唐霜 www.tangshuang.net法如下。来说一下参数:

著作权归作者所有,禁止商业用途转载。【作者:唐霜】

url模板

vue-resource使用了url-t转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。emplate来解析url模板,有兴趣的著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】同学可以去研究一下url-templat【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】e。具体来说,就是下面这种用法:

著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】
let rsrc = this.$resource('/book/{id}', {id: 12})

上面说了第二个参数prams是url模板【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】的参数。按照上面这个代码,resourc本文作者:唐霜,转载请注明出处。【作者:唐霜】e的url会指向:/book/12,这个本文作者:唐霜,转载请注明出处。【转载请注明来源】应该非常好理解。

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】ang.net

默认操作

get: {method: 'GET'},
save: {method: 'POST'},
query: {method: 'GET'},
update: {method: 'PUT'},
remove: {method: 'DELETE'},
delete: {method: 'DELETE'},

怎么用呢?

【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】ang.net转载请注明出处:www.tangshua【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netng.net【本文首发于唐霜的博客】
rsrc.get(options).then(..)..

操作只有一个参数options,opti转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。ons里面就可以放headers了。它的【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。返回值就是上面$http的响应了。

本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netngnet】

自定义操作

上面说道,actions这个参数可以让你【本文首发于唐霜的博客】【转载请注明来源】自己自定义自己的操作。比如:

【转载请注明来源】未经授权,禁止复制转载。【原创内容,转载请注明出处】
let actions = {
  patch: {
    method: 'PATCH',
  },
}
let rsrc = this.$srouce('/book/{id}', {id: 12}, actions)
rsrc.patch().then(..)..

相当于你自己新增一个方法,它的参数也是o转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netptions。

【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netngnet】【作者:唐霜】【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

头部对象

{
  // Constructor
  constructor(object: headers)
  // Properties
  map (object)
  // Methods
  has(string: name) (boolean)
  get(string: name) (string)
  getAll() (string[])
  set(string: name, string: value) (void)
  append(string: name, string: value) (void)
  delete(string: name) (void)
  forEach(function: callback, any: thisArg) (void)
}

怎么用头部呢?比如要要请求一个资源的时候著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】,必须通过头部来进行验证:

本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshua【本文首发于唐霜的博客】原创内容,盗版必究。ngnet】原创内容,盗版必究。【关注微信公众号:wwwtangshua【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】ngnet】
var headers = {
  'User-Token': 'xxx',
}
var options = {
  headers,
}
var rsrc = this.$resource(url, options)rsrc.get().then(..)...

但是有个点需要注意一下,发送header本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】s只需要传入一个对象字面量,而返回的re本文版权归作者所有,未经授权不得转载。【转载请注明来源】sponse里面的headers是一个h原创内容,盗版必究。【作者:唐霜】ttp Header对象。Header对【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。象就有本节上述的这些属性和方法。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netang.net

发送表单数据

使用FormData发送表单。

本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。
{
  var formData = new FormData();
  // append string
  formData.append('foo', 'bar');
  // append Blob/File object
  formData.append('pic', fileInput, 'mypic.jpg');
  // POST /someUrl
  this.$http.post('/someUrl', formData).then((response) => {
    // success callback
  }, (response) => {
    // error callback
  });
}

终止请求

当一个新的请求被发送的时候请终止上一个请【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】求。例如在一个自动完成的输入框中输入的时本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。候。

转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】ng.net【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。ngnet】原创内容,盗版必究。
{
  // GET /someUrl
  this.$http.get('/someUrl', {
    // use before callback
    before(request) {
      // abort previous request, if exists
      if (this.previousRequest) {
        this.previousRequest.abort();
      }
      // set previous request on Vue instance
      this.previousRequest = request;
    }
  }).then((response) => {
    // success callback
  }, (response) => {
    // error callback
  });
}

插件

本章教你怎么给vue写插件。但是,在写插【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】件之前,你应该回忆一下,前面我们说过,用【作者:唐霜】【版权所有】唐霜 www.tangshuang.netVue.use安装插件。知道怎么用之后,转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】在来看怎么开发一个插件就比较容易理解一些【关注微信公众号:wwwtangshuangnet】【作者:唐霜】

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【转载请注明来源】转载请注明出处:www.tangshuang.netng.net

开发插件

插件通常会为Vue添加全局功能。插件的范本文作者:唐霜,转载请注明出处。【转载请注明来源】围没有限制——一般有下面几种:

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】ng.net本文版权归作者所有,未经授权不得转载。
  1. 添加全局方法或者属性,如: vue-element
  2. 转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。ng.net【作者:唐霜】【本文受版权保护】
  3. 添加全局资源:指令/过滤器/过渡(过渡也转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】是vue里面的一项功能,会在下面的章节详未经授权,禁止复制转载。【版权所有,侵权必究】细阐述)等,如 vue-touch
  4. 【转载请注明来源】转载请注明出处:www.tangshua【版权所有,侵权必究】【原创内容,转载请注明出处】ng.net【本文受版权保护】
  5. 通过全局 mixin方法添加一些组件选项本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】,如: vuex
  6. 转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【转载请注明来源】ng.net【本文首发于唐霜的博客】【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。
  7. 添加 Vue 实例方法,通过把它们添加到未经授权,禁止复制转载。未经授权,禁止复制转载。 Vue.prototype 上实现。
  8. 本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】et 获取更多精彩内容】
  9. 一个库,提供自己的 API,同时提供上面【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】提到的一个或多个功能,如 vue-router
  10. 【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n【原创内容,转载请注明出处】【转载请注明来源】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu原创内容,盗版必究。未经授权,禁止复制转载。ang.net

Vue.js 的插件应当有一个公开方法 【本文受版权保护】【原创不易,请尊重版权】install 。这个方法的第一个参数是【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net Vue 构造器 , 第二个参数是一个可本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】选的选项对象:

本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】【原创内容,转载请注明出处】
MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或属性
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }
  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })
  // 3. 注入组件
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })
  // 4. 添加实例属性或方法
  Vue.prototype.$myMethod = function (options) {
    // 逻辑...
  }
}

利用上面四种方式,你就可以更好的控制你的原创内容,盗版必究。【未经授权禁止转载】组件或应用了。而除了第4种,前面三种你在【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】前面其实已经阅读到过了,有兴趣可以回到对【本文首发于唐霜的博客】未经授权,禁止复制转载。应的章节复习一下。

【版权所有】唐霜 www.tangshu【转载请注明来源】原创内容,盗版必究。ang.net转载请注明出处:www.tangshua【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。ng.net【未经授权禁止转载】

使用插件

通过全局方法 Vue.use() 使用插著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。件:

未经授权,禁止复制转载。未经授权,禁止复制转载。未经授权,禁止复制转载。
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

也可以传入一个选项对象:

本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】
Vue.use(MyPlugin, { someOption: true })

Vue.use 会自动阻止注册相同插件多【本文受版权保护】本文版权归作者所有,未经授权不得转载。次,届时只会注册一次该插件。
【原创内容,转载请注明出处】 一些插件,如 vue-router 如本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。果 Vue 是全局变量则自动调用 Vue著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】.use() 。不过在模块环境中应当始终原创内容,盗版必究。未经授权,禁止复制转载。显式调用 Vue.use() :

著作权归作者所有,禁止商业用途转载。【转载请注明来源】【转载请注明来源】
// 通过 Browserify 或 Webpack 使用 CommonJS 兼容模块
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了调用此方法
Vue.use(VueRouter)

生命周期

生命周期,是组件思想中非常重要的一个环节【作者:唐霜】著作权归作者所有,禁止商业用途转载。。简单的说就是一个组件从一个类,被实例化原创内容,盗版必究。【原创内容,转载请注明出处】之后执行的一系列操作,到最后这个实例被销【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】毁的整个过程。

未经授权,禁止复制转载。【访问 www.tangshuang.n【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】【作者:唐霜】未经授权,禁止复制转载。

什么是生命周期?

每个 Vue 实例在被创建之前都要经过一【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。系列的初始化过程。例如,实例需要配置数据本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net观测(data observer)、编译【版权所有,侵权必究】转载请注明出处:www.tangshuang.net模版、挂载实例到 DOM ,然后在数据变【原创内容,转载请注明出处】未经授权,禁止复制转载。化时更新 DOM 。在这个过程中,实例也【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。会调用一些 生命周期钩子 ,这就给我们提【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。供了执行自定义逻辑的机会。

原创内容,盗版必究。转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】ng.net【原创不易,请尊重版权】

我们只需要在实例中使用这些钩子函数,那么本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。当生命周期进行到特定位置时,就会调用这些【未经授权禁止转载】未经授权,禁止复制转载。函数,从而进行函数中规定的操作,这样就可【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net以在一个实例的不同生命阶段执行一些你想要未经授权,禁止复制转载。【原创不易,请尊重版权】执行的操作。

【本文首发于唐霜的博客】【本文受版权保护】

钩子的 this 指向调用它的 Vue 【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】实例。一些用户可能会问 Vue.js 是【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。否有“控制器”的概念?答案是,没有。组件【原创不易,请尊重版权】未经授权,禁止复制转载。的自定义逻辑可以分布在这些钩子中。

【作者:唐霜】【未经授权禁止转载】【转载请注明来源】

生命周期示意图


未经授权,禁止复制转载。 不用牢牢记住这张图,你需要的时候,打开【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。本书,找到这里即可。这张图将来会在你的开著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。发中经常用到。

【版权所有,侵权必究】转载请注明出处:www.tangshua【未经授权禁止转载】原创内容,盗版必究。ng.net【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。

生命周期钩子函数

所有的生命周期钩子自动绑定 this 上本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】下文到实例中,因此你可以访问数据,对属性【作者:唐霜】未经授权,禁止复制转载。和方法进行运算。这意味着 你不能使用箭头【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】函数来定义一个生命周期方法 (例如 cr著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.neteated: () => this【原创不易,请尊重版权】【原创不易,请尊重版权】.fetchTodos())。这是因为箭【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net头函数绑定了父上下文,因此 this 与著作权归作者所有,禁止商业用途转载。【作者:唐霜】你期待的 Vue 实例不同, this.【本文首发于唐霜的博客】【未经授权禁止转载】fetchTodos 的行为未定义。

【版权所有,侵权必究】【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】et 获取更多精彩内容】

beforeCreate

在实例初始化之后,数据观测(data o【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。bserver) 和 event/wat【本文受版权保护】【版权所有】唐霜 www.tangshuang.netcher 事件配置之前被调用。

未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】ang.net

created

实例已经创建完成之后被调用。在这一步,实【本文受版权保护】著作权归作者所有,禁止商业用途转载。例已完成以下的配置:数据观测(data 本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。observer),属性和方法的运算, 本文作者:唐霜,转载请注明出处。【本文受版权保护】watch/event 事件回调。然而,【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net挂载阶段还没开始,$el 属性目前不可见【作者:唐霜】转载请注明出处:www.tangshuang.net

【作者:唐霜】原创内容,盗版必究。【原创内容,转载请注明出处】

beforeMount

在挂载开始之前被调用:相关的 rende本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netr 函数首次被调用。

【转载请注明来源】【访问 www.tangshuang.n【转载请注明来源】【本文首发于唐霜的博客】et 获取更多精彩内容】

该钩子在服务器端渲染期间不被调用。

【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshu【转载请注明来源】【作者:唐霜】ang.net

mounted

el 被新创建的 vm.$el 替换,并原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。挂载到实例上去之后调用该钩子。如果 ro【作者:唐霜】原创内容,盗版必究。ot 实例挂载了一个文档内元素,当 mo未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。unted 被调用时 vm.$el 也在【版权所有,侵权必究】未经授权,禁止复制转载。文档内。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【本文首发于唐霜的博客】【访问 www.tangshuang.n【本文受版权保护】【未经授权禁止转载】et 获取更多精彩内容】

该钩子在服务器端渲染期间不被调用。

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【访问 www.tangshuang.n【作者:唐霜】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】

beforeUpdate

数据更新时调用,发生在虚拟 DOM 重新【本文受版权保护】转载请注明出处:www.tangshuang.net渲染和打补丁之前。

【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netang.net【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。ngnet】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。ang.net

你可以在这个钩子中进一步地更改状态,这不【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】会触发附加的重渲染过程。

本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【作者:唐霜】ang.net

该钩子在服务器端渲染期间不被调用。

【未经授权禁止转载】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ng.net著作权归作者所有,禁止商业用途转载。

updated

由于数据更改导致的虚拟 DOM 重新渲染本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】和打补丁,在这之后会调用该钩子。

【未经授权禁止转载】【访问 www.tangshuang.n未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】

当这个钩子被调用时,组件 DOM 已经更原创内容,盗版必究。本文作者:唐霜,转载请注明出处。新,所以你现在可以执行依赖于 DOM 的【原创不易,请尊重版权】【转载请注明来源】操作。然而在大多数情况下,你应该避免在此本文作者:唐霜,转载请注明出处。原创内容,盗版必究。期间更改状态,因为这可能会导致更新无限循著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。环。

【版权所有,侵权必究】【本文首发于唐霜的博客】

该钩子在服务器端渲染期间不被调用。

【未经授权禁止转载】【作者:唐霜】转载请注明出处:www.tangshua【原创内容,转载请注明出处】原创内容,盗版必究。ng.net本文作者:唐霜,转载请注明出处。

activated

keep-alive 组件激活时调用。
【原创不易,请尊重版权】 该钩子在服务器端渲染期间不被调用。

【本文首发于唐霜的博客】【原创内容,转载请注明出处】原创内容,盗版必究。

参考:构建组件 – keep-al【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。ive动态组件 – keep-al【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】ive

【版权所有,侵权必究】【作者:唐霜】本文版权归作者所有,未经授权不得转载。

deactivated

keep-alive 组件停用时调用。
【作者:唐霜】 该钩子在服务器端渲染期间不被调用。

【本文首发于唐霜的博客】原创内容,盗版必究。

beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全原创内容,盗版必究。【原创内容,转载请注明出处】可用。
本文版权归作者所有,未经授权不得转载。 该钩子在服务器端渲染期间不被调用。

【转载请注明来源】【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netngnet】原创内容,盗版必究。未经授权,禁止复制转载。

destroyed

Vue 实例销毁后调用。调用后,Vue 【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。实例指示的所有东西都会解绑定,所有的事件本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。监听器会被移除,所有的子实例也会被销毁。
【原创内容,转载请注明出处】 该钩子在服务器端渲染期间不被调用。

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

Virtual DOM 虚拟DOM

终于写(copy)了那么多章之后,要来谈【转载请注明来源】本文版权归作者所有,未经授权不得转载。一谈Virtual DOM。相信很多人对【作者:唐霜】转载请注明出处:www.tangshuang.net这项技术早都垂涎三尺,想要对它的原理进行本文作者:唐霜,转载请注明出处。原创内容,盗版必究。窥探。本章将结合vue简单梳理Virtu【转载请注明来源】【未经授权禁止转载】al DOM的原理。

【版权所有,侵权必究】【未经授权禁止转载】

vue2.0之后才支持Virtual D本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】OM,它介于编译template和渲染界【关注微信公众号:wwwtangshuangnet】【作者:唐霜】面之间。

【版权所有】唐霜 www.tangshu【原创不易,请尊重版权】【本文受版权保护】ang.net【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】ngnet】转载请注明出处:www.tangshua【本文首发于唐霜的博客】【原创内容,转载请注明出处】ng.net

Virtual DOM的灵感来源

DOM是一个很昂贵的对象,之所以昂贵,是未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。因为它内部的方法太多,而且相互联系。DO著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netM本质也是一个对象,但是这个对象首先有非本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】常多的属性和方法,一个DOM节点对象就会【本文受版权保护】未经授权,禁止复制转载。占用非常多的内存,其次,当你操作DOM节【本文受版权保护】【原创内容,转载请注明出处】点的时候,DOM对象会不断操作自己,同时著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。还会操作和自己相关的其他DOM节点对象,【未经授权禁止转载】本文作者:唐霜,转载请注明出处。所以整个DOM树是牵一发而动全身,操作D【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。OM就会消耗很多资源。

【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

既然DOM是一个对象,跟javascri著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】pt的其他对象并没有本质上的不同,那么,【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net可以不可以在另一个空间复制一个和DOM结【作者:唐霜】本文作者:唐霜,转载请注明出处。构相同的对象,但是,这个新的对象会删除很转载请注明出处:www.tangshuang.net【未经授权禁止转载】多方法或属性,只保留几个必要的,而操作这本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】些对象的时候,不会有那么高消耗的连带操作【版权所有,侵权必究】【原创内容,转载请注明出处】,这样操作这个对象和操作DOM就完全是两【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。回事,性能上肯定快很多。最后,就是当操作【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】完之后,怎么把这个对象跟真实的DOM映射【原创不易,请尊重版权】【本文受版权保护】起来?你可能还记得前面提到过一个key属原创内容,盗版必究。【本文首发于唐霜的博客】性,通过一个唯一标记来确定哪些位置改变了【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net,针对这些改变的对象,找到对应的DOM节【版权所有,侵权必究】【作者:唐霜】点,进行重新渲染。

【原创内容,转载请注明出处】【版权所有,侵权必究】未经授权,禁止复制转载。原创内容,盗版必究。

vue2.0中的Virtual DOM

在前面的阅读中,你已经见过VNode了,【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net它是vue2里面加入的一种新对象,用来实转载请注明出处:www.tangshuang.net【作者:唐霜】现Virtual DOM。在vue渲染真【本文受版权保护】【关注微信公众号:wwwtangshuangnet】实的DOM之前,内部的响应式系统改变的都原创内容,盗版必究。转载请注明出处:www.tangshuang.net是VNode。响应式系统在下一章讲。

【本文首发于唐霜的博客】转载请注明出处:www.tangshua原创内容,盗版必究。【转载请注明来源】ng.net【作者:唐霜】【版权所有】唐霜 www.tangshu【本文受版权保护】未经授权,禁止复制转载。ang.net

VNode模拟DOM树

在vue中Virtual DOM是通过V【原创内容,转载请注明出处】【未经授权禁止转载】Node类来表达的,每个DOM元素或vu著作权归作者所有,禁止商业用途转载。【转载请注明来源】e组件都对应一个VNode对象。VNod原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。e结构如下(图来自《vue.js权威指南【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。》):
【未经授权禁止转载】

【原创不易,请尊重版权】【本文首发于唐霜的博客】

VNode

它包含了tag, text, elm, 【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】data, parent, childr【转载请注明来源】著作权归作者所有,禁止商业用途转载。en等属性。它可以由真实的DOM生成,也转载请注明出处:www.tangshuang.net【转载请注明来源】可以由组件生成。如果由组件生成的话,VN【本文首发于唐霜的博客】原创内容,盗版必究。ode的componentOptions本文作者:唐霜,转载请注明出处。【未经授权禁止转载】有值,而如果由DOM生成,则该值空。

【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ngnet】【原创内容,转载请注明出处】转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【作者:唐霜】ng.net

那么有什么方法获取一个元素的VNode呢未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。?没有。

【未经授权禁止转载】【访问 www.tangshuang.n【原创内容,转载请注明出处】【版权所有,侵权必究】et 获取更多精彩内容】【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。ang.net

VNodeComponentOptions

如果VNode是由组件生成的,所有的组件【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net相关信息都在这个对象里面。

原创内容,盗版必究。【版权所有,侵权必究】【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】ang.net未经授权,禁止复制转载。

VNodeData

VNode中的节点数据data属性的详细【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。描述,包括slot, ref, stat未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】icClass, style, clas【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】s, props, attrs, tra转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。nsition, directives等【本文首发于唐霜的博客】原创内容,盗版必究。信息。

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

VNodeDirective

VNodeData中的directive【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.nets属性的详细信息,包括name, val【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】ue, oldValue, arg, m【原创内容,转载请注明出处】【转载请注明来源】odifiers等。

【关注微信公众号:wwwtangshua【作者:唐霜】【作者:唐霜】ngnet】【转载请注明来源】

如何生成VNode?

前面我们提到过render函数的参数cr【版权所有,侵权必究】【未经授权禁止转载】eateElement,其实你再回头去看本文版权归作者所有,未经授权不得转载。【转载请注明来源】createElement这个函数,就大未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。概清楚是怎么回事,它实际上就生成了VNo未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。de(一个对象)。但是如果我们传入了te转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。mplate而没有传入render函数呢【本文首发于唐霜的博客】【本文首发于唐霜的博客】?vue会通过一个ast语法优化,对我们原创内容,盗版必究。【未经授权禁止转载】传入的template经过HTML解析器转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。之后的对象转化为给createEleme【原创不易,请尊重版权】【未经授权禁止转载】nt的参数。

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【未经授权禁止转载】

总之,你会发现,vue的render函数本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。实际上是要生成VNode,它到真实的DO【本文受版权保护】本文版权归作者所有,未经授权不得转载。M,还有一个过程。

【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。ang.net未经授权,禁止复制转载。【未经授权禁止转载】【本文首发于唐霜的博客】

VNode patch生成DOM

Virtual DOM之所以快,是因为在【原创不易,请尊重版权】【转载请注明来源】生成真实的DOM之前,通过内部的一个简单【版权所有】唐霜 www.tangshuang.net【本文受版权保护】的多的对象的对比,判断是否有变化,具体的【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net变化在哪里,这个对比的过程比直接操作DO原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。M要快非常多。

【本文受版权保护】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。【本文首发于唐霜的博客】

vue还有一个特点,VNode还具有队列本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。,当VNode发生变化时,会放在一个队列本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。里,并不会马上去更新DOM,而是在遍历完原创内容,盗版必究。【原创不易,请尊重版权】整个队列之后才更新DOM。所以性能上又好【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】了一些。

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

vue里对比新旧DOM的方法是patch【未经授权禁止转载】转载请注明出处:www.tangshuang.netVnode这个方法,当它决定是否要更新D本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。OM之前,会比较DOM节点对应的新旧VN【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。ode,只有不同时,才进行更新,这个对比【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。是在VNode内部,因此比对比DOM快很【本文受版权保护】转载请注明出处:www.tangshuang.net多。patchValue这个方法是vue著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。里面非常出色,可以说是vue里面使得Vi【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】rtual DOM可行的核心部分。它的实【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。现比较复杂,本书也说不清楚,你要是有兴趣【关注微信公众号:wwwtangshuangnet】【本文受版权保护】,可以阅读源码,细心研究。

【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】et 获取更多精彩内容】本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。

vue生成真正的DOM靠createEl本文作者:唐霜,转载请注明出处。【未经授权禁止转载】m方法,它把一个VNode真正转化为真实著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net的DOM。

转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。ng.net【未经授权禁止转载】【未经授权禁止转载】【本文首发于唐霜的博客】

响应式原理

我们已经涵盖了大部分的基础知识 R【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net11; 现在是时候深入底层原理了!Vue著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】 最显著的特性之一便是不太引人注意的响应【作者:唐霜】【未经授权禁止转载】式系统(reactivity syste转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】m)。模型层(model)只是普通 Ja【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。vaScript 对象,修改它则更新视图【版权所有,侵权必究】【原创不易,请尊重版权】(view)。这会让状态管理变得非常简单【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。且直观,不过理解它的工作原理以避免一些常【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】见的问题也是很重要的。在本章中,我们将开【本文受版权保护】原创内容,盗版必究。始深入挖掘 Vue 响应式系统的底层细节【转载请注明来源】【版权所有,侵权必究】

原创内容,盗版必究。【原创不易,请尊重版权】

如何追踪变化

把一个普通 JavaScript 对象传【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】给 Vue 实例的 data 选项,Vu本文作者:唐霜,转载请注明出处。原创内容,盗版必究。e 将遍历此对象所有的属性,并使用 Object.definePropert著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】y 把这些属性全部转为 getter/se本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】tter。Object.definePr【原创不易,请尊重版权】未经授权,禁止复制转载。operty 是仅 ES5 支持,且无法转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。 shim 的特性,这也就是为什么 Vu原创内容,盗版必究。【转载请注明来源】e 不支持 IE8 以及更低版本浏览器的本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。原因。

本文版权归作者所有,未经授权不得转载。【转载请注明来源】

用户看不到 getter/setter,【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。但是在内部它们让 Vue 追踪依赖,在属【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。性被访问和修改时通知变化。这里需要注意的【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net问题是浏览器控制台在打印数据对象时 ge【本文受版权保护】【原创内容,转载请注明出处】tter/setter 的格式化并不同,未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net所以你可能需要安装 vue-devtools 来获取更加友好的检查接口。

【本文受版权保护】【关注微信公众号:wwwtangshua【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。ngnet】【作者:唐霜】

每个组件实例都有相应的 watcher 未经授权,禁止复制转载。【未经授权禁止转载】实例对象,它会在组件渲染的过程中把属性记【版权所有,侵权必究】原创内容,盗版必究。录为依赖,之后当依赖项的 setter 转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net被调用时,会通知 watcher 重新计【转载请注明来源】【版权所有】唐霜 www.tangshuang.net算,从而致使它关联的组件得以更新。
【原创内容,转载请注明出处】

【原创内容,转载请注明出处】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】

变化检测问题

受现代 JavaScript 的限制(以【版权所有】唐霜 www.tangshuang.net【转载请注明来源】及废弃 Object.observe),【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。Vue 不能检测到对象属性的添加或删除。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】由于 Vue 会在初始化实例时对属性执行【未经授权禁止转载】【版权所有,侵权必究】 getter/setter 转化过程,【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。所以属性必须在 data 对象上存在才能【原创内容,转载请注明出处】【本文受版权保护】让 Vue 转换它,这样才能让它是响应的【转载请注明来源】著作权归作者所有,禁止商业用途转载。。例如:

转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ng.net未经授权,禁止复制转载。未经授权,禁止复制转载。【作者:唐霜】
var vm = new Vue({
  data:{ 
   a:1
  }
})
// `vm.a` 是响应的vm.b = 2
// `vm.b` 是非响应的

Vue 不允许在已经创建的实例上动态添加【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】新的根级响应式属性(root-level本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net reactive property)。原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】然而它可以使用 Vue.set(obje本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。ct, key, value) 方法将响原创内容,盗版必究。未经授权,禁止复制转载。应属性添加到嵌套的对象上:

【本文首发于唐霜的博客】【作者:唐霜】【本文受版权保护】
Vue.set(vm.someObject, 'b', 2)

您还可以使用 vm.$set 实例方法,本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。这也是全局 Vue.set 方法的别名:

【转载请注明来源】本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。et 获取更多精彩内容】【原创不易,请尊重版权】
this.$set(this.someObject,'b',2)

有时你想向已有对象上添加一些属性,例如使著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。用 Object.assign() 或 本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】_.extend() 方法来添加属性。但【转载请注明来源】【原创不易,请尊重版权】是,添加到对象上的新属性不会触发更新。在【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net这种情况下可以创建一个新的对象,让它包含【未经授权禁止转载】【本文受版权保护】原对象的属性和新的属性:

【转载请注明来源】【原创不易,请尊重版权】
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

声明响应式属性

由于 Vue 不允许动态添加根级响应式属【作者:唐霜】【版权所有,侵权必究】性,所以你必须在初始化实例前声明根级响应【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。式属性,哪怕只是一个空值:

原创内容,盗版必究。【原创内容,转载请注明出处】原创内容,盗版必究。原创内容,盗版必究。
var vm = new Vue({
  data: {
    // 声明 message 为一个空值字符串
    message: ''
  },
  template: '<div>{{ message }}</div>'
})
// 之后设置 `message` 
vm.message = 'Hello!'

如果你在 data 选项中未声明 mes转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netsage,Vue 将警告你渲染函数在试图【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。访问的属性不存在。

著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【作者:唐霜】原创内容,盗版必究。

这样的限制在背后是有其技术原因的,它消除本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】了在依赖项跟踪系统中的一类边界情况,也使【关注微信公众号:wwwtangshuangnet】【本文受版权保护】 Vue 实例在类型检查系统的帮助下运行原创内容,盗版必究。【作者:唐霜】的更高效。而且在代码可维护性方面也有一点本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。重要的考虑:data 对象就像组件状态的【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。概要,提前声明所有的响应式属性,可以让组【原创不易,请尊重版权】【转载请注明来源】件代码在以后重新阅读或其他开发人员阅读时【原创不易,请尊重版权】【本文首发于唐霜的博客】更易于被理解。

【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。ngnet】著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】

异步更新队列

可能你还没有注意到,Vue 异步执行 DOM 更新。只要观察到数据变化,【本文受版权保护】本文版权归作者所有,未经授权不得转载。Vue 将开启一个队列,并缓冲在同一事件【关注微信公众号:wwwtangshuangnet】【本文受版权保护】循环中发生的所有数据改变。如果同一个 w原创内容,盗版必究。【原创内容,转载请注明出处】atcher 被多次触发,只会一次推入到转载请注明出处:www.tangshuang.net【未经授权禁止转载】队列中。这种在缓冲时去除重复数据对于避免【转载请注明来源】未经授权,禁止复制转载。不必要的计算和 DOM 操作上非常重要。【本文首发于唐霜的博客】【本文受版权保护】然后,在下一个的事件循环“tick”中,【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。Vue 刷新队列并执行实际(已去重的)工【原创内容,转载请注明出处】未经授权,禁止复制转载。作。Vue 在内部尝试对异步队列使用原生转载请注明出处:www.tangshuang.net【转载请注明来源】的 Promise.then 和 Mut【版权所有,侵权必究】转载请注明出处:www.tangshuang.netationObserver,如果执行环境未经授权,禁止复制转载。【原创不易,请尊重版权】不支持,会采用 setTimeout(f转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netn, 0) 代替。

【访问 www.tangshuang.n原创内容,盗版必究。【原创内容,转载请注明出处】et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】

例如,当你设置 vm.someData 【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。= ‘new value&#【版权所有】唐霜 www.tangshuang.net【转载请注明来源】8217; ,该组件不会立即重新渲染。当原创内容,盗版必究。【原创内容,转载请注明出处】刷新队列时,组件会在事件循环队列清空时的本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】下一个“tick”更新。多数情况我们不需【本文首发于唐霜的博客】【作者:唐霜】要关心这个过程,但是如果你想在 DOM 【本文受版权保护】转载请注明出处:www.tangshuang.net状态更新后做点什么,这就可能会有些棘手。【原创不易,请尊重版权】【原创不易,请尊重版权】虽然 Vue.js 通常鼓励开发人员沿着【原创不易,请尊重版权】未经授权,禁止复制转载。“数据驱动”的方式思考,避免直接接触 D【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】OM,但是有时我们确实要这么做。为了在数【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net据变化之后等待 Vue 完成更新 DOM【版权所有,侵权必究】【原创不易,请尊重版权】 ,可以在数据变化之后立即使用 Vue.本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netnextTick(callback) 。【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。这样回调函数在 DOM 更新完成后就会调【版权所有,侵权必究】原创内容,盗版必究。用。例如:

【转载请注明来源】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ang.net【转载请注明来源】未经授权,禁止复制转载。
<div id="example">{{message}}</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})

在组件内使用 vm.$nextTick(本文作者:唐霜,转载请注明出处。【转载请注明来源】) 实例方法特别方便,因为它不需要全局 未经授权,禁止复制转载。【版权所有,侵权必究】Vue ,并且回调函数中的 this 将【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】自动绑定到当前的 Vue 实例上:

【版权所有,侵权必究】【版权所有,侵权必究】
Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = 'updated'
      console.log(this.$el.textContent) // => '没有更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '更新完成'
      })
    }
  }
})

路由:vue-router

当我们开始打算用vue来写app的时候,本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】一定会考虑路由的问题。vue官方出品了v【转载请注明来源】【版权所有,侵权必究】ue-router,它可以实现改变url转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。来切换视图,它有完整的中文文档,而且内容【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。不多,很快就可以看完,所以本书就不完完全原创内容,盗版必究。【作者:唐霜】全的copy过来了,你可以进入官方的中文文档阅读。
未经授权,禁止复制转载。 本章主要是想让你能够使用vue-rou【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.netter进行开发,对于深层的机制就不予阐述【关注微信公众号:wwwtangshuangnet】【转载请注明来源】了。

本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ang.net原创内容,盗版必究。未经授权,禁止复制转载。

安装和代码结构

和VueResource的安装一样,vu转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】e-router的安装也非常简单:

著作权归作者所有,禁止商业用途转载。【作者:唐霜】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ang.net
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

接下来,打算使用它来进行路由了:

【未经授权禁止转载】【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】ng.net
// 1. 定义(路由)组件。// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定义路由// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]
// 3. 创建 router 实例,然后传 `routes` 配置// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes, // (缩写)相当于 routes: routes
})
// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  el: '#app',
  template: '<router-view></router-view>',  router,
})
// 现在,应用已经启动了!

我们来观察一下上面的代码。只需要将Vue【作者:唐霜】原创内容,盗版必究。Router的一个实例传给Vue实例。而著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。实例化VueRouter的时候,传入一个本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】routes,routes是一个数组,数著作权归作者所有,禁止商业用途转载。【作者:唐霜】组的每个元素是一个组件(构造器参数)。

【转载请注明来源】【本文受版权保护】【本文首发于唐霜的博客】

其实,我们也可以传一个组件构造器进去,路【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】由实例创建时,会自动创建这个组件的实例。

【本文受版权保护】【版权所有,侵权必究】【原创不易,请尊重版权】

当这样的代码运行之后。当你访问/foo的【未经授权禁止转载】原创内容,盗版必究。时候,就会在<router-vie原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。w></router-vie著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。w>这个地方替换为Foo这个组件的【作者:唐霜】【转载请注明来源】渲染结果。当你切换url为/bar的时候【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net,渲染的就是Bar这个组件的渲染结果。也本文版权归作者所有,未经授权不得转载。【作者:唐霜】就是视图随着url改变而改变。

【版权所有,侵权必究】【版权所有,侵权必究】

实例化参数配置

上面的new VueRouter的时候,本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net需要传入参数,对路由实例进行配置,那么有【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。哪些配置项可选呢?

【未经授权禁止转载】【原创内容,转载请注明出处】转载请注明出处:www.tangshua【作者:唐霜】未经授权,禁止复制转载。ng.net未经授权,禁止复制转载。

routes

declare type RouteConfig = {
  path: string;
  component?: Component;
  name?: string; // for named routes (命名路由)
  components?: { [name: string]: Component }; // for named views (命名视图组件)
  redirect?: string | Location | Function;
  alias?: string | Array<string>;
  children?: Array<RouteConfig>; // for nested routes
  beforeEnter?: (to: Route, from: Route, next: Function) => void;
  meta?: any;
}

上面的红色字段可能是我们使用的最多的字段著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。

【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【原创不易,请尊重版权】ngnet】【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netang.net【本文受版权保护】

mode

base

linkActiveClass

scrollBehavior

(
  to: Route,
  from: Route,
  savedPosition?: { x: number, y: number }
) => { x: number, y: number } | { selector: string } | ?{}

router-view

<router-view>&未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。lt;/router-view>就【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。是用来显示VueRouter实例的渲染位著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net置。<router-view>本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】; 组件是一个 functional 组【转载请注明来源】原创内容,盗版必究。件,渲染路径匹配到的视图组件。<r【原创内容,转载请注明出处】【未经授权禁止转载】outer-view> 渲染的组件本文版权归作者所有,未经授权不得转载。【转载请注明来源】还可以内嵌自己的 <router-本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】view>,根据嵌套路径,渲染嵌套【作者:唐霜】【版权所有】唐霜 www.tangshuang.net组件。
转载请注明出处:www.tangshua【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。ng.net 有时候想同时(同级)展示多个视图,而不本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。是嵌套展示,例如创建一个布局,有 sid【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。ebar(侧导航) 和 main(主内容【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。) 两个视图,这个时候命名视图就派上用场原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】了。你可以在界面中拥有多个单独命名的视图【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net,而不是只有一个单独的出口。如果 rou【作者:唐霜】本文作者:唐霜,转载请注明出处。ter-view 没有设置名字,那么默认本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net为 default。

【关注微信公众号:wwwtangshua【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】ngnet】【作者:唐霜】【原创内容,转载请注明出处】【访问 www.tangshuang.n【未经授权禁止转载】【作者:唐霜】et 获取更多精彩内容】
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

一个视图使用一个组件渲染,因此对于同个路【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】由,多个视图就需要多个组件。确保正确使用转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】 components 配置(带上 s)【转载请注明来源】本文作者:唐霜,转载请注明出处。

转载请注明出处:www.tangshua【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.netng.net未经授权,禁止复制转载。未经授权,禁止复制转载。【原创内容,转载请注明出处】
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

这个时候在实例化VueRouter的时候【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net,就不是传component了,而是传给【原创不易,请尊重版权】转载请注明出处:www.tangshuang.netcomponents这个参数了。在com【原创内容,转载请注明出处】【原创内容,转载请注明出处】ponents里面,就要使用键值对的形式原创内容,盗版必究。【本文受版权保护】,传入不同的组件构造器给不同的name。

【原创内容,转载请注明出处】【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netngnet】【版权所有,侵权必究】

Router 实例

属性

router.app

【本文受版权保护】著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】【版权所有,侵权必究】

router.mode

【版权所有,侵权必究】【版权所有,侵权必究】转载请注明出处:www.tangshua【原创不易,请尊重版权】【作者:唐霜】ng.net【本文首发于唐霜的博客】

router.currentRoute

【原创内容,转载请注明出处】【未经授权禁止转载】【版权所有】唐霜 www.tangshu【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.netang.net

方法

router.beforeEach(gu【本文受版权保护】【版权所有,侵权必究】ard)
本文作者:唐霜,转载请注明出处。 router.afterEach(ho本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】ok)

【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu【版权所有,侵权必究】未经授权,禁止复制转载。ang.net

router.push(location【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】)
【版权所有,侵权必究】 router.replace(loca【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】tion)
原创内容,盗版必究。 router.go(n)
【原创内容,转载请注明出处】 router.back()
【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】ngnet】 router.forward()

著作权归作者所有,禁止商业用途转载。【转载请注明来源】【转载请注明来源】【原创不易,请尊重版权】

router.getMatchedCom【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】ponents(location?)

【原创内容,转载请注明出处】未经授权,禁止复制转载。

router.resolve(locat【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】ion, current?, appen未经授权,禁止复制转载。【本文首发于唐霜的博客】d?)

原创内容,盗版必究。【本文受版权保护】【未经授权禁止转载】
{
  location: Location;
  route: Route;
  href: string;
}

router.addRoutes(rou【关注微信公众号:wwwtangshuangnet】【本文受版权保护】tes)

【作者:唐霜】【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netngnet】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。

router.onReady(callb本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netack)

转载请注明出处:www.tangshua【原创内容,转载请注明出处】未经授权,禁止复制转载。ng.net【访问 www.tangshuang.n未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】

动态路由匹配

参数匹配

我们经常需要把某种模式匹配到的所有路由,转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net全都映射到同个组件。例如,我们有一个 U【转载请注明来源】【未经授权禁止转载】ser 组件,对于所有 ID 各不相同的【版权所有】唐霜 www.tangshuang.net【作者:唐霜】用户,都要使用这个组件来渲染。那么,我们【关注微信公众号:wwwtangshuangnet】【本文受版权保护】可以在 vue-router 的路由路径转载请注明出处:www.tangshuang.net【未经授权禁止转载】中使用『动态路径参数』(dynamic 【本文受版权保护】【关注微信公众号:wwwtangshuangnet】segment)来达到这个效果:

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。
const User = {
  template: '<div>User</div>'
}
const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})

现在呢,像 /user/foo 和 /u转载请注明出处:www.tangshuang.net原创内容,盗版必究。ser/bar 都将映射到相同的路由。

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【版权所有】唐霜 www.tangshu【原创不易,请尊重版权】转载请注明出处:www.tangshuang.netang.net

一个『路径参数』使用冒号 : 标记。当匹【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。配到一个路由时,参数值会被设置到 thi【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】s.$route.params,可以在每【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net个组件内使用。于是,我们可以更新 Use本文作者:唐霜,转载请注明出处。原创内容,盗版必究。r 的模板,输出当前用户的 ID:

【本文首发于唐霜的博客】【原创内容,转载请注明出处】【原创内容,转载请注明出处】原创内容,盗版必究。
const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

你可以在一个路由中设置多段『路径参数』,【本文受版权保护】【本文首发于唐霜的博客】对应的值都会设置到 $route.par原创内容,盗版必究。【原创内容,转载请注明出处】ams 中。例如:

【版权所有,侵权必究】【访问 www.tangshuang.n【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】et 获取更多精彩内容】转载请注明出处:www.tangshua【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】ng.net【作者:唐霜】
模式 匹配路径 $route.params
/user/:username /user/evan { username: ‘evan’ }
/user/:username/post/:post_id /user/evan/post/123 { username: ‘evan’, post_id: 123 }

除了 $route.params 外,$【本文受版权保护】未经授权,禁止复制转载。route 对象还提供了其它有用的信息,著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。例如,$route.query(如果 U转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。RL 中有查询参数)、$route.ha【版权所有】唐霜 www.tangshuang.net【本文受版权保护】sh 等等。你可以查看 API 文档 的详细说明。

【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】et 获取更多精彩内容】未经授权,禁止复制转载。【版权所有,侵权必究】【访问 www.tangshuang.n原创内容,盗版必究。【原创内容,转载请注明出处】et 获取更多精彩内容】

响应路由参数的变化

提醒一下,当使用路由参数时,例如从 /u【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】ser/foo 导航到 user/bar【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】,原来的组件实例会被复用。因为两个路由都【原创不易,请尊重版权】原创内容,盗版必究。渲染同个组件,比起销毁再创建,复用则显得原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】更加高效。不过,这也意味着组件的生命周期转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net钩子不会再被调用。

【关注微信公众号:wwwtangshua【转载请注明来源】【版权所有,侵权必究】ngnet】【原创不易,请尊重版权】未经授权,禁止复制转载。

复用组件时,想对路由参数的变化作出响应的【未经授权禁止转载】【作者:唐霜】话,你可以简单地 watch(监测变化)【原创内容,转载请注明出处】【原创不易,请尊重版权】 $route 对象:

原创内容,盗版必究。【转载请注明来源】【版权所有,侵权必究】
const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 对路由变化作出响应...
    }
  }
}

高级匹配模式

vue-router 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹转载请注明出处:www.tangshuang.net原创内容,盗版必究。配模式,例如:可选的动态路径参数、匹配零【原创不易,请尊重版权】【本文受版权保护】个或多个、一个或多个,甚至是自定义正则匹【原创不易,请尊重版权】【本文首发于唐霜的博客】配。查看它的 文档 学习高阶的路径匹配,还有 这个例子 展示 vue-router 怎么使用这类【本文受版权保护】【本文首发于唐霜的博客】匹配。

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

匹配优先级

有时候,同一个路径可以匹配多个路由,此时未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】,匹配的优先级就按照路由的定义顺序:谁先转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net定义的,谁的优先级就最高。

【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ang.net【版权所有】唐霜 www.tangshu【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。ang.net

嵌套路由

实际生活中的应用界面,通常由多层嵌套的组【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。件组合而成。同样地,URL 中各段动态路【版权所有,侵权必究】原创内容,盗版必究。径也按某种结构对应嵌套的各层组件。

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。

借助 vue-router,使用嵌套路由【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】配置,就可以很简单地表达这种关系。

【未经授权禁止转载】【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。

接着上节创建的 app:

【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。
<div id="app">
  <router-view></router-view>
</div>
const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

这里的 <router-view&【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。gt; 是最顶层的出口,渲染最高级路由匹【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net配到的组件。同样地,一个被渲染组件同样可著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】以包含自己的嵌套 <router-本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。view>。例如,在 User 组【转载请注明来源】【作者:唐霜】件的模板添加一个 <router-【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。view>:

未经授权,禁止复制转载。【原创不易,请尊重版权】【未经授权禁止转载】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】ang.net
const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}

要在嵌套的出口中渲染组件,需要在 Vue【未经授权禁止转载】【转载请注明来源】Router 的参数中使用 childr【本文首发于唐霜的博客】【原创不易,请尊重版权】en 配置:

未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。原创内容,盗版必究。原创内容,盗版必究。
const router = new VueRouter({
  routes: [
    { 
      path: '/user/:id', 
      component: User,
      children: [
      {
        // 当 /user/:id/profile 匹配成功,
        // UserProfile 会被渲染在 User 的 <router-view> 中
        path: 'profile',
        component: UserProfile
      },
      {
        // 当 /user/:id/posts 匹配成功
        // UserPosts 会被渲染在 User 的 <router-view> 中
        path: 'posts',
        component: UserPosts
      }]
    }
  ]
})

要注意,以 / 开头的嵌套路径会被当作根著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net路径。 这让你充分的使用嵌套组件而无须设本文作者:唐霜,转载请注明出处。原创内容,盗版必究。置嵌套的路径。

【版权所有】唐霜 www.tangshu【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。ang.net【版权所有】唐霜 www.tangshu【转载请注明来源】原创内容,盗版必究。ang.net【版权所有,侵权必究】【转载请注明来源】

你会发现,children 配置就是像 本文版权归作者所有,未经授权不得转载。【作者:唐霜】routes 配置一样的路由配置数组,所【转载请注明来源】转载请注明出处:www.tangshuang.net以呢,你可以嵌套多层路由。

【转载请注明来源】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【本文受版权保护】ang.net

此时,基于上面的配置,当你访问 /use【作者:唐霜】本文版权归作者所有,未经授权不得转载。r/foo 时,User 的出口是不会渲未经授权,禁止复制转载。【原创不易,请尊重版权】染任何东西,这是因为没有匹配到合适的子路未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。由。如果你想要渲染点什么,可以提供一个 转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】空的 子路由:

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu【作者:唐霜】未经授权,禁止复制转载。ang.net
const router = new VueRouter({
  routes: [{
    path: '/user/:id', component: User,
    children: [
      // 当 /user/:id 匹配成功,
      // UserHome 会被渲染在 User 的 <router-view> 中
      { path: '', component: UserHome },
      // ...其他子路由
    ]
  }]
})

router-link

<router-link> 【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】组件支持用户在具有路由功能的应用中(点击【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】)导航。 通过 to 属性指定目标地址,【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。默认渲染成带有正确链接的 <a&g【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。t; 标签,可以通过配置 tag 属性生转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。成别的标签.。另外,当目标路由成功激活时【转载请注明来源】【版权所有】唐霜 www.tangshuang.net,链接元素自动设置一个表示激活的 CSS【本文首发于唐霜的博客】【本文受版权保护】 类名。

【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netngnet】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ng.net

<router-link> 转载请注明出处:www.tangshuang.net【未经授权禁止转载】比起写死的 <a href=【版权所有,侵权必究】【未经授权禁止转载】221;…”&g【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】t; 会好一些,理由如下:

【作者:唐霜】未经授权,禁止复制转载。

Props

to

表示目标路由的链接。当被点击后,内部会立【原创不易,请尊重版权】【作者:唐霜】刻把 to 的值传到 router.pu著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netsh(),所以这个值可以是一个字符串或者转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】是描述目标位置的对象。

本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】【版权所有,侵权必究】
  <!-- 字符串 -->
  <router-link to="home">Home</router-link>
  <!-- 渲染结果 -->
  <a href="home">Home</a>
  <!-- 使用 v-bind 的 JS 表达式 -->
  <router-link v-bind:to="'home'">Home</router-link>
  <!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
  <router-link :to="'home'">Home</router-link>
  <!-- 同上 -->
  <router-link :to="{ path: 'home' }">Home</router-link>
  <!-- 命名的路由 -->
  <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
  <!-- 带查询参数,下面的结果为 /register?plan=private -->
  <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>

replace

设置 replace 属性的话,当点击时未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】,会调用 router.replace(未经授权,禁止复制转载。未经授权,禁止复制转载。) 而不是 router.push(),【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。于是导航后不会留下 history 记录著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】

本文版权归作者所有,未经授权不得转载。【本文受版权保护】【版权所有】唐霜 www.tangshu【转载请注明来源】本文版权归作者所有,未经授权不得转载。ang.net
  <router-link :to="{ path: '/abc'}" replace></router-link>

append

设置 append 属性后,则在当前(相【作者:唐霜】原创内容,盗版必究。对)路径前添加基路径。例如,我们从 /a【未经授权禁止转载】转载请注明出处:www.tangshuang.net 导航到一个相对路径 b,如果没有配置 转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。append,则路径为 /b,如果配了,本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。则为 /a/b

【作者:唐霜】著作权归作者所有,禁止商业用途转载。【作者:唐霜】【原创内容,转载请注明出处】
  <router-link :to="{ path: 'relative/path'}" append></router-link>

tag

有时候想要 <router-lin本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】k> 渲染成某种标签,例如 <转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。;li>。 于是我们使用 tag 转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】prop 类指定何种标签,同样它还是会监【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。听点击,触发导航。

【版权所有,侵权必究】转载请注明出处:www.tangshua【作者:唐霜】著作权归作者所有,禁止商业用途转载。ng.net转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【作者:唐霜】ng.net
  <router-link to="/foo" tag="li">foo</router-link>
  <!-- 渲染结果 -->
  <li>foo</li>

active-class

设置 链接激活时使用的 CSS 类名。默【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。认值可以通过路由的构造选项 linkAc【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.nettiveClass 来全局配置。

【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】ang.net著作权归作者所有,禁止商业用途转载。

exact

“是否激活” 默本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】认类名的依据是 inclusive ma【转载请注明来源】【转载请注明来源】tch (全包含匹配)。 举个例子,如果原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】当前的路径是 /a 开头的,那么 <【本文首发于唐霜的博客】【本文受版权保护】;router-link to=R著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net21;/a”> 也会被【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】设置 CSS 类名。

【未经授权禁止转载】【本文首发于唐霜的博客】【转载请注明来源】

按照这个规则,<router-li【转载请注明来源】【关注微信公众号:wwwtangshuangnet】nk to=”/”本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net;> 将会点亮各个路由!想要链接使【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】用 “exact 匹配模式&未经授权,禁止复制转载。【原创内容,转载请注明出处】#8221;,则使用 exact 属性:

未经授权,禁止复制转载。【未经授权禁止转载】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】ng.net
  <!-- 这个链接只会在地址为 / 的时候被激活 -->
  <router-link to="/" exact>

events

2.1.0+才有。声明可以用来触发导航的【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net事件。可以是一个字符串或是一个包含字符串【转载请注明来源】原创内容,盗版必究。的数组。

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。

将”激活时的CSS类名”应用在外层元素

有时候我们要让 “激活时的C本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】SS类名” 应用在外层元素,【本文首发于唐霜的博客】【本文受版权保护】而不是 <a> 标签本身,那【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net么可以用 <router-link【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】> 渲染外层元素,包裹着内层的原生【未经授权禁止转载】【转载请注明来源】 <a> 标签:

【版权所有】唐霜 www.tangshu【作者:唐霜】本文版权归作者所有,未经授权不得转载。ang.net【本文首发于唐霜的博客】
<router-link tag="li" to="/foo">
  <a>/foo</a>
</router-link>

在这种情况下,<a> 将作为【作者:唐霜】本文版权归作者所有,未经授权不得转载。真实的链接(它会获得正确的 href 的【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】),而 “激活时的CSS类名转载请注明出处:www.tangshuang.net【未经授权禁止转载】” 则设置到外层的 <【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。li>。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

用代码切换URL

除了使用 <router-link未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。> 创建 a 标签来定义导航链接,【未经授权禁止转载】原创内容,盗版必究。我们还可以借助 router 的实例方法本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】,通过编写代码来实现。

【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netang.net【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netang.net

router.push(location)

想要导航到不同的 URL,则使用 rou原创内容,盗版必究。【版权所有,侵权必究】ter.push 方法。这个方法会向 h未经授权,禁止复制转载。转载请注明出处:www.tangshuang.netistory 栈添加一个新的记录,所以,未经授权,禁止复制转载。【作者:唐霜】当用户点击浏览器后退按钮时,则回到之前的【本文受版权保护】本文作者:唐霜,转载请注明出处。 URL。

【本文受版权保护】【作者:唐霜】

当你点击 <router-link本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。> 时,这个方法会在内部调用,所以【本文首发于唐霜的博客】【转载请注明来源】说,点击 <router-link本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。 :to=”…&【作者:唐霜】原创内容,盗版必究。#8221;> 等同于调用 rou【转载请注明来源】本文作者:唐霜,转载请注明出处。ter.push(…)。

本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】ngnet】【版权所有,侵权必究】原创内容,盗版必究。
声明式 编程式
<router-link :to=”…”> router.push(…)

该方法的参数可以是一个字符串路径,或者一本文作者:唐霜,转载请注明出处。【本文受版权保护】个描述地址的对象。例如:

转载请注明出处:www.tangshua【作者:唐霜】【本文首发于唐霜的博客】ng.net本文版权归作者所有,未经授权不得转载。
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

router.replace(location)

跟 router.push 很像,唯一的【本文首发于唐霜的博客】【作者:唐霜】不同就是,它不会向 history 添加【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】新记录,而是跟它的方法名一样 —— 替换原创内容,盗版必究。未经授权,禁止复制转载。掉当前的 history 记录。

转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【作者:唐霜】ng.net【原创不易,请尊重版权】【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。
声明式 编程式
<router-link :to=”…” replace> router.replace(…)

router.go(n)

这个方法的参数是一个整数,意思是在 hi【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】story 记录中向前或者后退多少步,类【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】似 window.history.go(【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】n)。
【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】 例子

【未经授权禁止转载】【原创不易,请尊重版权】
// 在浏览器记录中前进一步,等同于 
history.forward()
router.go(1)
// 后退一步记录,等同于 
history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

操作 History

你也许注意到 router.push、 【转载请注明来源】【本文首发于唐霜的博客】router.replace 和 rou【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】ter.go 跟 window.history.pushS本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。tate、 window.history【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】.replaceState 和 wind本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】ow.history.go好像, 实际上它们确实是效仿 windo本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netw.history API 的。

【本文受版权保护】【本文首发于唐霜的博客】

因此,如果你已经熟悉 Browser History APIs,那么在 vue-router 中操作 本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。history 就是超级简单的。

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【本文受版权保护】ng.net【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。ngnet】

还有值得提及的,vue-router 的【版权所有】唐霜 www.tangshuang.net【转载请注明来源】导航方法 (push、 replace、【作者:唐霜】【作者:唐霜】 go) 在各类路由模式(history本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net、 hash 和 abstract)下表【作者:唐霜】【版权所有,侵权必究】现一致。

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。未经授权,禁止复制转载。

重定向 和 别名

重定向

重定向也是通过 routes 配置来完成本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】,下面例子是从 /a 重定向到 /b:

未经授权,禁止复制转载。未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})

重定向的目标也可以是一个命名的路由:

【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

甚至是一个方法,动态返回重定向目标:

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。
const router = new VueRouter({
  routes: [
    { 
      path: '/a', 
      redirect: to => {
        // 方法接收 目标路由 作为参数
        // return 重定向的 字符串路径/路径对象
      }
    }
  ]
})

别名

『重定向』的意思是,当用户访问 /a时,【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。URL 将会被替换成 /b,然后匹配路由【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。为 /b,那么『别名』又是什么呢?

【访问 www.tangshuang.n【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】未经授权,禁止复制转载。

/a 的别名是 /b,意味着,当用户访问【未经授权禁止转载】【转载请注明来源】 /b 时,URL 会保持为 /b,但是未经授权,禁止复制转载。【版权所有,侵权必究】路由匹配则为 /a,就像用户访问 /a 【原创内容,转载请注明出处】【原创不易,请尊重版权】一样。

【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】ngnet】【未经授权禁止转载】原创内容,盗版必究。【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】

上面对应的路由配置为:

【未经授权禁止转载】【版权所有,侵权必究】
const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

『别名』的功能让你可以自由地将 UI 结本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。构映射到任意的 URL,而不是受限于配置原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。的嵌套路由结构。

【未经授权禁止转载】【本文首发于唐霜的博客】

$router和$route

在组件内部可以通过this.$route【原创不易,请尊重版权】原创内容,盗版必究。r和this.$route获取路由信息。

【未经授权禁止转载】转载请注明出处:www.tangshua【转载请注明来源】【本文首发于唐霜的博客】ng.net【原创不易,请尊重版权】【版权所有,侵权必究】

this.$router

router这个实例化对象的引用。所以,【本文受版权保护】未经授权,禁止复制转载。上面说的Router实例里面的属性和方法【原创不易,请尊重版权】原创内容,盗版必究。,this.$router都有,于是就可【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net以用它来操作路由了,比如跳转路由之类的。

【作者:唐霜】【转载请注明来源】原创内容,盗版必究。【本文首发于唐霜的博客】

this.$route

当前url对应的路由信息,主要包括下面信【原创不易,请尊重版权】【未经授权禁止转载】息:

【作者:唐霜】本文作者:唐霜,转载请注明出处。

$route.path

类型: string
【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。ngnet】 字符串,对应当前路由的路径,总是解析为【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】绝对路径,如 “/foo/b【作者:唐霜】本文作者:唐霜,转载请注明出处。ar”。

本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】

$route.params

类型: Object
本文作者:唐霜,转载请注明出处。 一个 key/value 对象,包含了【版权所有,侵权必究】【原创不易,请尊重版权】 动态片段 和 全匹配片段,如果没有路由【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】参数,就是一个空对象。

【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】ngnet】本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】

$route.query

类型: Object
原创内容,盗版必究。 一个 key/value 对象,表示 【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】URL 查询参数。例如,对于路径 /fo【版权所有,侵权必究】【未经授权禁止转载】o?user=1,则有 $route.q【转载请注明来源】本文版权归作者所有,未经授权不得转载。uery.user == 1,如果没有查未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。询参数,则是个空对象。

【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。ang.net【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ngnet】【作者:唐霜】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netng.net

$route.hash

类型: string
【访问 www.tangshuang.n【本文首发于唐霜的博客】【原创不易,请尊重版权】et 获取更多精彩内容】 当前路由的 hash 值 (带 #) 【原创内容,转载请注明出处】【本文首发于唐霜的博客】,如果没有 hash 值,则为空字符串。

【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。ang.net转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。ng.net转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。ng.net原创内容,盗版必究。

$route.fullPath

类型: string
【本文首发于唐霜的博客】 完成解析后的 URL,包含查询参数和 【版权所有】唐霜 www.tangshuang.net【本文受版权保护】hash 的完整路径。

【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。原创内容,盗版必究。et 获取更多精彩内容】【未经授权禁止转载】

$route.matched

类型: Array<RouteRe未经授权,禁止复制转载。【原创不易,请尊重版权】cord>
【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netngnet】 一个数组,包含当前路由的所有嵌套路径片【转载请注明来源】著作权归作者所有,禁止商业用途转载。段的 路由记录 。路由记录就是 rout【作者:唐霜】【关注微信公众号:wwwtangshuangnet】es 配置数组中的对象副本(还有在 ch转载请注明出处:www.tangshuang.net【版权所有,侵权必究】ildren 数组)。

未经授权,禁止复制转载。【原创不易,请尊重版权】【版权所有,侵权必究】
const router = new VueRouter({
  routes: [
    // 下面的对象就是 route record
    { path: '/foo', component: Foo,
      children: [
        // 这也是个 route record
        { path: 'bar', component: Bar }
      ]
    }
  ]
})

当 URL 为 /foo/bar,$ro未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】ute.matched 将会是一个包含从【未经授权禁止转载】转载请注明出处:www.tangshuang.net上到下的所有对象(副本)。

【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。【作者:唐霜】【未经授权禁止转载】

$route.name

当前路由的名称,如果有的话。

【本文受版权保护】【作者:唐霜】【访问 www.tangshuang.n【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【本文受版权保护】ngnet】

区别

$router是实例化对象,而$rout【本文首发于唐霜的博客】【本文受版权保护】e仅仅是当前的路由信息,两则完全不同。相【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net对来说,$router丰富的多,还提供了【本文首发于唐霜的博客】未经授权,禁止复制转载。很多方法来操作路由。

转载请注明出处:www.tangshua【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.netng.net【未经授权禁止转载】【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【未经授权禁止转载】ang.net【原创不易,请尊重版权】

钩子

我们可以通过一些钩子,来改变vue-ro【本文受版权保护】【版权所有】唐霜 www.tangshuang.netuter导航的默认行为。vue-rout【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】er 提供的导航钩子主要用来拦截导航,让转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net它完成跳转或取消。有多种方式可以在路由导转载请注明出处:www.tangshuang.net【未经授权禁止转载】航发生时执行钩子:全局的, 单个路由独享未经授权,禁止复制转载。【本文首发于唐霜的博客】的, 或者组件级的。

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。原创内容,盗版必究。

全局钩子

你可以使用 router.beforeE【转载请注明来源】【版权所有】唐霜 www.tangshuang.netach 注册一个全局的 before 钩著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。子:

【未经授权禁止转载】【本文受版权保护】原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
  // ...
})

当一个导航触发时,全局的 before 【转载请注明来源】【转载请注明来源】钩子按照创建顺序调用。钩子是异步解析执行【未经授权禁止转载】【版权所有,侵权必究】,此时导航在所有钩子 resolve 完本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】之前一直处于 等待中。

【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netang.net【转载请注明来源】

每个钩子方法接收三个参数:

【本文受版权保护】【原创内容,转载请注明出处】

确保要调用 next 方法,否则钩子就不本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】会被 resolved。

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。

同样可以注册一个全局的 after 钩子本文作者:唐霜,转载请注明出处。【转载请注明来源】,不过它不像 before 钩子那样,a【作者:唐霜】未经授权,禁止复制转载。fter 钩子没有 next 方法,不能著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】改变导航:

【作者:唐霜】原创内容,盗版必究。【版权所有】唐霜 www.tangshu【未经授权禁止转载】转载请注明出处:www.tangshuang.netang.net本文作者:唐霜,转载请注明出处。
router.afterEach(route => {
  // ...
})

某个路由独享的钩子

你可以在路由配置上直接定义 before未经授权,禁止复制转载。【未经授权禁止转载】Enter 钩子:

【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ngnet】【原创内容,转载请注明出处】【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net原创内容,盗版必究。ang.net
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

这些钩子与全局 before 钩子的方法原创内容,盗版必究。本文作者:唐霜,转载请注明出处。参数是一样的。

【本文受版权保护】【未经授权禁止转载】

组件内的钩子

最后,你可以在路由组件内直接定义以下路由原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。导航钩子:

【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。ang.net【未经授权禁止转载】【本文首发于唐霜的博客】
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当钩子执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

beforeRouteEnter 钩子 转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。不能 访问 this,因为钩子在导航确认【未经授权禁止转载】【作者:唐霜】前被调用,因此即将登场的新组件还没被创建【作者:唐霜】转载请注明出处:www.tangshuang.net

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【本文首发于唐霜的博客】转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】ng.net

不过,你可以通过传一个回调给 next来【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。访问组件实例。在导航被确认的时候执行回调未经授权,禁止复制转载。未经授权,禁止复制转载。,并且把组件实例作为回调方法的参数。

【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】ang.net【原创不易,请尊重版权】
beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

你可以 在 beforeRouteLea【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】ve 中直接访问 this。这个 lea本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】ve 钩子通常用来禁止用户在还未保存修改转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。前突然离开。可以通过 next(fals【未经授权禁止转载】转载请注明出处:www.tangshuang.nete) 来取消导航。

【原创内容,转载请注明出处】【访问 www.tangshuang.n【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】et 获取更多精彩内容】

过渡

vue里面提供了过渡的一些基础操作,比如【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。通过切换元素的class属性,配合css著作权归作者所有,禁止商业用途转载。【本文受版权保护】实现过渡效果,在vue-router中也本文作者:唐霜,转载请注明出处。【转载请注明来源】提供了过渡效果,让你在切换view时可以转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。更加酷炫。本章就来整体介绍vue里面的过【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】渡相关的知识。

【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。et 获取更多精彩内容】【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。ngnet】【原创不易,请尊重版权】

过渡效果

概述

Vue 在插入、更新或者移除 DOM 时【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。,提供多种不同方式的应用过渡效果。包括以本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。下工具:

【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。ngnet】

在这里,我们只会讲到进入、离开和列表的过【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。渡, 你也可以看下一节的 管理过渡状态.

未经授权,禁止复制转载。【作者:唐霜】【未经授权禁止转载】

单元素/组件的过渡

Vue 提供了 transition 的【未经授权禁止转载】未经授权,禁止复制转载。封装组件,在下列情形中,可以给任何元素和原创内容,盗版必究。【作者:唐霜】组件添加 entering/leavin转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】g 过渡

本文作者:唐霜,转载请注明出处。【作者:唐霜】

这里是一个典型的例子:

【未经授权禁止转载】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。
<div id="demo">
  <button v-on:click="show = !show">
    Toggle
  </button>
  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#demo',
  data: {
    show: true
  }
})
.fade-enter-active,
 .fade-leave-active {
  transition: opacity .5s
}
.fade-enter, .fade-leave-active {
  opacity: 0
}

当插入或删除包含在 transition【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。 组件中的元素时,Vue 将会做以下处理转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net

未经授权,禁止复制转载。【原创不易,请尊重版权】【转载请注明来源】
  1. 自动嗅探目标元素是否应用了 CSS 过渡【未经授权禁止转载】未经授权,禁止复制转载。或动画,如果是,在恰当的时机添加/删除 【本文受版权保护】转载请注明出处:www.tangshuang.netCSS 类名。
  2. 【转载请注明来源】【版权所有,侵权必究】原创内容,盗版必究。
  3. 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
  4. 本文作者:唐霜,转载请注明出处。【作者:唐霜】【本文首发于唐霜的博客】
  5. 如果没有找到 JavaScript 钩子【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】并且也没有检测到 CSS 过渡/动画,D未经授权,禁止复制转载。【作者:唐霜】OM 操作(插入/删除)在下一帧中立即执著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。行。(注意:此指浏览器逐帧动画机制,与 【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。Vue,和Vue的 nextTick 概本文版权归作者所有,未经授权不得转载。【转载请注明来源】念不同)
  6. 【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netet 获取更多精彩内容】原创内容,盗版必究。【原创内容,转载请注明出处】【原创不易,请尊重版权】

过渡的CSS类名

会有 4 个(CSS)类名在 enter【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】/leave 的过渡中切换

【原创内容,转载请注明出处】【原创内容,转载请注明出处】【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。
  1. v-enter: 定义进入过渡的开始状态【本文受版权保护】【未经授权禁止转载】。在元素被插入时生效,在下一个帧移除。
  2. 【未经授权禁止转载】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】
  3. v-enter-active: 定义进入【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】过渡的结束状态。在元素被插入时生效,在 【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.nettransition/animation【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。 完成之后移除。
  4. 转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。ng.net【关注微信公众号:wwwtangshua原创内容,盗版必究。转载请注明出处:www.tangshuang.netngnet】
  5. v-leave: 定义离开过渡的开始状态【版权所有,侵权必究】【本文受版权保护】。在离开过渡被触发时生效,在下一个帧移除【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】
  6. 转载请注明出处:www.tangshua【原创不易,请尊重版权】【未经授权禁止转载】ng.net未经授权,禁止复制转载。未经授权,禁止复制转载。
  7. v-leave-active: 定义离开【版权所有】唐霜 www.tangshuang.net【本文受版权保护】过渡的结束状态。在离开过渡被触发时生效,【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】在 transition/animati【本文受版权保护】未经授权,禁止复制转载。on 完成之后移除。
  8. 【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。


转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【本文受版权保护】ng.net 对于这些在 enter/leave 过著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。渡中切换的类名,v- 是这些类名的前缀。【转载请注明来源】【版权所有】唐霜 www.tangshuang.net使用 <transition na【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。me=”my-transit【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.netion”> 可以重置前【本文受版权保护】转载请注明出处:www.tangshuang.net缀,比如 v-enter 替换为 my-【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.nettransition-enter。

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。

v-enter-active 和 v-l【转载请注明来源】【原创内容,转载请注明出处】eave-active 可以控制 进入/著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。离开 过渡的不同阶段,在下面章节会有个示【原创不易,请尊重版权】【转载请注明来源】例说明。

【未经授权禁止转载】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

CSS 过渡

常用的过渡都是使用 CSS 过渡。

转载请注明出处:www.tangshua【原创内容,转载请注明出处】【原创内容,转载请注明出处】ng.net【版权所有,侵权必究】【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【原创内容,转载请注明出处】ang.net

下面是一个简单例子:

本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。ngnet】
<div id="example-1">
  <button @click="show = !show">
    Toggle render
  </button>
  <transition name="slide-fade">
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#example-1',
  data: {
    show: true
  }
})
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
  transition: all .3s ease;
}
.slide-fade-leave-active {
  transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, 
.slide-fade-leave-active {
  transform: translateX(10px);
  opacity: 0;
}

CSS 动画

CSS 动画用法同 CSS 过渡,区别是原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。在动画中 v-enter 类名在节点插入【未经授权禁止转载】本文作者:唐霜,转载请注明出处。 DOM 后不会立即删除,而是在 ani【原创不易,请尊重版权】【原创不易,请尊重版权】mationend 事件触发时删除。

【本文首发于唐霜的博客】【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。【未经授权禁止转载】

示例: (省略了兼容性前缀)

【原创不易,请尊重版权】未经授权,禁止复制转载。
<div id="example-2">
  <button @click="show = !show">Toggle show</button>
  <transition name="bounce">
    <p v-if="show">Look at me!</p>
  </transition>
</div>
new Vue({
  el: '#example-2',
  data: {
    show: true
  }
})
.bounce-enter-active {
  animation: bounce-in .5s;
}
.bounce-leave-active {
  animation: bounce-out .5s;
}
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}
@keyframes bounce-out {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(0);
  }
}

自定义过渡类名

我们可以通过以下特性来自定义过渡类名:

【访问 www.tangshuang.n【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】

他们的优先级高于普通的类名,这对于 Vu未经授权,禁止复制转载。【转载请注明来源】e 的过渡系统和其他第三方 CSS 动画未经授权,禁止复制转载。【本文受版权保护】库,如 Animate.css 结合使用十分有用。

【未经授权禁止转载】【未经授权禁止转载】

示例:

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】原创内容,盗版必究。
<link href="https://unpkg.com/animate.css@3.5.1/animate.min.css" rel="stylesheet" type="text/css">
<div id="example-3">
  <button @click="show = !show">
    Toggle render
  </button>
  <transition
    name="custom-classes-transition"
    enter-active-class="animated tada"
    leave-active-class="animated bounceOutRight"
  >
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#example-3',
  data: {
    show: true
  }
})

Transitions 和 Animations

Vue 为了知道过渡的完成,必须设置相应本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net的事件监听器。它可以是 transiti【作者:唐霜】【版权所有,侵权必究】onend 或 animationend本文作者:唐霜,转载请注明出处。【作者:唐霜】 ,这取决于给元素应用的 CSS 规则。【作者:唐霜】【原创内容,转载请注明出处】如果你使用其中任何一种,Vue 能自动识【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net别类型并设置监听。

【关注微信公众号:wwwtangshua【本文首发于唐霜的博客】【版权所有,侵权必究】ngnet】【本文首发于唐霜的博客】未经授权,禁止复制转载。

但是,在一些场景中,你需要给同一个元素同【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】时设置两种过渡动效,比如 animati【转载请注明来源】【未经授权禁止转载】on 很快的被触发并完成了,而 tran【版权所有,侵权必究】未经授权,禁止复制转载。sition 效果还没结束。在这种情况中【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】,你就需要使用 type 特性并设置 a【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netnimation 或 transitio【作者:唐霜】【原创不易,请尊重版权】n 来明确声明你需要 Vue 监听的类型著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net

【转载请注明来源】【本文受版权保护】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。

JavaScript 钩子

可以在属性中声明 JavaScript 本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。钩子

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。【作者:唐霜】【转载请注明来源】
<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled">
  <!-- ... -->
</transition>
// ...
methods: {
  // --------
  // 进入中
  // --------
  beforeEnter: function (el) {
    // ...
  },
  // 此回调函数是可选项的设置
  // 与 CSS 结合时使用
  enter: function (el, done) {
    // ...
    done()
  },
  afterEnter: function (el) {
    // ...
  },
  enterCancelled: function (el) {
    // ...
  },
  // --------
  // 离开时
  // --------
  beforeLeave: function (el) {
    // ...
  },
  // 此回调函数是可选项的设置
  // 与 CSS 结合时使用
  leave: function (el, done) {
    // ...
    done()
  },
  afterLeave: function (el) {
    // ...
  },
  // leaveCancelled 只用于 v-show 中
  leaveCancelled: function (el) {
    // ...
  }
}

这些钩子函数可以结合 CSS trans【原创不易,请尊重版权】【版权所有,侵权必究】itions/animations 使用【作者:唐霜】本文作者:唐霜,转载请注明出处。,也可以单独使用。

著作权归作者所有,禁止商业用途转载。【本文受版权保护】【版权所有】唐霜 www.tangshu【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】ang.net

当只用 JavaScript 过渡的时候【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。, 在 enter 和 leave 中,转载请注明出处:www.tangshuang.net【本文受版权保护】回调函数 done 是必须的 。 否则,转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。它们会被同步调用,过渡会立即完成。

【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。

推荐对于仅使用 JavaScript 过未经授权,禁止复制转载。【原创不易,请尊重版权】渡的元素添加 v-bind:css=&#【未经授权禁止转载】原创内容,盗版必究。8221;false”,Vu本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】e 会跳过 CSS 的检测。这也可以避免著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】过渡过程中 CSS 的影响。

转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】ng.net【原创内容,转载请注明出处】

一个使用 Velocity.js 的简单转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net例子:

【作者:唐霜】未经授权,禁止复制转载。【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。
<!--Velocity works very much like jQuery.animate and isa great option for JavaScript animations-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="example-4">
  <button @click="show = !show">
    Toggle
  </button>
  <transition
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
    v-bind:css="false"
  >
    <p v-if="show">
      Demo
    </p>
  </transition>
</div>

new Vue({
  el: '#example-4',
  data: {
    show: false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.transformOrigin = 'left'
    },
    enter: function (el, done) {
      Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
      Velocity(el, { fontSize: '1em' }, { complete: done })
    },
    leave: function (el, done) {
      Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
          rotateZ: '45deg',
          translateY: '30px',
          translateX: '30px',
          opacity: 0
        },
        { complete: done }
      )
    }
  }
})

初始渲染的过渡

可以通过 appear 特性设置节点的在【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。初始渲染的过渡

【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】ang.net【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netang.net【转载请注明来源】
<transition appear>
  <!-- ... -->
</transition>

这里默认和进入和离开过渡一样,同样也可以【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。自定义 CSS 类名。

本文作者:唐霜,转载请注明出处。【本文受版权保护】本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。ng.net
<transition
  appear
  appear-class="custom-appear-class"
  appear-active-class="custom-appear-active-class">
  <!-- ... -->
</transition>

自定义 JavaScript 钩子:

【转载请注明来源】【转载请注明来源】
<transition
  appear
  v-on:before-appear="customBeforeAppearHook"
  v-on:appear="customAppearHook"
  v-on:after-appear="customAfterAppearHook">
  <!-- ... -->
</transition>

多个元素的过渡

我们之后讨论 多个组件的过渡, 对于原生标签可以使用 v-if/v-本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。else 。最常见的多标签过渡是一个列表未经授权,禁止复制转载。【原创不易,请尊重版权】和描述这个列表为空消息的元素:

【未经授权禁止转载】【原创内容,转载请注明出处】【原创内容,转载请注明出处】
<transition>
  <table v-if="items.length > 0">
    <!-- ... -->
  </table>
  <p v-else>Sorry, no items found.</p>
</transition>

可以这样使用,但是有一点需要注意:

转载请注明出处:www.tangshua【本文受版权保护】【原创不易,请尊重版权】ng.net未经授权,禁止复制转载。原创内容,盗版必究。

当有相同标签名的元素切换时,需要通过 k【未经授权禁止转载】【作者:唐霜】ey 特性设置唯一的值来标记以让 Vue【原创内容,转载请注明出处】【原创不易,请尊重版权】 区分它们,否则 Vue 为了效率只会替转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net换相同标签内部的内容。即使在技术上没有必原创内容,盗版必究。【本文首发于唐霜的博客】要,给在 <transition&原创内容,盗版必究。【作者:唐霜】gt; 组件中的多个元素设置 key 是转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net一个更好的实践。

本文作者:唐霜,转载请注明出处。【未经授权禁止转载】未经授权,禁止复制转载。

示例:

【原创不易,请尊重版权】【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。
<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  <button v-else key="edit">
    Edit
  </button>
</transition>

在一些场景中,也可以给通过给同一个元素的未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net key 特性设置不同的状态来代替 v-原创内容,盗版必究。未经授权,禁止复制转载。if 和 v-else,上面的例子可以重【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】写为:

【本文受版权保护】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>

使用多个 v-if 的多个元素的过渡可以本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。重写为绑定了动态属性的单个元素过渡。 例本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。如:

本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n【原创内容,转载请注明出处】【原创不易,请尊重版权】et 获取更多精彩内容】【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。et 获取更多精彩内容】原创内容,盗版必究。
<transition>
  <button v-if="docState === 'saved'" key="saved">
    Edit
  </button>
  <button v-if="docState === 'edited'" key="edited">
    Save
  </button>
  <button v-if="docState === 'editing'" key="editing">
    Cancel
  </button>
</transition>

可以重写为:

本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】【未经授权禁止转载】【原创不易,请尊重版权】
<transition>
  <button v-bind:key="docState">
    {{ buttonMessage }}
  </button>
</transition>
// ...
computed: {
  buttonMessage: function () {
    switch (docState) {
      case 'saved': return 'Edit'
      case 'edited': return 'Save'
      case 'editing': return 'Cancel'
    }
  }
}

过渡模式

在 “on” 按钮和 “off” 按钮的转载请注明出处:www.tangshuang.net【版权所有,侵权必究】过渡中,两个按钮都被重绘了,一个离开过渡【转载请注明来源】转载请注明出处:www.tangshuang.net的时候另一个开始进入过渡。这是 <【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。transition> 的默认行为【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。 – 进入和离开同时发生。

【转载请注明来源】原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【转载请注明来源】

在元素绝对定位在彼此之上的时候运行正常。【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】然后,我们加上 translate 让它著作权归作者所有,禁止商业用途转载。【转载请注明来源】们运动像滑动过渡。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。ang.net【未经授权禁止转载】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ng.net

同时生效的进入和离开的过渡不能满足所有要【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】求,所以 Vue 提供了 过渡模式

【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ngnet】【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu【本文首发于唐霜的博客】【转载请注明来源】ang.net

用 out-in 重写之前的开关按钮过渡未经授权,禁止复制转载。【版权所有,侵权必究】

原创内容,盗版必究。【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。ang.net本文版权归作者所有,未经授权不得转载。
<transition name="fade" mode="out-in">
  <!-- ... the buttons ... -->
</transition>

只用添加一个简单的特性,就解决了之前的过本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】渡问题而无需任何额外的代码。

【作者:唐霜】原创内容,盗版必究。【转载请注明来源】

in-out 模式不是经常用到,但对于一【原创内容,转载请注明出处】【转载请注明来源】些稍微不同的过渡效果还是有用的。将之前滑【原创内容,转载请注明出处】未经授权,禁止复制转载。动淡出的例子结合。

【版权所有,侵权必究】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ang.net

多个组件的过渡

多个组件的过渡简单很多 – 【版权所有,侵权必究】【转载请注明来源】我们不需要使用 key 特性。相反,我们原创内容,盗版必究。转载请注明出处:www.tangshuang.net只需要使用动态组件:

原创内容,盗版必究。【未经授权禁止转载】【原创不易,请尊重版权】【关注微信公众号:wwwtangshua【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】ngnet】
<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>
new Vue({
  el: '#transition-components-demo',
  data: {
    view: 'v-a'
  },
  components: {
    'v-a': {
      template: '<div>Component A</div>'
    },
    'v-b': {
      template: '<div>Component B</div>'
    }
  }
})
.component-fade-enter-active,
.component-fade-leave-active {
  transition: opacity .3s ease;
}
.component-fade-enter, 
.component-fade-leave-active {
  opacity: 0;
}

列表过渡

目前为止,关于过渡我们已经讲到:

转载请注明出处:www.tangshua【版权所有,侵权必究】原创内容,盗版必究。ng.net【未经授权禁止转载】【关注微信公众号:wwwtangshua未经授权,禁止复制转载。未经授权,禁止复制转载。ngnet】【原创内容,转载请注明出处】

那么怎么同时渲染整个列表,比如使用 v-本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】for ?在这种场景中,使用 <t【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。ransition-group> 【本文受版权保护】【版权所有】唐霜 www.tangshuang.net组件。在我们深入例子之前,先了解关于这个【作者:唐霜】转载请注明出处:www.tangshuang.net组件的几个特点:

原创内容,盗版必究。【未经授权禁止转载】【作者:唐霜】

列表的进入和离开过渡

现在让我们由一个简单的例子深入,进入和离本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。开的过渡使用之前一样的 CSS 类名。

转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】ng.net转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netng.net原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。
<div id="list-demo" class="demo">
  <button v-on:click="add">Add</button>
  <button v-on:click="remove">Remove</button>
  <transition-group name="list" tag="p">
    <span v-for="item in items" v-bind:key="item" class="list-item">
      {{ item }}
    </span>
  </transition-group>
</div>
new Vue({
  el: '#list-demo',
  data: {
    items: [1,2,3,4,5,6,7,8,9],
    nextNum: 10
  },
  methods: {
    randomIndex: function () {
      return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
      this.items.splice(this.randomIndex(), 0, this.nextNum++)
    },
    remove: function () {
      this.items.splice(this.randomIndex(), 1)
    },
  }
})
.list-item {
  display: inline-block;
  margin-right: 10px;
}
.list-enter-active, 
.list-leave-active {
  transition: all 1s;
}
.list-enter, 
.list-leave-active {
  opacity: 0;
  transform: translateY(30px);
}

这个例子有个问题,当添加和移除元素的时候【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net,周围的元素会瞬间移动到他们的新布局的位原创内容,盗版必究。原创内容,盗版必究。置,而不是平滑的过渡,我们下面会解决这个【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】问题。

未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】

列表的位移过渡

<transition-group【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】> 组件还有一个特殊之处。不仅可以原创内容,盗版必究。原创内容,盗版必究。进入和离开动画,还可以改变定位。要使用这【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】个新功能只需了解新增的 v-move 特原创内容,盗版必究。【作者:唐霜】性,它会在元素的改变定位的过程中应用。像转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。之前的类名一样,可以通过 name 属性【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】来自定义前缀,也可以通过 move-cl本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netass 属性手动设置。

【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。

v-move 对于设置过渡的切换时机和过【转载请注明来源】【原创不易,请尊重版权】渡曲线非常有用,你会看到如下的例子:

【访问 www.tangshuang.n【未经授权禁止转载】转载请注明出处:www.tangshuang.netet 获取更多精彩内容】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
<div id="flip-list-demo" class="demo">
  <button v-on:click="shuffle">Shuffle</button>
  <transition-group name="flip-list" tag="ul">
    <li v-for="item in items" v-bind:key="item">
      {{ item }}
    </li>
  </transition-group>
</div>
new Vue({
  el: '#flip-list-demo',
  data: {
    items: [1,2,3,4,5,6,7,8,9]
  },
  methods: {
    shuffle: function () {
      this.items = _.shuffle(this.items)
    }
  }
})
.flip-list-move {
  transition: transform 1s;
}

这个看起来很神奇,内部的实现,Vue 使【未经授权禁止转载】【原创不易,请尊重版权】用了一个叫 FLIP 简单的动画队列使用 transform未经授权,禁止复制转载。【版权所有,侵权必究】s 将元素从之前的位置平滑过渡新的位置。

【关注微信公众号:wwwtangshua原创内容,盗版必究。【版权所有,侵权必究】ngnet】【访问 www.tangshuang.n【转载请注明来源】【转载请注明来源】et 获取更多精彩内容】【未经授权禁止转载】【本文首发于唐霜的博客】

我们将之前实现的例子和这个技术结合,使我本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。们列表的一切变动都会有动画过渡。

【转载请注明来源】【关注微信公众号:wwwtangshua【本文受版权保护】著作权归作者所有,禁止商业用途转载。ngnet】转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.netng.net
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
<div id="list-complete-demo" class="demo">
  <button v-on:click="shuffle">Shuffle</button>
  <button v-on:click="add">Add</button>
  <button v-on:click="remove">Remove</button>
  <transition-group name="list-complete" tag="p">
    <span
      v-for="item in items"
      v-bind:key="item"
      class="list-complete-item"
    >
      {{ item }}
    </span>
  </transition-group>
</div>
new Vue({
  el: '#list-complete-demo',
  data: {
    items: [1,2,3,4,5,6,7,8,9],
    nextNum: 10
  },
  methods: {
    randomIndex: function () {
      return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
      this.items.splice(this.randomIndex(), 0, this.nextNum++)
    },
    remove: function () {
      this.items.splice(this.randomIndex(), 1)
    },
    shuffle: function () {
      this.items = _.shuffle(this.items)
    }
  }
})
.list-complete-item {
  transition: all 1s;
  display: inline-block;
  margin-right: 10px;
}
.list-complete-enter, 
.list-complete-leave-active {
  opacity: 0;
  transform: translateY(30px);
}
.list-complete-leave-active {
  position: absolute;
}

需要注意的是使用 FLIP 过渡的元素不【作者:唐霜】原创内容,盗版必究。能设置为 display: inline【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。 。作为替代方案,可以设置为 displ【未经授权禁止转载】【未经授权禁止转载】ay: inline-block 或者放【转载请注明来源】【原创不易,请尊重版权】置于 flex 中。

【本文受版权保护】未经授权,禁止复制转载。原创内容,盗版必究。

列表的渐进过渡

通过 data 属性与 JavaScri著作权归作者所有,禁止商业用途转载。【作者:唐霜】pt 通信 ,就可以实现列表的渐进过渡:

【未经授权禁止转载】转载请注明出处:www.tangshua【原创内容,转载请注明出处】【本文受版权保护】ng.net
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="staggered-list-demo">
  <input v-model="query">
  <transition-group
    name="staggered-fade"
    tag="ul"
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
  >
    <li
      v-for="(item, index) in computedList"
      v-bind:key="item.msg"
      v-bind:data-index="index"
    >{{ item.msg }}</li>
  </transition-group>
</div>

new Vue({
  el: '#staggered-list-demo',
  data: {
    query: '',
    list: [
      { msg: 'Bruce Lee' },
      { msg: 'Jackie Chan' },
      { msg: 'Chuck Norris' },
      { msg: 'Jet Li' },
      { msg: 'Kung Fury' }
    ]
  },
  computed: {
    computedList: function () {
      var vm = this
      return this.list.filter(function (item) {
        return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
      })
    }
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.height = 0
    },
    enter: function (el, done) {
      var delay = el.dataset.index * 150
      setTimeout(function () {
        Velocity(
          el,
          { opacity: 1, height: '1.6em' },
          { complete: done }
        )
      }, delay)
    },
    leave: function (el, done) {
      var delay = el.dataset.index * 150
      setTimeout(function () {
        Velocity(
          el,
          { opacity: 0, height: 0 },
          { complete: done }
        )
      }, delay)
    }
  }
})

可复用的过渡

过渡可以通过 Vue 的组件系统实现复用【未经授权禁止转载】未经授权,禁止复制转载。。要创建一个可复用过渡组件,你需要做的就【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】是将 <transition>【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net; 或者 <transition-【版权所有】唐霜 www.tangshuang.net【转载请注明来源】group> 作为根组件,然后将任【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。何子组件放置在其中就可以了。

【本文首发于唐霜的博客】【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。【转载请注明来源】ngnet】【关注微信公众号:wwwtangshua原创内容,盗版必究。【版权所有,侵权必究】ngnet】【原创不易,请尊重版权】

使用 template 的简单例子:

【作者:唐霜】【版权所有】唐霜 www.tangshu原创内容,盗版必究。【未经授权禁止转载】ang.net【转载请注明来源】转载请注明出处:www.tangshua【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。ng.net
Vue.component('my-special-transition', {
  template: `
    <transition
      name="very-special-transition"
      mode="out-in"
      v-on:before-enter="beforeEnter"
      v-on:after-enter="afterEnter"
    >
      <slot></slot>
    </transition>
  `,
  methods: {
    beforeEnter: function (el) {
      // ...
    },
    afterEnter: function (el) {
      // ...
    }
  }
})

函数组件更适合完成这个任务:

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【作者:唐霜】【原创内容,转载请注明出处】ng.net【关注微信公众号:wwwtangshua【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】ngnet】
Vue.component('my-special-transition', {
  functional: true,
  render: function (createElement, context) {
    var data = {
      props: {
        name: 'very-special-transition',
        mode: 'out-in'
      },
      on: {
        beforeEnter: function (el) {
          // ...
        },
        afterEnter: function (el) {
          // ...
        }
      }
    }
    return createElement('transition', data, context.children)
  }
})

动态过渡

在 Vue 中即使是过渡也是数据驱动的!著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。动态过渡最基本的例子是通过 name 特原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】性来绑定动态值。

【作者:唐霜】【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。
<transition v-bind:name="transitionName">
  <!-- ... -->
</transition>

当你想用 Vue 的过渡系统来定义的 C【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。SS 过渡/动画 在不同过渡间切换会非常本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。有用。

转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】ng.net【原创内容,转载请注明出处】【本文受版权保护】【转载请注明来源】

所有的过渡特性都是动态绑定。它不仅是简单原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】的特性,通过事件的钩子函数方法,可以在获原创内容,盗版必究。【未经授权禁止转载】取到相应上下文数据。这意味着,可以根据组【原创内容,转载请注明出处】【原创不易,请尊重版权】件的状态通过 JavaScript 过渡【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net设置不同的过渡效果。

【本文受版权保护】【原创内容,转载请注明出处】
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="dynamic-fade-demo">
  Fade In: <input type="range" v-model="fadeInDuration" min="0" v-bind:max="maxFadeDuration">
  Fade Out: <input type="range" v-model="fadeOutDuration" min="0" v-bind:max="maxFadeDuration">
  <transition
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
  >
    <p v-if="show">hello</p>
  </transition>
  <button v-on:click="stop = true">Stop it!</button>
</div>

new Vue({
  el: '#dynamic-fade-demo',
  data: {
    show: true,
    fadeInDuration: 1000,
    fadeOutDuration: 1000,
    maxFadeDuration: 1500,
    stop: false
  },
  mounted: function () {
    this.show = false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
    },
    enter: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 1 },
        {
          duration: this.fadeInDuration,
          complete: function () {
            done()
            if (!vm.stop) vm.show = false
          }
        }
      )
    },
    leave: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 0 },
        {
          duration: this.fadeOutDuration,
          complete: function () {
            done()
            vm.show = true
          }
        }
      )
    }
  }
})

最后,创建动态过渡的最终方案是组件通过接【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net受 props 来动态修改之前的过渡。一【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】句老话,唯一的限制是你的想象力。

转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】ng.net【访问 www.tangshuang.n原创内容,盗版必究。【本文首发于唐霜的博客】et 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】

过渡状态

Vue 的过渡系统提供了非常多简单的方法【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。设置进入、离开和列表的动效。那么对于数据【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。元素本身的动效呢,比如:

【转载请注明来源】本文作者:唐霜,转载请注明出处。

所有的原始数字都被事先存储起来,可以直接转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。转换到数字。做到这一步,我们就可以结合 本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】Vue 的响应式和组件系统,使用第三方库转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】来实现切换元素的过渡状态。

【关注微信公众号:wwwtangshua【版权所有,侵权必究】【原创不易,请尊重版权】ngnet】转载请注明出处:www.tangshua【版权所有,侵权必究】【原创内容,转载请注明出处】ng.net未经授权,禁止复制转载。

状态动画 与 watcher

通过 watcher 我们能监听到任何数转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net值属性的数值更新。可能听起来很抽象,所以原创内容,盗版必究。未经授权,禁止复制转载。让我们先来看看使用Tweenjs一个例子【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。

未经授权,禁止复制转载。【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。
<script src="https://unpkg.com/tween.js@16.3.4"></script>
<div id="animated-number-demo">
  <input v-model.number="number" type="number" step="20">
  <p>{{ animatedNumber }}</p>
</div>

new Vue({
  el: '#animated-number-demo',
  data: {
    number: 0,
    animatedNumber: 0
  },
  watch: {
    number: function(newValue, oldValue) {
      var vm = this
      function animate (time) {
        requestAnimationFrame(animate)
        TWEEN.update(time)
      }
      new TWEEN.Tween({ tweeningNumber: oldValue })
        .easing(TWEEN.Easing.Quadratic.Out)
        .to({ tweeningNumber: newValue }, 500)
        .onUpdate(function () {
          vm.animatedNumber = this.tweeningNumber.toFixed(0)
        })
        .start()
      animate()
    }
  }
})

当你把数值更新时,就会触发动画。这个是一【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。个不错的演示,但是对于不能直接像数字一样本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。存储的值,比如 CSS 中的 color著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。 的值,通过下面的例子我们来通过 Col【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】or.js 实现一个例子:

本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】ng.net未经授权,禁止复制转载。
<script src="https://unpkg.com/tween.js@16.3.4"></script>
<script src="https://unpkg.com/color-js@1.0.3/color.js"></script>
<div id="example-7">
  <input
    v-model="colorQuery"
    v-on:keyup.enter="updateColor"
    placeholder="Enter a color"
  >
  <button v-on:click="updateColor">Update</button>
  <p>Preview:</p>
  <span
    v-bind:style="{ backgroundColor: tweenedCSSColor }"
    class="example-7-color-preview"
  ></span>
  <p>{{ tweenedCSSColor }}</p>
</div>

var Color = net.brehaut.Colornew Vue({
  el: '#example-7',
  data: {
    colorQuery: '',
    color: {
      red: 0,
      green: 0,
      blue: 0,
      alpha: 1
    },
    tweenedColor: {}
  },
  created: function () {
    this.tweenedColor = Object.assign({}, this.color)
  },
  watch: {
    color: function () {
      function animate (time) {
        requestAnimationFrame(animate)
        TWEEN.update(time)
      }
      new TWEEN.Tween(this.tweenedColor)
        .to(this.color, 750)
        .start()
      animate()
    }
  },
  computed: {
    tweenedCSSColor: function () {
      return new Color({
        red: this.tweenedColor.red,
        green: this.tweenedColor.green,
        blue: this.tweenedColor.blue,
        alpha: this.tweenedColor.alpha
      }).toCSS()
    }
  },
  methods: {
    updateColor: function () {
      this.color = new Color(this.colorQuery).toRGB()
      this.colorQuery = ''
    }
  }
})

.example-7-color-preview {
  display: inline-block;
  width: 50px;
  height: 50px;
}

动态状态转换

就像 Vue 的过渡组件一样,数据背后状著作权归作者所有,禁止商业用途转载。【本文受版权保护】态转换会实时更新,这对于原型设计十分有用转载请注明出处:www.tangshuang.net【本文受版权保护】。当你修改一些变量,即使是一个简单的 S【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】VG 多边形也可是实现很多难以想象的效果转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。

未经授权,禁止复制转载。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

See this fiddle for the complete co【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】de behind the above 原创内容,盗版必究。原创内容,盗版必究。demo.

著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。ang.net【本文首发于唐霜的博客】

通过组件组织过渡

管理太多的状态转换会很快的增加 Vue 【本文受版权保护】【未经授权禁止转载】实例或者组件的复杂性,幸好很多的动画可以【转载请注明来源】未经授权,禁止复制转载。提取到专用的子组件。我们来将之前的示例改【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。写一下:

未经授权,禁止复制转载。【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。【未经授权禁止转载】et 获取更多精彩内容】
<script src="https://unpkg.com/tween.js@16.3.4"></script>
<div id="example-8">
  <input v-model.number="firstNumber" type="number" step="20">  +
  <input v-model.number="secondNumber" type="number" step="20"> =
  {{ result }}
  <p>
    <animated-integer v-bind:value="firstNumber"></animated-integer> +
    <animated-integer v-bind:value="secondNumber"></animated-integer> =
    <animated-integer v-bind:value="result"></animated-integer>
  </p>
</div>
// 这种复杂的补间动画逻辑可以被复用
// 任何整数都可以执行动画
// 组件化使我们的界面十分清晰
// 可以支持更多更复杂的动态过渡
// strategies.
Vue.component('animated-integer', {
  template: '<span>{{ tweeningValue }}</span>',
  props: {
    value: {
      type: Number,
      required: true
    }
  },
  data: function () {
    return {
      tweeningValue: 0
    }
  },
  watch: {
    value: function (newValue, oldValue) {
      this.tween(oldValue, newValue)
    }
  },
  mounted: function () {
    this.tween(0, this.value)
  },
  methods: {
    tween: function (startValue, endValue) {
      var vm = this
      function animate (time) {
        requestAnimationFrame(animate)
        TWEEN.update(time)
      }
      new TWEEN.Tween({ tweeningValue: startValue })
        .to({ tweeningValue: endValue }, 500)
        .onUpdate(function () {
          vm.tweeningValue = this.tweeningValue.toFixed(0)
        })
        .start()
      animate()
    }
  }
})
// All complexity has now been removed from the main Vue instance!
new Vue({
  el: '#example-8',
  data: {
    firstNumber: 20,
    secondNumber: 40
  },
  computed: {
    result: function () {
      return this.firstNumber + this.secondNumber
    }
  }
})

我们能在组件中结合使用这一节讲到各种过渡著作权归作者所有,禁止商业用途转载。【本文受版权保护】策略和 Vue 内建的过渡系统。总之,对于完成各种过渡动效几乎没有阻碍本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】

【作者:唐霜】【访问 www.tangshuang.n【版权所有】唐霜 www.tangshuang.net【作者:唐霜】et 获取更多精彩内容】【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。ngnet】

vue-router过渡效果

<router-view> 【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。是基本的动态组件,所以我们可以用 <著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。;transition> 组件给它本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】添加一些过渡效果:

【未经授权禁止转载】转载请注明出处:www.tangshua原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。ng.net
<transition>
  <router-view></router-view>
</transition>

<transition> 的转载请注明出处:www.tangshuang.net【本文受版权保护】所有功能 在这里同样适用。

转载请注明出处:www.tangshua【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.netng.net【版权所有,侵权必究】

单个路由的过渡

上面的用法会给所有路由设置一样的过渡效果未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。,如果你想让每个路由组件有各自的过渡效果本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net,可以在各路由组件内使用 <tra著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】nsition> 并设置不同的 n原创内容,盗版必究。【本文受版权保护】ame。

【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。
const Foo = {
  template: `
    <transition name="slide">
      <div class="foo">...</div>
    </transition>
  `
}
const Bar = {
  template: `
    <transition name="fade">
      <div class="bar">...</div>
    </transition>
  `
}

基于路由的动态过渡

还可以基于当前路由与目标路由的变化关系,【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。动态设置过渡效果:

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。【作者:唐霜】
<!-- 使用动态的 transition name -->
<transition :name="transitionName">
  <router-view></router-view>
</transition>
// 接着在父组件内
// watch $route 决定使用哪种过渡
watch: {
  '$route' (to, from) {
    const toDepth = to.path.split('/').length
    const fromDepth = from.path.split('/').length
    this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
  }
}

.vue文件

介绍

在很多Vue项目中,我们使用 Vue.c【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】omponent 来定义全局组件,紧接着【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。用 new Vue({ el: R【本文首发于唐霜的博客】【转载请注明来源】16;#container ‘【本文受版权保护】【本文受版权保护】;}) 在每个页面内指定一个容器元素。

【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】【原创不易,请尊重版权】ngnet】【原创内容,转载请注明出处】未经授权,禁止复制转载。未经授权,禁止复制转载。

这种方式在很多中小规模的项目中运作的很好【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。,在这些项目里 JavaScript 只【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。被用来加强特定的视图。但当在更复杂的项目【本文受版权保护】本文版权归作者所有,未经授权不得转载。中,或者你的前端完全由 JavaScri【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】pt 驱动的时候,下面这些缺点将变得非常本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。明显:

【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。

文件扩展名为 .vue 的 single【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net-file components(单文件著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。组件) 为以上所有问题提供了解决方法,并【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net且还可以使用 Webpack 或 Bro【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。wserify 等构建工具。

未经授权,禁止复制转载。转载请注明出处:www.tangshua【原创不易,请尊重版权】【原创不易,请尊重版权】ng.net【版权所有,侵权必究】【未经授权禁止转载】

现在我们获得:

未经授权,禁止复制转载。【版权所有,侵权必究】【版权所有,侵权必究】【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。et 获取更多精彩内容】

正如我们说过的,我们可以使用预处理器来构【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。建简洁和功能更丰富的组件,比如 Jade【转载请注明来源】本文作者:唐霜,转载请注明出处。,Babel (with ES2015 【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】modules),和 Stylus。

转载请注明出处:www.tangshua【作者:唐霜】【版权所有】唐霜 www.tangshuang.netng.net本文作者:唐霜,转载请注明出处。

这些特定的语言只是例子,你可以只是简单地转载请注明出处:www.tangshuang.net原创内容,盗版必究。使用 Babel,TypeScript,【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.netSCSS,PostCSS –【未经授权禁止转载】转载请注明出处:www.tangshuang.net 或者其他任何能够帮助你提高生产力的预处【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】理器。

【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。【转载请注明来源】

起步

针对刚接触 JavaScript 模块开发系统的用户

有了 .vue 组件,我们就进入了高级 未经授权,禁止复制转载。原创内容,盗版必究。JavaScript 应用领域。如果你没【未经授权禁止转载】【版权所有,侵权必究】有准备好的话,意味着还需要学会使用一些附本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】加的工具:

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。

在你花一些时日了解这些资源之后,我们建议著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。你参考 webpack-simple 。只要遵循指示,你就能很快的运行一个用【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】到 .vue 组件,ES2015 和 热著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。重载( hot-reloading ) 本文作者:唐霜,转载请注明出处。【作者:唐霜】的Vue项目!

【转载请注明来源】【未经授权禁止转载】【原创不易,请尊重版权】【原创内容,转载请注明出处】

这个模板使用 Webpack,一个能将多个模块打包成最终应用的模块打【未经授权禁止转载】本文作者:唐霜,转载请注明出处。包工具。 这个视频 介绍了Webpack的更多相关信息。 【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】学习了这些基础知识后, 你可能想看看 这个在 Egghead.io上的 高级 未经授权,禁止复制转载。【版权所有,侵权必究】Webpack 课程.

未经授权,禁止复制转载。【未经授权禁止转载】【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】ngnet】

在 Webpack中,每个模块被打包到 【版权所有,侵权必究】【作者:唐霜】bundle 之前都由一个相应的 “lo【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netader” 来转换,Vue 也提供 vue-loader 插件来执行 .vue 单文件组件 的转【原创不易,请尊重版权】未经授权,禁止复制转载。换. 这个 webpack-simple 模板已经为你准备好了所有的东西,但是如【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。果你想了解更多关于 .vue组件和 We本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】bpack 如何一起运转的信息,你可以阅【本文受版权保护】【作者:唐霜】vue-loader 的文档

著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【版权所有,侵权必究】ngnet】【本文受版权保护】原创内容,盗版必究。

针对高级用户

无论你更钟情 Webpack 或是 Br【转载请注明来源】【关注微信公众号:wwwtangshuangnet】owserify,我们为简单的和更复杂的转载请注明出处:www.tangshuang.net【版权所有,侵权必究】项目都提供了一些文档模板。我们建议浏览 github.com/vuejs-tem【本文受版权保护】转载请注明出处:www.tangshuang.netplates,找到你需要的部分,然后参考 READM未经授权,禁止复制转载。【原创不易,请尊重版权】E 中的说明,使用 vue-cli 工具生成新的项目。

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】未经授权,禁止复制转载。

模板中使用 Webpack ,一个模块加载器加载多个模块然后构建成【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net最终应用。为了进一步了解 Webpack未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。, 可以看 官方介绍视频。如果你有基础,可以看 在 Egghead.io 上的 Webp著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】ack 进阶教程

本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】

vue-loader

通过vue-loader对.vue进行预著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】处理。vue-loader是webpac【本文受版权保护】本文作者:唐霜,转载请注明出处。k的一个插件,它可以对你的.vue文件进【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】行预处理,即它把你的style部分进行预著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】编译之后,处理成css,把templat【转载请注明来源】【本文首发于唐霜的博客】e部分编译成vue需要的模板,把scri未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.netpt部分编译为es的javascript【版权所有,侵权必究】转载请注明出处:www.tangshuang.net。我们看下如何在webpack的conf著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】ig文件中进行配置:

转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【作者:唐霜】ng.net原创内容,盗版必究。
{
  module: {
    loaders: [
      {test: /\.vue$/, loader: 'vue-loader'},
    ],
  },
}

.vue里面还支持预处理的其他语言来写,【版权所有】唐霜 www.tangshuang.net【本文受版权保护】比如style用scss来写,templ未经授权,禁止复制转载。【版权所有,侵权必究】ate用jade来写,script用co原创内容,盗版必究。未经授权,禁止复制转载。ffee来写。那么在对.vue进行编译时【原创不易,请尊重版权】原创内容,盗版必究。,就需要提前预编译这些语言。因此,你还得【作者:唐霜】【版权所有】唐霜 www.tangshuang.net安装对应的预编译模块,比如scss,你得转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】安装编译scss要用的node-sass【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】

【本文受版权保护】未经授权,禁止复制转载。
npm install --save sass-loader node-sass

你必须在webpack的文件内配置一个v【本文首发于唐霜的博客】【原创内容,转载请注明出处】ue选项,vue-loader会自动调用原创内容,盗版必究。【本文首发于唐霜的博客】这个选项中的loaders来进行处理:

转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】ng.net本文作者:唐霜,转载请注明出处。
{
  module: {
    loaders: [
      {test: /\.vue$/, loader: 'vue-loader'},
    ],
  },
  vue: {
    loaders: {
      html: 'vue-html-loader!jade-loader',
      js: 'babel-loader',
      css: 'vue-style-loader!sass-loader!css-loader',
    },
  },
}

因为我也没有深度实践过,所以这里只是给了【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。参考代码,如果你在使用中遇到什么问题,可未经授权,禁止复制转载。【作者:唐霜】以在下方留言,让我们一起讨论你的问题。

未经授权,禁止复制转载。【转载请注明来源】

vuex

vuex和react的flux对应,借鉴本文作者:唐霜,转载请注明出处。【本文受版权保护】FluxRedux、和 The Elm Architecture。它是一个专为 Vue.js 应用程序开【作者:唐霜】原创内容,盗版必究。发的状态管理模式,你可以通过这里深入阅读。

【版权所有】唐霜 www.tangshu原创内容,盗版必究。【本文首发于唐霜的博客】ang.net本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】

什么是vuex

Vuex 是一个专为 Vue.js 应用著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】态,并以相应的规则保证状态以一种可预测的【版权所有,侵权必究】【原创内容,转载请注明出处】方式发生变化。Vuex 也集成到 Vue转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net 的官方调试工具 devtools extension,提供了诸如零配置的 time-trav【未经授权禁止转载】【转载请注明来源】el 调试、状态快照导入导出等高级调试功【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】能。

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】【未经授权禁止转载】

简单的说,vuex就是用一个全局单例模式未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】管理组件的共享状态,即用一个全局变量实现本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。多个关联组件的状态管理,这样让组件之间发未经授权,禁止复制转载。【转载请注明来源】生的事件可以更统一的在一个地方管理起来。

未经授权,禁止复制转载。【版权所有,侵权必究】原创内容,盗版必究。

说到底,vuex是vue的一个插件,实现【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。组件之间的状态管理。

【未经授权禁止转载】本文作者:唐霜,转载请注明出处。

编者按:vue是渐进式框架,所谓“渐进式【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。”就是说你需要的时候才用,不需要的时候不【本文受版权保护】【本文受版权保护】用,所以,当你的应用足够复杂的时候,才用本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。vuex,小应用其实没必要使用。

本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】【本文受版权保护】

vuex有一个概念叫“状态”,说白了,它【版权所有,侵权必究】【未经授权禁止转载】就是一个变量state,被挂在store【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net上面,所谓状态,其实也就是上面说的共享的原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】数据,只不过这些数据是统一由vuex来管著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net理,在不同的组件内都可以使用,并且可以更【未经授权禁止转载】转载请注明出处:www.tangshuang.net新,不过要用commit来更新,不可以直【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】接更新state。

原创内容,盗版必究。【作者:唐霜】

每一个 Vuex 应用的核心就是 sto【作者:唐霜】本文版权归作者所有,未经授权不得转载。re(仓库)。”store&【原创不易,请尊重版权】【原创内容,转载请注明出处】#8221; 基本上就是一个容器,它包含【本文受版权保护】原创内容,盗版必究。着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有以下两点不【本文受版权保护】原创内容,盗版必究。同:

【本文首发于唐霜的博客】未经授权,禁止复制转载。【访问 www.tangshuang.n【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】et 获取更多精彩内容】
  1. Vuex 的状态存储是响应式的。当 Vu本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。e 组件从 store 中读取状态的时候本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。,若 store 中的状态发生变化,那么【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。相应的组件也会相应地得到高效更新。
  2. 【未经授权禁止转载】【本文受版权保护】
  3. 你不能直接改变 store 中的状态。改【原创不易,请尊重版权】【未经授权禁止转载】变 store 中的状态的唯一途径就是显【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的【转载请注明来源】【本文受版权保护】变化,从而让我们能够实现一些工具帮助我们本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net更好地了解我们的应用。
  4. 本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】【作者:唐霜】

State

state就是vuex里面的状态,说白了【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net,就是用来保存各个数据的挂载点。

【版权所有,侵权必究】原创内容,盗版必究。未经授权,禁止复制转载。未经授权,禁止复制转载。

单一状态树

Vuex 使用 单一状态树 —— 是的,【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。用一个对象就包含了全部的应用层级状态。至著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net此它便作为一个『唯一数据源(SSOT)』【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。而存在。这也意味着,每个应用将仅仅包含一【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。个 store 实例。单一状态树让我们能【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。够直接地定位任一特定的状态片段,在调试的【未经授权禁止转载】【本文首发于唐霜的博客】过程中也能轻易地取得整个当前应用状态的快【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。照。

【关注微信公众号:wwwtangshua【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.netngnet】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。ng.net【作者:唐霜】转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netng.net

单状态树和模块化并不冲突 —— 在后面的著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net章节里我们会讨论如何将状态和状态变更事件未经授权,禁止复制转载。【原创内容,转载请注明出处】分布到各个子模块中。

本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netngnet】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

组件中获得状态

那么我们如何在 Vue 组件中展示状态呢原创内容,盗版必究。转载请注明出处:www.tangshuang.net?由于 Vuex 的状态存储是响应式的,【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】从 store 实例中读取状态最简单的方【未经授权禁止转载】【本文受版权保护】法就是在计算属性中返回某个状态:

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。【转载请注明来源】
// 创建一个 Counter 组件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

之所以要放在计算属性中,是因为计算属性会【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。追踪自己的依赖,当依赖发生变化时,计算属【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】性也跟着变化。每当 store.stat【转载请注明来源】【版权所有,侵权必究】e.count 变化的时候, 都会重新求【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。取计算属性,并且触发更新相关联的 DOM【转载请注明来源】本文版权归作者所有,未经授权不得转载。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。

然而,这种模式导致组件依赖的全局状态单例著作权归作者所有,禁止商业用途转载。【转载请注明来源】。在模块化的构建系统中,在每个需要使用 【作者:唐霜】未经授权,禁止复制转载。state 的组件中需要频繁地导入,并且本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net在测试组件时需要模拟状态。

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netng.net【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。

Vuex 通过 store 选项,提供了原创内容,盗版必究。原创内容,盗版必究。一种机制将状态从根组件『注入』到每一个子【作者:唐霜】著作权归作者所有,禁止商业用途转载。组件中:

【访问 www.tangshuang.n【本文首发于唐霜的博客】【本文受版权保护】et 获取更多精彩内容】【作者:唐霜】
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})
const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

通过在根实例中注册 store 选项,该【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。 store 实例会注入到根组件下的所有著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】子组件中,且子组件能通过 this.$s【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】tore 访问到。让我们更新下 Coun本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】ter 的实现:

未经授权,禁止复制转载。原创内容,盗版必究。【未经授权禁止转载】【未经授权禁止转载】
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState 辅助函数

当一个组件需要获取多个状态时候,将这些状【版权所有,侵权必究】原创内容,盗版必究。态都声明为计算属性会有些重复和冗余。为了【本文受版权保护】【版权所有】唐霜 www.tangshuang.net解决这个问题,我们可以使用 mapSta【本文首发于唐霜的博客】【原创不易,请尊重版权】te 辅助函数帮助我们生成计算属性,让你【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】少按几次键:

【版权所有】唐霜 www.tangshu【作者:唐霜】本文版权归作者所有,未经授权不得转载。ang.net转载请注明出处:www.tangshua【转载请注明来源】【原创内容,转载请注明出处】ng.net【原创不易,请尊重版权】【关注微信公众号:wwwtangshua【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.netngnet】
// 在单独构建的版本中辅助函数为 
Vuex.mapStateimport { mapState } from 'vuex'
export default {
 // ... 
 computed: mapState({
   // 箭头函数可使代码更简练
   count: state => state.count,
   // 或者,传字符串参数 'count' 等同于 `state => state.count`
   count: 'count',
   // 或者,可以直接写成:
   'count',
   // 为了能够使用 `this` 获取局部状态,必须使用常规函数
   countPlusLocalState (state) {
    return state.count + this.localCount
   }
 })
}

当映射的计算属性的名称与 state 的著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。子节点名称相同时,我们也可以给 mapS转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.nettate 传一个字符串数组。

【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。
computed: mapState([
 // 映射 this.count 为 store.state.count 
 'count'
])

组件仍保有局部状态

使用 Vuex 并不意味着你需要将所有的著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】状态放入 Vuex。虽然将所有的状态放到【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】 Vuex 会使状态变化更显式和易调试,【本文受版权保护】【版权所有,侵权必究】但也会使代码变得冗长和不直观。如果有些状【原创内容,转载请注明出处】未经授权,禁止复制转载。态严格属于单个组件,最好还是作为组件的局【原创内容,转载请注明出处】【原创不易,请尊重版权】部状态。你应该根据你的应用开发需要进行权【作者:唐霜】【关注微信公众号:wwwtangshuangnet】衡和确定。

【转载请注明来源】【原创内容,转载请注明出处】【原创不易,请尊重版权】

Getters

有时候我们需要从 store 中的 st【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】ate 中派生出一些状态,例如对列表进行【本文受版权保护】【作者:唐霜】过滤并计数:

【本文受版权保护】【访问 www.tangshuang.n【本文首发于唐霜的博客】【原创内容,转载请注明出处】et 获取更多精彩内容】【本文受版权保护】
computed: { 
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

如果有多个组件需要用到此属性,我们要么复原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。制这个函数,或者抽取到一个共享函数然后在【本文首发于唐霜的博客】原创内容,盗版必究。多处导入它 —— 无论哪种方式都不是很理【作者:唐霜】【关注微信公众号:wwwtangshuangnet】想。

【本文首发于唐霜的博客】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

Vuex 允许我们在 store 中定义本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】『getters』(可以认为是 stor本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】e 的计算属性)。Getters 接受 原创内容,盗版必究。原创内容,盗版必究。state 作为其第一个参数:

【未经授权禁止转载】【未经授权禁止转载】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netng.net
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

Getters 会暴露为 store.g【版权所有,侵权必究】【本文首发于唐霜的博客】etters 对象:

转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。ng.net未经授权,禁止复制转载。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【作者:唐霜】ang.net
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

Getters 也可以接受其他 gett本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】ers 作为第二个参数:

本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】【关注微信公众号:wwwtangshua【转载请注明来源】【本文首发于唐霜的博客】ngnet】
getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

我们可以很容易地在任何组件中使用它

【原创内容,转载请注明出处】原创内容,盗版必究。转载请注明出处:www.tangshua【未经授权禁止转载】【版权所有,侵权必究】ng.net本文版权归作者所有,未经授权不得转载。
computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}

mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netstore 中的 getters 映射到未经授权,禁止复制转载。【版权所有,侵权必究】局部计算属性

【原创不易,请尊重版权】【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。
import { mapGetters } from 'vuex'
export default {
  // ...
  computed: {
    // 使用对象展开运算符将 getters 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

如果你想将一个 getter 属性另取一【作者:唐霜】转载请注明出处:www.tangshuang.net个名字,使用对象形式:

本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。
mapGetters({
  // 映射 this.doneCount 为 store.getters.doneTodosCount
  doneCount: 'doneTodosCount'
})

Mutations

更改 Vuex 的 store 中的状态【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。的唯一方法是提交 mutation。Vu原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。ex 中的 mutations 非常类似【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】于事件:每个 mutation 都有一个著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。字符串的 事件类型 (type) 和 一【原创内容,转载请注明出处】原创内容,盗版必究。个 回调函数 (handler)。这个回【转载请注明来源】本文版权归作者所有,未经授权不得转载。调函数就是我们实际进行状态更改的地方,并【作者:唐霜】原创内容,盗版必究。且它会接受 state 作为第一个参数:

原创内容,盗版必究。【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netet 获取更多精彩内容】
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++ // 注意:在vuex中,只有mutations里面可以直接修改state
    }
  }
})

你不能直接调用一个 mutation h【转载请注明来源】【作者:唐霜】andler。这个选项更像是事件注册:“本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】当触发一个类型为 increment 的【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。 mutation 时,调用此函数。”要【转载请注明来源】【本文受版权保护】唤醒一个 mutation handle【转载请注明来源】本文作者:唐霜,转载请注明出处。r,你需要以相应的 type 调用 st【转载请注明来源】【未经授权禁止转载】ore.commit 方法:

【作者:唐霜】【原创不易,请尊重版权】
store.commit('increment')

提交Payload

你可以向 store.commit 传入本文版权归作者所有,未经授权不得转载。【本文受版权保护】额外的参数,即 mutation 的 载著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。荷(payload):

【原创不易,请尊重版权】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】ng.net【关注微信公众号:wwwtangshua原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】ngnet】
// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)

在大多数情况下,载荷应该是一个对象,这样【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net可以包含多个字段并且记录的 mutati【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.neton 会更易读:

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】未经授权,禁止复制转载。
// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

对象风格的提交方式

提交 mutation 的另一种方式是直【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net接使用包含 type 属性的对象:

【未经授权禁止转载】未经授权,禁止复制转载。【原创内容,转载请注明出处】【本文首发于唐霜的博客】
store.commit({
  type: 'increment',
  amount: 10
})

当使用对象风格的提交方式,整个对象都作为【原创不易,请尊重版权】未经授权,禁止复制转载。载荷传给 mutation 函数,因此 本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】handler 保持不变:

【原创内容,转载请注明出处】【关注微信公众号:wwwtangshua【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】ngnet】
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

Mutations需遵守Vue的响应规则

既然 Vuex 的 store 中的状态【转载请注明来源】【原创内容,转载请注明出处】是响应式的,那么当我们变更状态时,监视状【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】态的 Vue 组件也会自动更新。这也意味未经授权,禁止复制转载。原创内容,盗版必究。着 Vuex 中的 mutation 也未经授权,禁止复制转载。【原创内容,转载请注明出处】需要与使用 Vue 一样遵守一些注意事项【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。

原创内容,盗版必究。【关注微信公众号:wwwtangshua【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。ngnet】

使用常量替代Mutation事件类型

使用常量替代 mutation 事件类型转载请注明出处:www.tangshuang.net【转载请注明来源】在各种 Flux 实现中是很常见的模式。【本文受版权保护】【版权所有,侵权必究】这样可以使 linter 之类的工具发挥本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】作用,同时把这些常量放在单独的文件中可以【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】让你的代码合作者对整个 app 包含的 未经授权,禁止复制转载。【转载请注明来源】mutation 一目了然:

【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu【本文受版权保护】【原创不易,请尊重版权】ang.net本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。ngnet】
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

用不用常量取决于你 —— 在需要多人协作转载请注明出处:www.tangshuang.net【作者:唐霜】的大型项目中,这会很有帮助。但如果你不喜【版权所有】唐霜 www.tangshuang.net【转载请注明来源】欢,你完全可以不这样做。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】ang.net

mutation必须是同步函数

一条重要的原则就是要记住 mutatio【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】n 必须是同步函数。为什么?请参考下面的【版权所有,侵权必究】转载请注明出处:www.tangshuang.net例子:

【本文受版权保护】【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。ngnet】【作者:唐霜】【原创不易,请尊重版权】
mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}

现在想象,我们正在 debug 一个 a【作者:唐霜】【作者:唐霜】pp 并且观察 devtool 中的 m本文作者:唐霜,转载请注明出处。原创内容,盗版必究。utation 日志。每一条 mutat【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】ion 被记录,devtools 都需要原创内容,盗版必究。本文作者:唐霜,转载请注明出处。捕捉到前一状态和后一状态的快照。然而,在【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。上面的例子中 mutation 中的异步本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】函数中的回调让这不可能完成:因为当 mu未经授权,禁止复制转载。【作者:唐霜】tation 触发的时候,回调函数还没有【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】被调用,devtools 不知道什么时候【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。回调函数实际上被调用 —— 实质上任何在【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】回调函数中进行的的状态的改变都是不可追踪未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net的。

著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【原创不易,请尊重版权】

在组件中提交Mutations

你可以在组件中使用 this.$stor【本文首发于唐霜的博客】【未经授权禁止转载】e.commit(‘xxx&著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。#8217;) 提交 mutation,【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。或者使用 mapMutations 辅助未经授权,禁止复制转载。原创内容,盗版必究。函数将组件中的 methods 映射为 转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。store.commit 调用(需要在根【关注微信公众号:wwwtangshuangnet】【本文受版权保护】节点注入 store)。

【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【转载请注明来源】ang.net原创内容,盗版必究。【原创不易,请尊重版权】
import { mapMutations } from 'vuex'
export default {
  // ...
  methods: {
    ...mapMutations([
      'increment' // 映射 this.increment() 为 this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
    })
  }
}

Actions

Action 类似于 mutation,【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。不同在于:

【本文首发于唐霜的博客】【原创内容,转载请注明出处】【作者:唐霜】

让我们来注册一个简单的 action:

【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】ang.net【原创不易,请尊重版权】【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net【本文受版权保护】et 获取更多精彩内容】
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment') // 注意,须要先注册mutations
    }
  }
})

Action 函数接受一个与 store【原创内容,转载请注明出处】原创内容,盗版必究。 实例具有相同方法和属性的 contex转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。t 对象,因此你可以调用 context【本文受版权保护】【关注微信公众号:wwwtangshuangnet】.commit 提交一个 mutatio【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】n,或者通过 context.state【本文首发于唐霜的博客】【本文受版权保护】 和 context.getters 来【转载请注明来源】原创内容,盗版必究。获取 state 和 getters。当本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。我们在之后介绍到 Modules 时,你【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】就知道 context 对象为什么不是 【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】store 实例本身了。

转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】ng.net【本文受版权保护】【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。ang.net【作者:唐霜】

实践中,我们会经常会用到 ES2015 【版权所有,侵权必究】原创内容,盗版必究。的 参数解构 来简化代码(特别是我们需要【未经授权禁止转载】【原创内容,转载请注明出处】调用 commit 很多次的时候):

【未经授权禁止转载】未经授权,禁止复制转载。
actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

分发Action

Action 通过 store.disp本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】atch 方法触发:

著作权归作者所有,禁止商业用途转载。【本文受版权保护】【未经授权禁止转载】
store.dispatch('increment')

乍一眼看上去感觉多此一举,我们直接分发 著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。mutation 岂不更方便?实际上并非【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】如此,还记得 mutation 必须同步【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。执行这个限制么?Action 就不受约束【本文受版权保护】原创内容,盗版必究。!我们可以在 action 内部执行异步原创内容,盗版必究。未经授权,禁止复制转载。操作:

【转载请注明来源】【未经授权禁止转载】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】ang.net
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

Actions 支持同样的载荷方式和对象【本文受版权保护】未经授权,禁止复制转载。方式进行分发:

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】et 获取更多精彩内容】
// 以载荷形式分发
store.dispatch('incrementAsync', {  amount: 10})
// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

来看一个更加实际的购物车示例,涉及到调用【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】异步 API 和 分发多重 mutati【作者:唐霜】著作权归作者所有,禁止商业用途转载。ons:

转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。【本文受版权保护】ng.net【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netet 获取更多精彩内容】
actions: {
  checkout ({ commit, state }, products) {
    // 把当前购物车的物品备份起来
    const savedCartItems = [...state.cart.added]
    // 发出结账请求,然后乐观地清空购物车
    commit(types.CHECKOUT_REQUEST)
    // 购物 API 接受一个成功回调和一个失败回调
    shop.buyProducts(
      products,
      // 成功操作
      () => commit(types.CHECKOUT_SUCCESS),
      // 失败操作
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

注意我们正在进行一系列的异步操作,并且通本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net过提交 mutation 来记录 act转载请注明出处:www.tangshuang.net【本文受版权保护】ion 产生的副作用(即状态变更)。

转载请注明出处:www.tangshua【本文受版权保护】【版权所有,侵权必究】ng.net未经授权,禁止复制转载。【本文首发于唐霜的博客】【原创内容,转载请注明出处】

在组件中分发Action

你在组件中使用 this.$store.【原创内容,转载请注明出处】【转载请注明来源】dispatch(‘xxx&【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。#8217;) 分发 action,或者【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】使用 mapActions 辅助函数将组【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】件的 methods 映射为 store转载请注明出处:www.tangshuang.net【未经授权禁止转载】.dispatch 调用(需要先在根节点【转载请注明来源】转载请注明出处:www.tangshuang.net注入 store):

【访问 www.tangshuang.n【版权所有,侵权必究】未经授权,禁止复制转载。et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【未经授权禁止转载】ngnet】
import { mapActions } from 'vuex'
export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
    })
  }
}

Actions异步回调通知

Action 通常是异步的,那么如何知道【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】 action 什么时候结束呢?更重要的原创内容,盗版必究。本文作者:唐霜,转载请注明出处。是,我们如何才能组合多个 action,【作者:唐霜】【本文受版权保护】以处理更加复杂的异步流程?

原创内容,盗版必究。【转载请注明来源】【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。ang.net

首先,你需要明白 store.dispa转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。tch 可以处理被触发的action的回原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】调函数返回的Promise,并且stor【原创不易,请尊重版权】原创内容,盗版必究。e.dispatch仍旧返回Promis著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。e:

【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n原创内容,盗版必究。本文作者:唐霜,转载请注明出处。et 获取更多精彩内容】
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

现在你可以:

【版权所有】唐霜 www.tangshu【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。ang.net【转载请注明来源】著作权归作者所有,禁止商业用途转载。
store.dispatch('actionA').then(() => {
  // ...
})

在另外一个 action 中也可以:

原创内容,盗版必究。【作者:唐霜】
actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

最后,如果我们利用 async / aw转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netait 这个 JavaScript 即将【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】到来的新特性,我们可以像这样组合 act【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】ion:

【访问 www.tangshuang.n原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】原创内容,盗版必究。【未经授权禁止转载】
// 假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

一个 store.dispatch 在不【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net同模块中可以触发多个 action 函数【本文受版权保护】【未经授权禁止转载】。在这种情况下,只有当所有触发函数完成后【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net,返回的 Promise 才会执行。

原创内容,盗版必究。【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。ang.net

Modules

使用单一状态树,导致应用的所有状态集中到原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。一个很大的对象。但是,当应用变得很大时,【作者:唐霜】未经授权,禁止复制转载。store 对象会变得臃肿不堪。

【版权所有,侵权必究】【本文首发于唐霜的博客】【未经授权禁止转载】

为了解决以上问题,Vuex 允许我们将 【原创内容,转载请注明出处】【版权所有,侵权必究】store 分割到模块(module)。原创内容,盗版必究。原创内容,盗版必究。每个模块拥有自己的 state、muta未经授权,禁止复制转载。【本文首发于唐霜的博客】tion、action、getters、原创内容,盗版必究。【转载请注明来源】甚至是嵌套子模块——从上至下进行类似的分著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】割:

【转载请注明来源】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。
const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}
const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

模块的局部状态

对于模块内部的 mutation 和 g【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。etter,接收的第一个参数是模块的局部本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。状态。

【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。
const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // state 模块的局部状态
      state.count++
    }
  },
  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}
同样,对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState:
const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态转载请注明出处:www.tangshuang.net【版权所有,侵权必究】会作为第三个参数:

【版权所有】唐霜 www.tangshu【作者:唐霜】【本文首发于唐霜的博客】ang.net本文版权归作者所有,未经授权不得转载。
const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

命名空间

模块内部的 action、mutatio【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。n、和 getter 现在仍然注册在全局【本文首发于唐霜的博客】原创内容,盗版必究。命名空间——这样保证了多个模块能够响应同转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。一 mutation 或 action。【版权所有,侵权必究】【版权所有,侵权必究】你可以通过添加前缀或后缀的方式隔离各模块本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】,以避免名称冲突。你也可能希望写出一个可【原创内容,转载请注明出处】未经授权,禁止复制转载。复用的模块,其使用环境不可控。例如,我们本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。想创建一个 todos 模块:

【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。ang.net未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。【转载请注明来源】
// types.js
// 定义 getter、action、和 mutation 的名称为常量,以模块名 `todos` 为前缀
export const DONE_COUNT = 'todos/DONE_COUNT'
export const FETCH_ALL = 'todos/FETCH_ALL'
export const TOGGLE_DONE = 'todos/TOGGLE_DONE'
// modules/todos.js
import * as types from '../types'
// 使用添加了前缀的名称定义 getter、action 和 mutation
const todosModule = {
  state: { todos: [] },
  getters: {
    [types.DONE_COUNT] (state) {
      // ...
    }
  },
  actions: {
    [types.FETCH_ALL] (context, payload) {
      // ...
    }
  },
  mutations: {
    [types.TOGGLE_DONE] (state, payload) {
      // ...
    }
  }
}

模块动态注册

在 store 创建之后,你可以使用 s本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。tore.registerModule 原创内容,盗版必究。未经授权,禁止复制转载。方法注册模块:

【关注微信公众号:wwwtangshua本文作者:唐霜,转载请注明出处。【本文受版权保护】ngnet】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。ng.net【本文首发于唐霜的博客】转载请注明出处:www.tangshua【本文受版权保护】【本文首发于唐霜的博客】ng.net
store.registerModule('myModule', {
  // ...
})

模块的状态将是 store.state.本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netmyModule。

原创内容,盗版必究。【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。

模块动态注册功能可以让其他 Vue 插件【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。为了应用的 store 附加新模块,以此本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。来分割 Vuex 的状态管理。例如,vu【本文首发于唐霜的博客】【原创内容,转载请注明出处】ex-router-sync 插件可以集本文版权归作者所有,未经授权不得转载。【本文受版权保护】成 vue-router 与 vuex,【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。管理动态模块的路由状态。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu【转载请注明来源】原创内容,盗版必究。ang.net

你也可以使用 store.unregis转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。terModule(moduleName转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】) 动态地卸载模块。注意,你不能使用此方【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。法卸载静态模块(在创建 store 时声【原创不易,请尊重版权】【版权所有,侵权必究】明的模块)。

【访问 www.tangshuang.n原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【转载请注明来源】【作者:唐霜】

小结

本章讲vue,其实就是一直在反复谈论如何【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。在组件之间共享数据。vuex通过一个中间转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net的数据存储仓库store来实现组件之间的【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。数据交换。你可以使用一个全局变量保存这个【作者:唐霜】【作者:唐霜】store,然后就可以在所有地方使用这个本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。store。

本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【转载请注明来源】ngnet】【原创不易,请尊重版权】【本文受版权保护】

如果要在组件中局部使用,你须要把这个st【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】ore传入到根实例,这样在每一个组件里面【版权所有,侵权必究】原创内容,盗版必究。都可以使用this.$store.sta本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】te来访问共享状态。这个状态和视图是联动【原创内容,转载请注明出处】【原创内容,转载请注明出处】的,当状态在一个组件中被更改,那么其他组【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net件中如果使用到这个状态,那么视图也会跟着【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】更改。

【原创不易,请尊重版权】【未经授权禁止转载】【转载请注明来源】

不过就像前面在探讨prop属性的时候一样【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】,你不能直接通过修改this.$stor【版权所有,侵权必究】转载请注明出处:www.tangshuang.nete.state上的某个值来修改状态,你必本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】须在store被创建的时候就先确定好要准本文版权归作者所有,未经授权不得转载。【作者:唐霜】备哪些数据用来共享,并且写好对应的mut【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】ations,在组件内使用this.$s本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。tore.commit来提交mutati【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。ons,达到修改state的目的。com著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】mit提交是修改state的唯一方法。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。

但是所有的mutations操作必须是同【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】步的,要异步操作,就必须使用action【本文受版权保护】原创内容,盗版必究。s,和mutations使用方法一样,a【原创不易,请尊重版权】转载请注明出处:www.tangshuang.netctions也必须在创建store时定义【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】好,在组件内使用this.$store.转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】dispatch来分发某一个action转载请注明出处:www.tangshuang.net【转载请注明来源】。而在action函数体内,也必须通过c著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】ommit来修改state。

【转载请注明来源】未经授权,禁止复制转载。【未经授权禁止转载】【本文首发于唐霜的博客】

其他

vue-cli

vue官方提供了一个命令端工具vue-c【未经授权禁止转载】原创内容,盗版必究。li来快速创建、编译你的组件,你可以通过这里深入阅读。

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。原创内容,盗版必究。【作者:唐霜】

服务端渲染

vue2.0版本之后,开始支持服务端渲染本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。。简单的来说,服务端渲染就跟以前我们直接【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】用php输出html差不多,但是对于前后【本文受版权保护】原创内容,盗版必究。端都是vue的node服务器环境而言,服【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】务端渲染可以实现后端渲染完之后,前端可以【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。获知哪里是由服务端渲染的,这样前端就不用著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】自己渲染了。

【原创内容,转载请注明出处】【原创内容,转载请注明出处】【转载请注明来源】【访问 www.tangshuang.n【未经授权禁止转载】【本文受版权保护】et 获取更多精彩内容】

编者不是很看好服务端渲染,它使得开发的逻【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】辑变得很难理解,而且如果开发时考虑服务端未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net渲染,不得不考虑一些原本编程中不需要思考【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net的问题,这其实也违背了编程本身的乐趣。如本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。果你看“生命周期”一章,就会发现,很多钩未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。子函数在服务端渲染的时候不被调用,这使得【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。你在编程的时候,原本对生命周期的理解会变本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】得被怀疑。

【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。

后记

本书作为vue的中文教程,主要是为了帮助原创内容,盗版必究。【版权所有,侵权必究】那些想要尽快学会vue,使用vue进行编【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net程的同学准备的,所以里面涉及的内容更偏向本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】于实用性和可理解性。大部分内容都是从官网【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】或对应的api文档中拷贝过来,同时加上自【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】己的话,使得对应的知识点更容易理解一些。【本文受版权保护】【原创不易,请尊重版权】但是毕竟不可能做到完美,肯定还会有不足之【未经授权禁止转载】本文作者:唐霜,转载请注明出处。处,如果你在阅读中有什么疑问或不懂的地方【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。,请在下方的留言框中留言,我会第一时间解转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net答你。

未经授权,禁止复制转载。【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netang.net本文作者:唐霜,转载请注明出处。

如果你觉得本书对你有帮助,通过下方的二维码向我打赏吧,帮助我写出更多有用的内容。

2017-05-04 |