1 简易安装
要使用Vue.js,我们得先把它安装到我们的项目中,说明了简易安装,我们讲解的肯定是最简单的方法,先不管那些高大上的费时间的安装方法,直接引入一个js文件.
官网提供了Vue.js源码下载的地方:https://cdn.jsdelivr.net/vue/2.1.3/vue.js
如果你不想下载到本地,要可以直接用CDN的方式,引入网上资源,一样可以:
这样,我们就成功地用最简单的方法把Vue.js引入到我们的项目中了。至于那些高大上的npm,Bower等花式安装方法,我们后期再看它。
2 数据驱动视图
引入之后,我们就可以把它用起来。听说它最牛逼的地方是数据驱动视图,解放DOM操作,让你不再做又复杂又耗性能的DOM操作。那么,我们就看看它是怎么玩的!
假设,我们现在要把js对象中的某个变量的值渲染在页面上,传统的做法,就是先用getElementById获取到DOM节点对象,再innerHTML设置它的内容。
我们通过new Vue( )创建一个实例vm,参数是一个json对象,属性el提供一个在页面上存在的DOM 元素(id=‘app’),表明这个实例是关联指定的DOM节点。
在DOM节点上,我们就可以使用双大括号{ { }}的语法来渲染Vue实例对象data中已经存在的属性值,如上面案例中的name属性的值“web前端教程”就会被渲染到页面中,替换{ { name }} 显示效果为:“web前端教程”。
3 双向绑定
更方便的是,Vue.js还提供了方便的语法指令,实现视图和数据的双向绑定,也就是说,不但数据变化了可以驱动视图,用户在页面上做了一些操作,也很方便地实现更新model层的数据。
例子:监听用户在页面输入框输入的内容,然后将其实时更新在页面上。
在Vue中我们使用v-model指令就可以轻松实现。(v-model是什么东西,先不用管,后面会有章节详细介绍)。
4 组件
上面的我们演示了Vu.jse的数据驱动,别忘了,上一节我们提到Vue.js还有一个重要的核心,就是:组件化。
组件化就是把页面中特定的区块独立抽出来,并封装成一个可方便复用的组件。
例子:假设,页面上有多个一样的卡片:
在这里插入图片描述
传统的办法,我们可以要写三份同样的HTML布局:
web前端教程
这里是描述,很长的描述
web前端教程
这里是描述,很长的描述
web前端教程
这里是描述,很长的描述
如果我们把每个卡片看作一个可复用的区域的话,那么它就可以封装成一个组件。
在Vue.js中,我们试着把卡片封装成一个组件。
我们用Vue.component(tagName, options)注册了一个名字叫card的组件,这样,在需要复用这个组件的地方,我们只需要使用
可能你会说,组件里面的显示的内容不可能全都一样。放心,Vue为组件提供了props属性来接受传递进来的参数,后面我们会有专门的章节来介绍组件的详细用法。
进阶一:
我们之前说过,Vue是数据驱动视图的,只要model(模型层)的数据改变了,Vue就会帮我们改变视图上显示的内容,不用我们自己去动手写代码更新。那么,它是怎么做到的,我们的代码要怎么写才能做到这一点。
答案是:Vue实例。
先确保你的项目安装好Vue.js
安装好之后,我们来看看怎么创建和使用Vue实例,我们把它分成 4 步走。
第1步 创建语法
创建一个Vue实例的语法很简单,如下:
通过关键语句 new Vue( )我们就可以创建一个Vue实例:vm了。我们注意到了我们给Vue( )传了一个参数选项,是一个空对象,我们接着往下看。
第2步 设置数据
没错,我们就是利用上面的对象参数,来创建这个Vue实例wm的,比如,设置vm里面的数据。
let vm = new Vue({
//实例vm的数据
data:{
name: "张三",
age : 21
}
});
写法也很简单,参数对象不再是一个空对象,它包含一个属性:data,而data的值也是一个对象,这个对象就是我们给实例vm设置的数据了。比如:name为张三,age为21等等。
第3步 挂载元素
创建了一个实例vm,设置了vm的数据后,我们怎么把数据展示在视图上呢这就要通过我们的挂载元素了。我们看看怎么用:
视图view部分:
视图(html部分)上我们有一个id为”app”的div元素。
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
name: "张三",
age : 21
}
});
我们看到参数中我们不但有属性“data”,还多了个属性:“el”,el参数提供一个在页面上已经存在的DOM元素,作为我们实例vm的挂载目标。表示我们的实例vm和id为“app”的DOM节点就关联起来了。
第4步 渲染
实例vm创建好了,数据data有了,DOM节点也关联起来了,最后一步,就是把vm的数据绑定到指定的视图上了,也就是数据渲染。
我是{
{ name }},
今年{
{ age }}岁
对,就是你看到的这么简单,我们只需要用一个双大括号:{ { }} 即可,你可以留意到,{ { name }} 和 { { age }} 就是我们给实例vm设置的数据name和age,我们用**{ { }}**可以直接读取到它们的值。
我们访问页面,就会看到vm的数据data就会被成功地渲染出来:
就这样,我们就成功地创建了一个vue实例,并把它的数据渲染在视图上了,超
简单。
我们知道,定义一个Vue实例的参数有el(指定挂载的DOM元素),data(实例的数据),上一节讲过除了这两个之外,还可以定义其他参数。今天,我们就来学习在开发中,我们要怎么定义一个vue实例才能满足我们的需要?
下面,我们先用上一节的知识,先创建一个Vue实例:
很简单,轻松搞掂,接下来,就用这个实例来展开讲解。
我们就具体讲一下定义一个vue实例会用到的4个常用参数选项,不常用的选项,咱先不管它(后面有需要会补充)。因为学会这4个,就可以满足基本的开发需要了。
filters 过滤器
第一个要讲的是过滤器filters选项。为什么要有这个东西呢?举个例子,假设我们有一组数字,都是小数,如下:
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
num1:33.141,
num2:46.212,
num3:78.541
}
});
num1,num2,num3都是Vue实例vm的小数,我们把它展示在视图上:
数字1:{
{ num1 }}
数字2:{
{ num2 }}
数字3:{
{ num3 }}
利用上节讲到的双大括号{ { }}渲染出来,很简单。
突然,需求改了,我们不能把小数展示出来,需要把小数转换成整数再显示。
这个时候,我们需要把三个小数经过过滤处理后再展示,不能直接展示。这种情况就需要用到Vue的filters过滤器了。我们来看看怎么用:
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
num1:33.141,
num2:46.212,
num3:78.541
},
//过滤器
filters:{
toInt(value){
return parseInt(value);
}
}
});
我们回到过滤器filters,接着讲:定义完filters属性后,我们怎么用呢?
数字1:{
{ num1 | toInt}}
数字2:{
{ num2 | toInt}}
数字3:{
{ num3 | toInt}}
也很简单,如上面代码所示,通过管道符** | **把函数toInt 放在变量后面即可,num1,num2,num3会分别作为参数value传入toInt( value )方法进行运算,并返回一个整数。
18.**computed 计算属性 **
有时候,我们拿到一些数据,需要经过处理计算后得到的结果,才是我们要展示的内容。
比如:我们有三个数,但是需要展示的是三个数字之和。这种情况,就适合用我们的计算属性computed。
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
num1:1,
num2:3,
num3:6
},
//计算属性
computed:{
sum(){
return this.num1+this.num2+this.num3
}
}
});
计算属性computed的定义语法和过滤器filters类似,但是用法不一,如下:
总和:{
{ sum }}
计算属性computed用法更简洁,仅需**{ { sum }}**就能读取到它的计算结果:1+3+6结果应该为10。
需要注意的是,sum的值是依赖data中的数据num1,num2,num3的,一旦它们发生了变化,sum的值也会自动更新。
我们试一下,通过chrome控制台把num1的值从1变成2,再看看sum的结果会是多少?
methods 方法
顾名思义,在methods中,我们可以定义一些方法,供组件使用。
比如,我们定义一个数据a,当用户点击按钮的时候,a的值加1。这种情况,我们可以利用methods来实现。
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
a:0
},
//方法
methods:{
plus(){
return this.a++;
}
}
});
定义一个**plus( )的方法在methods中,下面我们把plus( ) **绑定在按钮的点击事件上:
{
{ a }}
在Vue中通过v-on:指令来绑定事件(指令后面章节会介绍),我们点击按钮,methods中的方法**plus( )**就会被调用,实现给a的值加1,并更新视图。
watch 观察
watch选项是Vue提供的用于检测指定的数据发生改变的api。
上面点击按钮a的值加1的例子,不就是数据发生变化了吗?我们就用watch选项来监听数字a是否发生了变化,如果了监听到了变化,我们就在控制台输入以下a的最新值。
在上个例子的代码基础上,我们加上watch部分的代码:
let vm = new Vue({
//挂载元素
el:'#app',
//实例vm的数据
data:{
a:0
},
//方法
methods:{
plus(){
return this.a++;
}
},
//观察
watch:{
a(){
console.log(`有变化了,最新值:`);
console.log(this.a);
}
}
});
最后一部分watch就是我们新加的代码,**a( ) **表示我们要观察监听的就是数据a,我们看运行结果:
看到了,我们点击按钮的时候,a的值加1发生了变化,而此时watch监听到了它的变化,便在控制台输出了我们指定的内容
这一节我们学习vue实例的生命周期,没错,实例也跟动物一样,有自己的“生命”,实例也会经历出生至死亡的各个阶段。
Vue把整个生命周期划分为创建、挂载、更新、销毁等阶段,每个阶段都会给一些“钩子”让我们来做一些我们想实现的动作。学习实例的生命周期,能帮助我们理解vue实例的运作机制,更好地合理利用各个钩子来完成我们的业务代码。
我们分别来看看这几个阶段:
1. beforeCreate
此阶段为实例初始化之后,此时的数据观察和事件配置都没好准备好。
我们试着console一下实例的数据data和挂载元素el,代码如下:
{
{name}}
得到的结果是:
即将创建
undefined
undefined
此时的实例的data和el还是undefined,不可用的。
2. created
beforeCreate之后紧接着的钩子就是创建完毕created,我们同样打印一下数据data和挂载元素el,看会得到什么?
在上一段代码的基础上,加上下面这段代码:
created(){
console.log('创建完毕');
console.log(this.$data);
console.log(this.$el);
}
此时,我们能读取到数据data的值,但是DOM还没生成,所以属性el还不存在,输出**$data为一个Object对象,而$el**的值为undefined。
3. beforeMount
上一个阶段我们知道DOM还没生成,属性el还为undefined,那么,此阶段为即将挂载,我们打印一下此时的$el是什么?
增加一下代码:
beforeMount(){
console.log('即将挂载');
console.log(this.$el);
}
}
我们看到打印结果:
即将挂载
{
{name}}
此时的**$el不再是undefined,而是成功关联到我们指定的dom节点
,但此时{ { name }}**还没有被成功地渲染成我们data中的数据。没事,我们接着往下看。4. mounted
mounted也就是挂载完毕阶段,到了这个阶段,数据就会被成功渲染出来,我们编写mounted的钩子,打印**$el** 看看:
mounted(){
console.log('挂载完毕');
console.log(this.$el);
}
打印结果:
挂载完毕
我们试一下,在控制台修改一下实例的数据name,在更新渲染之前,我们打印视图中文本innerHTML的内容会是多少:
我们在控制台把app.name的值从原来的 “前端君” 修改成 “web前端教程”,在更新视图之前beforeUpdate打印视图上的值,结果依然为原来的值:“前端君”,表明在此阶段,视图并未重新渲染更新。
6. updated
此阶段为更新渲染视图之后,此时再读取视图上的内容,已经是最新的内容,接着上面的案例,我们添加钩子updated的代码,如下:
updated(){
console.log('==更新成功==');
let name = this.$refs.app.innerHTML;
console.log('name:'+name);
}
大家注意两个不同阶段打印的name的值是不一样,updated阶段打印出来的name已经是最新的值:“web前端教程”,说明此刻视图已经更新了。
7. beforeDestroy
调用实例的destroy( )方法可以销毁当前的组件,在销毁前,会触发beforeDestroy钩子。
8. destroyed
成功销毁之后,会触发destroyed钩子,此时该实例与其他实例的关联已经被清除,它与视图之间也被解绑。
案例:我们通过在销毁前通过控制台修改实例的name,和销毁之后再次修改,看看情况。
beforeDestroy(){
console.log('销毁之前');
},
destroyed(){
console.log('销毁成功');
}
销毁之前,修改name的值,可以成功修改视图显示的内容为:“更新视图”,一旦效用实例的$destroy( )方法销毁之后,实例与视图的关系解绑,再修改name的值,已于事无补,视图再也不会更新了,说明实例成功被销毁了。
9. actived
keep-alive组件被激活的时候调用。
10. deactivated
keep-alive 组件停用时调用。
关于keep-alive组件的激活和停用,我们后面讲到具体案例再介绍,在这里你只需要知道vue提供了keep-alive组件激活和停用的钩子就可以了。
如何在html中绑定数据
这一节,我们学习如何在html上绑定我们实例中的数据。
Mustache 语法
什么叫Mustache语法,别被这高大上的叫法吓到了,其实就是双大括号**{ { }}**的写法,在之前的章节我们就演示过在视图中显示我们的数据,这是最常见的绑定方式。有了它,我们可以轻松地在视图显示我们的数据并及时自动更新,无需手动控制。
{
{ name }}
十分简单,页面视图上也成功显示我们的data中的name的值:“前端君”。
绑定纯html
有时候有一种这样的需求,我们的数据包含了一些html的标签代码,比如:
name:"前端君"
文本“前端君”被一个****标签包住,而我们在展示的是,需要合理地渲染strong标签,再显示我们想要展示文本内容。这种情况,用原来的双大括号{ { }}方式,就不能满足了,它会渲染成这样:
被当作是普通的文本数据被展示了,这并不是我们想要的结果。这个是时候,你需要用vue提供的v-html指令,用法如下:
v-html以属性的形式添加到了div中,值为“name”,也就是我们数据data中的name:
"前端君"
我们来看看视图展示的结果:
视图上的“前端君”有了明显的加粗效果,说明标签发挥了作用,我们通过chrome的开发者工具查看解析生成后的html文档,name的值,被解析成html标签,并作为字节点,插入在****中去。
这,就是v-html的作用啦。
绑定属性
前面两个都是控制视图展示文本内容,有时候,html标签的属性也很重要,比如:标签的href属性,标签的src属性等。Vue中如何将data中的数据绑定为这些属性的值呢?还是用双大括号**{ { }}**的写法吗?
当然不是,这里不需要用双大括号**{ { }}**,我们用v-bind指令,如下:
在视图中的a标签,我们在标签加上v-bind:来修饰href属性,而它的值就是data中的属性link。我们来看看解析渲染的html页面效果。
标签的属性href的值成功地绑定了data数据link的值,通过v-bind指令,就成功地将数据成功地绑定在视图的标签的属性中。
v-bind 指令的简写
对于v-bind指令,如果一个标签中需要绑定多个属性的话,就得连续写多个v-bind。
问题是没问题,但vue为了我们的代码更简洁易看,提供了v-bind指令的简写,仅需要冒号。
原本完整的写法:
hello官网
简洁的写法:
hello官网
此外,需要注意的是:当渲染的属性值是布尔值的时候(true和false),效果就不一样了,并不是简单地将true或者false渲染出来,而是当值为false的时候,属性会被移除。
我们试试看:
我们通过v-bind指令的缩写,给两个button标签的disabled属性绑定值,一个值为true,一个值为false,我们来看看效果:
我们看到,当属性值设置成true的时候,disabled的值为解析成“disabled”,当属性值设置成false的时候,属性disabled直接被移除掉了。
支持javascript表达式
上面讲到的都是将数据简单地绑定在视图上,但事实上,vue还支持我们对数据进行简单的运算:javascript表达式支持。
我们举3个例子演示一下:
1.加减乘除运算:
{
{ num+3 }}
上面的案例,在渲染的时候,并不是直接渲染data的num,而是对num进行的简单的加法:num+3,渲染的结果为:5。
三元运算符计算,上面元算的结果为:“yes”。
3.字符串拼接:
我们给
标签加上了指令 v-text ,它的值就是我们data数据中的msg,就这么简单,最后我们来看看渲染结果:
有没有发现,它的作用跟{ { msg }}效果是一样的:
{
{ msg }}
2. v-html 指令
2. v-html 指令
这个指令我们再上一节刚刚讲过,它帮助我们绑定一些包含html代码的数据在视图上,比如:“hello,vue”,这个字符串包含了标签,要想不被当作普通的字符串渲染出来,就得用 v-html 指令。
/script>
还是上面的代码,我们把 v-text 指令换成 v-html 指令,msg的值变成了含有html代码的:“hello vue”,我们看看渲染效果:
就这样,标签被成功解析并渲染出来,视图上的文本也有了加粗的效果,这就是v-html发挥了作用,bingo!
3. v-show 指令
v-show ,听这名字就可以猜测它跟元素的显示/隐藏 相关,没错,它就是用来控制元素的display css属性的。
v-show 指令的取值为true/false,分别对应着显示/隐藏。有比较才能看到效果,我们拿两个标签分别设置不同的值,看看解析渲染效果。
我是true
我是false
我们用了两个
标签,都加上了 v-show 指令,取值分别为true和fasle,直接看效果吧!
第一个p标签的v-show设置为true,元素正常显示;第二个p标签的v-show设置为false,元素解析成:
我是false
所以它不会显示在视图上。这就是 v-show 指令的用法,简单明了。
4. v-if 指令
v-if 指令的取值也是为true或false,它控制元素是否需要被渲染出来,听起来有点抽象,不怕,同样,我们拿两个元素设置不用的值,对比一下看效果就知道了。
我是true
我是true
我们把 v-show 指令换成了 v-if ,同样是两个
标签,同样是不同的取值:true和false。我们看效果:
看到了吧,设置为true的
标签,成功渲染出来,而设置为false的
标签,直接被一行注释代替了,并没有被解析渲染出来。
也许你会问了, v-show 和 v-if 都能控制元素显示或者隐藏,这两个怎么区别使用呢?
记住一点:如果需要频繁切换显示/隐藏的,就用 v-show ;如果运行后不太可能切换显示/隐藏的,就用 v-if 。
5. v-else 指令
if和else在编程语言一般都是结对出现的,在vue里面也不例外。它没有对应的值,但是要求前一个兄弟节点必须要使用 v-if 指令,也对,没有if,哪来的else。
我是if
我是else
我们使用两个
标签,第一个使用 v-if 指令,并取值为false,第二个使用 v-esle 指令,啥也不说了,看效果最直观:
只有第二个
标签被渲染出来,第一个
标签由于 v-if 指令的值为false,直接被忽视了,不渲染。
同理,一旦第一个标签的 v-if 指令的值为true,被忽视的就是第二个
标签了。 v-if 和 v-else 只有一个会被渲染出来。
有兴趣的同学,可以继续去了解一下 v-else-if 指令,同样很简单。
上一节我们学了5个重要的指令: v-text 、 v-html 、 v-show 、 v-if 、 v-else
这一节,我们继续学习剩下的5个指令。话不多说,撸起来!
- v-for 指令
有时候,我们的data中的存放的数据不是个简单的数字或者字符串,而是数组Array类型,这个时候,我们要把数组的元素展示在视图上,就需要用到vue提供的 v-for 指令,来实现列表的渲染。
我们看看它的用法:
{
{item}}
首先,我们的data中包含数组list,数组包含三个元素:“Tom”,“John”,“Lisa”,我们通过 v-for 指令把它渲染出来,其中item表示数组中的每个元素。我们看看渲染结果:
我们看到,我们解析渲染出三个div,其中包含的值分别是数组中的元素,表示我们解析渲染成功。
什么,怎么拿到索引?拿到每个元素的索引也很简单,我们稍微改动一下代码,把html部分的代码修改为:
{ {index}}.{ {item}}
在循环解析的过程中,我们不但要拿到list数组的每个元素item,我们还获取每个元素的索引,写法如上,循环的时候加上(index,item)。
我们来看效果图:
我们看到,索引分别是0,1,2都被成功地渲染出来了。这就是用 v-for 指令来渲染列表的用法。比起以前手动更新dom列表,简直就是方便得不要不要的。
提醒:v-for指令除了可以迭代数组,还可以迭代对象和整数。
7. v-bind 指令
在第六节我们也提过 v-bind 指令的作用和用法,它用于动态绑定DOM元素的属性,比较常见的比如:标签的href属性,标签的src属性。
用 v-bind 指令来修饰href属性,表明它的值是一个动态的值,对应的则是data中的link的值:http://hello.com.
来吧,看看渲染效果:
标签的href的值成功地解析渲染成:http://hello.com。
第六节也说过, v-bind 指令可以简写成一个冒号“:”,也就是以下两种写法是等价的。
hello官网
hello官网
它们的解析渲染效果是一样一样的。
8. v-on 指令
v-on 指令相当于绑定事件的监听器,绑定的事件触发了,可以指定事件的处理函数,记性好的同学应该记得我们在第四节介绍methods选项的时候,有用到 v-on 指令。(估计你也不记得了),这里我们还是配合methods来演示:
methods选项的用法不再展开讲解,还不理解的同学可以翻看第四节《定义一个vue实例常用的4个选项》
回到这个例子,我们通过 v-on 指令修饰click点击事件,指定事件响应后的处理函数为methods中的say( )方法,我们渲染看看效果:
点击按钮,可以成功触发click事件,并且调用say( ),一切都在我们的预期之中。
此外,如果你想给处理程序say( )传参数,也是可以的,用法跟普通的方法一致。
我们再上一个案例的基础上稍微修改代码,say(name)接受一个参数name,并把name打印出来,在调用的时候传如实参“Tom”。再看看效果,是不是在我们的预期之内:
“hello,Tom”被打印出来了,一切尽在掌握之中,感觉真好。
9. v-model 指令
这是一个最重要最常用的指令,一般用在表单输入,它帮助我们轻易地实现表单控件和数据的双向绑定,相对以前的手动更新DOM,简直就是开发者的福音,迫不及待地来看看它的用法:
你输入:{ { msg }}
只要给input控件添加 v-model 指令,并指定关联的数据msg,我们就可以轻松把把用户输入的内容绑定在msg上。我们把msg的内容显示出来,看是不是跟用户输入的内容是同步更新的:
是不是比你手动更新DOM爽多了,是不是感受到了vue的MVVM带来的快感?
- v-once 指令
最后,我们再来讲解一下v-once指令,它的特点是只渲染一次,后面元素中的数据再更新变化,都不会重新渲染。
我们再上面的案例代码中稍做修改,仔细看改了哪里:
你输入:{
{ msg }}
修改1:
标签增加了 v-once 指令;
修改2:msg的初始值不再是空字符串。我们来看看效果:
由于msg有了初始值,第一次渲染的时候,input控件和
标签都有了内容,由于
标签我们添加了 v-once 指令,所以,后期我们更新msg的值的时候,
标签的内容不会发生改变,也是符合我们的预期。
第九节:掌握vue的另一个核心:组件
组件是我们人为地把页面合理地拆分成一个个区块,让这些区块更方便我们重复使用,有了组件,我们可以更高效合理地开发和维护我们的项目。
竟然说得组件那么好用,那我们就来好好学学怎么使用它。
规划组件
假设我们页面上有这样的一个布局:
上图是我们模仿微信公众号的“历史消息”的界面,我们看到的是一个文章的目录列表。
这种情况下,我们把每一个文章标题区块看作一个组件来进行规划,这样就方便我们去复用这个组件:
实现组件
我们学会了如何规划出一个组件,接下来,我们看看在vue中如何实现一个组件。
我们用传统的实现方式一个组件,html代码如下:
这里是文章的标题
2017年4月10日
原创
忽略css(这里我们不介绍css),我们看到了上面html代码结构,class为unit的
容器以及它的子孙节点组成了我们的组件。在vue组件中,这些代码将作为我们组件的模板template。
什么意思?我们来看看vue如何实现一个组件的。
首先,我们还是先创建一个vue实例,很熟练了,没难度。
成功创建了一个vue实例vm,挂载元素为id为app的div节点。
接下来,我们在创建实例vm之前,利用vue提供的API来注册一个组件。稍微修改一下上面的代码:
我们使用了vue提供的全局API Vue.component() ,注册了一个名为:“my-article”的组件,而组件的template正好是我们上面的html代码,这样,我们就可以用 my-article> 的方式来使用我们的组件。
注意:一定要确保实例vm在创建之前, 组件已经被成功注册,这也是为什么我们要把代码写在实例化之前。
既然注册了组件 ,我们就来使用这个自定义的组件:
我们看看渲染的结果:
我们看到最终渲染的不是标签,而是我们组件的模板template的值。我们成功地注册一个自定义的组件并使用它。
但这并不够,我们有的文章目录中不仅仅只有一篇文章,而且每篇文章的标题和日期都不一样,我们如何动态地展示它们的数据呢?
这里就涉及到了组件的传参props,没错,不但函数可以接受参数,vue的组件也可以。接下来,我们看看怎么实现传参。
我们知道,组件中的这4部分是需要动态获取数据的:标题,发布日期,是否原创,文章封面图。
那么,我们就通过传参的方式把这些数据传到组件,实现数据动态展示。
首先,我们把数据存储在实例vm的data中:
let vm = new Vue({
el:"#app",
data:{
article:{
title:"第一节:Vue.js框架是什么,
为什么选择它?",
date:" 2017年03月06日",
is_original:true,
cover_url:"cover.jpg"
}
}
});
我们给data增加了一个文章article的信息,包括:标题title,发布日期date,是否原创is_original,封面图片cover_url。
文章的信息有了,我们怎么传到组件中去呢?
就像一个函数传参一样,你可以把detail理解成一个形参,article相当于实参。
我们给组件传了参,组件内部怎么接受并使用呢?我们接着看,十分简单!
我们把注册组件的代码稍微修改一下:
Vue.component('my-article',{
props:['detail'],
template:`
{
{detail.title}}
{
{detail.date}}
原创
`
});
除了template以外,我们增加了props,通过它来接受我们的参数detail,传进来之后,你可以在组件的模板template中使用它所接受的所有数据了。比如,我们传进来的数据包含着文章的信息:title,date,is_original,cover_url。
读取文章的标题:
{ {detail.title}}
读取文章的发布日期:
{ {detail.date}}
读取文章是否原创,并通过 v-show 指令控制显示/隐藏:
原创
读取文章的封面图片地址:
竟然读取了数据,我们就看看渲染结果:
数据是动态读取了,那么我们的目录并不仅仅只有一篇文章,当我们数据多了之后,该用什么方式展示出来呢?
let vm = new Vue({
el:"#app",
data:{
articles:[
{
title:"第一节:Vue.js框架是什么,
为什么选择它?",
date:" 2017年03月06日",
is_original:true,
cover_url:"cover.jpg"
},
{
title:"第二节:简易安装 和
快速入门Vue.js",
date:" 2017年03月09日",
is_original:true,
cover_url:"cover.jpg"
},
{
title:"第三节:创建一个Vue实例,
超简单",
date:" 2017年03月17日",
is_original:true,
cover_url:"cover.jpg"
},
{
title:"第四节:定义一个vue实例的
4个常用选项",
date:" 2017年03月20日",
is_original:true,
cover_url:"cover.jpg"
},
]
}
});
假设我们的articles中有4篇文章的信息。
也许你已经相当到了,我们可以使用 v-for 指令,它是专门用于处理列表渲染的指令。结合我们的组件,一起来实现这个文章目录的效果。
非常简单,组件我们已经封装好,我们只需要给它传参即可,所以我们不需要改动组件的代码。而articles是一个数组,我们用 v-for 指令对它进行遍历即可。
我们对html代码稍微改动一下:
这就是父组件→子组件通信的实现,那么,你可能会联想到,如果是子组件向父组件传递数据,要怎么实现呢?
子组件→父组件
接下来,我们就学习子组件→父组件通信。
相比父→子组件通信,子→父组件就稍微繁琐一点。我们会使用到组件的一个知识点:自定义事件。
网页事件我们听得多,常用到的有click点击事件,focus聚焦事件等等,事件要怎么自定义呢?
每一个vue实例都实现了事件接口,我们可以用它提供的API $emit( eventName)来触发一个事件。
是不是听得还是有点云里雾里的?我们来演示一下:
我们注册一个新组件:
Vue.component('son',{
template:``,
methods:{
send(){
this.$emit('connect');
}
}
});
复制代码
很简单的一个组件,就是一个按钮button,点击它的时候,会触发组件内部的send( )方法,而方法体里面会触发一个事件,事件名取名为:“connect”。
后我们就去父组件监听这个事件‘connect’,监听方式跟普通原生的事件一模一样,也是用 v-on 指令,缩写用@符号。 我们采用缩写来监听:
const app = new Vue({
el:"#app",
methods:{
say(){
console.log(`大家好,我监听到了
事件connect的触发`);
}
}
});
复制代码
我们在say( )方法触发的时候,在控制台打印一句话,表示我们自定义的事件connect成功触发,并被父组件监听到了。
我们看到了,点击子组件的按钮,成功地调用了父组件的say( )方法,十分顺利。
来到这里,其实我们已经完成了一大半。我们最后只需要把子组件的一些数据,通过这个事件connect传递到父组件,就可以实现子→父组件的通信。
我们修改一下子组件:
Vue.component('son',{
template:``,
data(){
return{
msg:'大家好,我是子组件的数据'
}
},
methods:{
send(){
this.$emit('connect',this.msg);
}
}
});
复制代码
我们把子组件的data中的msg,通过$emit()一并发射出来,在父组件的say( )方法接收即可。
methods:{
say(msg){
console.log(msg);
}
}
复制代码
最后还是确认一下是否真的可以读取到子组件出来的msg,看效果图:
这就成功地实现了子→父组件的数据传递。
非父子组件通信
除了父子组件的相互通信,非父子关系的组件该如何通信,我们可以巧妙地利用一个空的vue实例来作为一个中央事件总线。
但是在实际开发中,我们不会这么做,我们会使用专门用于状态管理的 vuex , vuex 的学习我们不在基础系列讲解,我们放在后期的进阶系列再一起学习。
在第六节的章节中,我们学会了如何给视图上的html标签绑定属性。
比如,给 标签绑定href属性,简单回忆一下:
复制代码
我们用 v-bind 指令(以后都用缩写的形式)来动态绑定一个标签的属性。
而这一节,我们特意来学习一下样式的动态绑定,因为它与普通属性的绑定略有不同,并且在实际开发中,动态绑定样式是一定会用到的知识,所以,还是值得我们用一个章节来学习一下它。
老办法,我们先来准备一个vue实例:
这是文字
复制代码 绑定class
对象语法:我们动态绑定的class的值是一个对象{ },具体怎么写我们来看看,在上面的代码上稍做修改:
这是文字
复制代码 我们看到给class绑定的是一个对象:{ ‘active’ : isActive },isActive是我们vm实例的数据,值为true,这与我们平时看到的class是一个字符串值不一样,这种写法,最后会被渲染成什么样呢? 我们运行看看渲染后的效果:
咦?class的值最后被渲染成:“active”,原来,在对象中,若该属性对应的value为true,则该属性会被渲染出来,为false,则被渲染出来。
我们尽快验证一下,我们在上面的代码上再稍作修改:
这是文字
复制代码
我们给class绑定的对象多了2个key和value,我们看看实例的数据data:
data:{
isActive:true,
isDanger:true,
isError:false
}
复制代码
isActive和isDanger的值都为true,isError都为false,猜一下,渲染出来的结果是什么?
看效果:
正和我们所预测的一样,值为true的会被成功渲染出来,为false的则不会被渲染出来。这个时候,你就可以根据需要给渲染出来的class编写样式了。
一旦vm实例对应的数据发生变化,比如isActive的值由true变成false,视图上的’active’ 类也会被删除,这样就会实现动态绑定样式啦!
除了对象语法来绑定class之外,我们还有另一种写法。
数组语法:用数组语法和对象语法来绑定class,又稍有不同。说了是数组语法,那写法就肯定不一样,我们继续来看看:
这是文字
复制代码 这个时候,class绑定的值就是一个数组了,数组有两个元素[ activeClass , errorClass ],它们对应的值是vm实例的数据data,我们看看vm的数据data:
data:{
activeClass:‘active’,
errorClass:‘error’
}
复制代码
渲染的时候,activeClass和errorClass对应的值就会被渲染成class。看效果图:
效果跟我们预期一样。这样,我们就可以修改vm实例的数据data,来实现动态修改class的样式了。
绑定内联样式style
除了使用class类以外,我们还可以在style内联样式上下功夫。
绑定内联样式也有2种语法,对象语法和数组语法,但我们这里只介绍常用的对象语法。
这是文字
复制代码 这个时候,我们绑定的就不是class了,是style属性。它的值是一个对象:{ color:colorStyle },同样,我们来看看vm实例的数据data: data:{ colorStyle:'red' } 原来colorStyle我们vm实例的数据,值为red。那是不是我们style中的color对应的颜色是就是red呢?
没错,看来你已经会举一反三了。 看渲染效果,我们验证一样:
学过了前面11个章节的知识,可以说你已经对vue2.0的基础知识有了一定程度的掌握,虽然在真正开发过程中,一些知识的使用会稍有不同,但是别慌,我们会把那部分内容在进阶系列,比如:单文件组件,过渡效果,状态管理vuex,路由vue-router,网络请求vue-resource等等。
那是不是就意味着我们现在还不能用基础知识做开发,当然不是,加强动手能力是进步的最好方式,我们今天就来用学过的基础知识,来动手做一个demo:todoList案例,以此来巩固一下学过的知识,并且练练手。
看一个todo案例的效果图,然后我们来模仿它做一个:
(gif图,加载需要一丢丢时间)
本来是打算录制成视频,但是demo相对容易,通过图文并茂的形式也能让大家很好的接收,倘若后期有需要视频的反馈,我再尝试录制成视频的形式。
如果你还没看完前面的11个章节,建议你先学习,否则欲速则不达。
磨刀不误砍柴工,在动手之前,我们理一下思绪该如何实现:
1.利用vue的mvvm的特性,绑定用户输入的内容和展示在列表的内容。
2.用户勾选表示已完成,通过动态修改样式来标识已完成。
3.用户点击按钮“delete”,通过v-show来控制任务隐藏。
通过这个思路,我们就可以把之前11个章节的部分内容串联起来,运用到这个案例中。
来吧,开始准备我们需要的工具:
chrome浏览器,或者一个支持ES5的Object.defineProperty特性的浏览器即可。
webstorm2017 ,我选用它的原因是因为webstorm2017增加对vue的完美支持,当然,如果你的电脑跑不起,或者不习惯,你也可以使用你喜欢的IDE。
安装vue.js
这里我用第二节的简易安装方式,并且是直接下载vue.js文件到本地,非cdn资源文件。
先看看目录结构,十分简单:一个todo.html,一个本地的vue2.0.js。
在head中,载入vue.2.0.js文件。
任务列表 复制代码 成功载入之后,我们就可以来编写代码了。 创建vue实例
利用第三节的知识,创建一个vue实例,超简单!
复制代码 顺利地创建了一个vue的实例app! 数据绑定
接下来,我们就实现思路的第一步:数据绑定。
在绑定之前,我们来设计关于任务的数据结构,一个任务包括:任务内容,是否完成,是否删除。
因此,我们可以得到一个完成的任务数据结构:
{
content:“任务内容”,
finished:false,//是否完成
deleted:false//是否删除
}
复制代码
那么,我们给实例的data添加代码:
const app = new Vue({
el:"#app",
data:{
//默认
task:{
content:’’,//内容为空
finished:false,//未完成
deleted:false//未删除
}
}
});
复制代码
默认初始化任务task的内容content为空,finished状态为false表示未完成,deleted状态为false表示未删除。
任务task的数据结构有了,我们就把它和页面的用户输入关联起来,还记得使用哪个指令吗?(花5秒钟时间回忆一下)
接着,我们就来写html代码:
复制代码 通过v-model指令,就可以成功地绑定task的content,用户在输入的同时,实例app的data也会实时地更新自身的数据。 我们通过控制台检验一下是否成功地绑定了:
(gif效果图,加载需要一丢丢时间)
虽然成功地绑定了task的content,但是我们的input没有添加样式,缺少美感,我们来给它添加class类“edit”和相关的样式。
.edit{
display:block ;
width:80%;
height: 35px;
line-height: 35px;
margin: 30px auto;
box-sizing: border-box;
padding-left: 4px;
border-radius: 4px;
border:1px solid #ccc;
outline: 0;
box-shadow: 0 0 5px #ccc;
}
复制代码
给input控件添加以上的css样式,它的外观就变成我们想要的效果:
用户不停地输入多个任务,我们要用一个数组list[ ]来存储用户输入的每一个任务task。
按键修饰符
假设:用户输入任务内容后,按下enter键表示完成输入。所以,我们要实现监听键盘事件。
这里我们会用到vue提供给我们的按键修饰符:
在监听键盘事件时,我们经常需要监测常见的键值。Vue允许为 v-on 在监听键盘事件时添加按键修饰符。
所以,我们给input控件添加键盘事件keydown的监听,最终代码如下:
复制代码
我们增加了@keydown.enter表示监听键盘中的enter键的按下事件,而addTask则是实例app中的methods方法,所以,我们也会给实例增加methods。如下:
const app = new Vue({
el:"#app",
data:{
//默认
task:{
content:'',//内容为空
finished:false,//未完成
deleted:false//未删除
}
},
methods:{
//添加任务
addTask:function(){
//.....
}
}
});
复制代码
接下来,我们就来编写addTask( )方法,实现将用户输入的内容存储起来,因为我们在之前就通过 v-model l将用户输入的内容和task中的content关联起来,所以我们只需要把task.content存储起来就可以了,存在哪里呢?我们用一个数组list[ ]来存储它们。如下:
const app = new Vue({
el:"#app",
data:{
//默认
task:{
content:'',//内容为空
finished:false,//未完成
deleted:false//未删除
},
//任务列表
list:[]
},
methods:{
//添加任务
addTask:function(){
//将task存入list数组
this.list.push(this.task);
//存入list[]后,重置task
this.task = {
content:'',//内容为空
finished:false,//未完成
deleted:false//未删除
}
}
}
});
上面的代码,我们给data增加了list,并且通过push方法,成功地把每个任务存放在list数组中。
任务列表list数组既然有了,我们就可以通关 v-for 循环,把它遍历并展示出来了。那我们就来编写列表的html代码,如下:
{ {item.content}}
有html还不够,加上css样式: .list{ margin: 0 auto; width:80%; } .unit{ position: relative; padding: 10px 0; border-bottom: 1px solid #efefef; } .unit:last-child{ border-bottom: 0; } 样式也加上了,我们来看看通过按下键盘enter键添加的任务,能否成功地展示在任务列表上,演示一下:
(gif效果图,加载需要一丢丢时间)
我们输入任务,并按下回车键,任务内容成功地添加到了list[ ]数组,并通过 v-for 遍历到页面上,十分顺利。
动态修改样式
但我们的工作还没结束,案例中,当勾选框被选中的时候,表示任务已完成,切换相应的样式,未选中的时候,表示任务未完成,也会切换样式。
接下来,我们就来实现这一步,我们用到了第十一节的动态class绑定的知识。
首先,我们先为每个checkbox绑定点击事件,并且动态渲染是否选中,稍微修改上面的代码:
@click=“changeState(index)”
:checked=“item.finished”
type=“checkbox”
点击checkbox,我们通过编写一个changeState( )方法来实现切换该任务的状态,所以我们来编写一下changeState( )方法:
//点击修改任务状态
changeState:function(index){
let curState = this.list[index].finished;
this.list[index].finished = !curState;
}
就这样,我们就顺利地实现了点击checkbox来修改每个任务task对应的状态finished(切换true或者false)。
既然修改了状态,我们就要在页面上看到相应的效果,我们通过动态的修改class来实现。
我们把这行代码:
{
{item.content}}
修改成:
{
{item.content}}
学习过第十一节我们知道,当改任务的finished为true的时候,就会添加样式 class=‘finish’ ;否则则不会。
所以,少不了finish的样式类代码:
.finish{
text-decoration: line-through;
color: #ccc;
}
好了,所有代码都准备好了,演示一下效果:
(gif效果图,加载需要一丢丢时间)
切换是否成功状态也成功了实现了。
删除任务
还差最后一步,我们来实现删除任务,当我们编写错误的任务的时候,就可以点击删除按钮来删掉它。
我们先为每个任务添加删除按钮,并添加点击事件:
(gif效果图,加载需要一丢丢时间)
删除任务的功能也顺利实现了。
为了稍做完善,当我们没有任何任务展示的时候,我们会在页面上显示“暂无任务”的文字提示。这样的提示对用户体验来说会比较友好一点。
我们增加html代码,如下:
暂无任务
css样式,如下: .empty{ font-size: 13px; color: #ccc; text-align: center; padding: 10px 0; } 那么,我们如何控制这个提示是否渲染呢?这里就用到了我们学过的 v-if 条件渲染指令,当我们的list[ ]数组的长度为0的时候,表示无任务,可展示“暂无任务”,反之则不渲染。 那好,我们就用v-if指令来稍做修改html代码:
暂无任务
我们在之前的章节说过,绑定数据的时候,可以使用简单的javascript表达式,上面的案例,我们就使用了简单的全等判断,你也可以使用计算属性computed来实现,留给大家自己动手去实现。
Vue中$符号的含义:
1:除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。例如:
var data = { a: 1 }
var vm = new Vue({ el: '#example', data: data}
)vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})
表示为变量
可以用来表示变量,比如变量 var s='asdsd’或var s = ′ a s d a s d ′ ; e s 6 中 也 可 以 采 用 s='asdasd'; es6中也可以采用 s=′asdasd′;es6中也可以采用{XXX}来在字符串中插入变量(这个记住要利用v-bind)