每一个Vue程序都要进行实例化以后使用,实例有两种。javascript
对于M-V-VM模型,由M-V-C模型衍生。css
只不过M-V-C中的C在M-V-VM中变为了VM。在M-V-VM中VM就是逻辑操做。经过VM,咱们去控制视图和数据之间 的变化。html
构建一个Vue实例逐步解析vue
//建立一个Vue实例 var vm= new Vue(); -->这个Vue实例就是VM //挂载一个DOM元素,做为数据展现的容器 -->这个el选项就是V var vm =new Vue({ el:'#XXX' }) //设置一个data选项,做为一个对象,只保存数据,而且其属性被Vue实例代理。 -->这个data对象就是M var vm =new Vue({ el:'#Name', data:{ key:value, ..... } })
每一个Vue实例都是经过构造函数Vue建立一个Vue的根实例java
var vm = new Vue({ //options })
在实例化Vue时,须要传入一个选项对象,它能够包含数据
(data),模板
,挂载元素
(el),方法
,生命周期钩子
等选项。web
Vue就是用选项对象中的data,created...等选项,来建立你想要的行为。这些选项能够在Vue中的API文档查看。express
能够扩展
的Vue构造器,从而用预约义
选项建立复用
的组件构造器
数组
//定义一个组件构造器 var myComponent =Vue.exted({ //扩展选项 }); //全部的 myComponent的实例都将以扩展的组件构造器建立 var mycomponentExp=new myComponent(); //mycomponentExp是一个组件
因此咱们如今知道,全部Vue.js组件都是被扩展的Vue构造器的实例浏览器
//html代码 <div id="app"> <p>{{name}}</p> </div> //javascript代码 var vm = new Vue({ el: '#app', data: { name: 'huang' } });
经过上面的代码思考,为何能够在视图中直接使用name属性?app
每一个Vue实例都会代理其选项对象中data对象的全部属性。
这就关于Vue的另外一个概念,数据代理
所谓数据代理(另称数据劫持),指的是在访问或修改对象的某个属性时,经过一段代码拦截这个行为,并进行额外的操做或者返回修改结果。比较典型的是Object.defineProperty()
和E2015的Proxy
对象。
对于数据劫持,最著名的应用就是双向绑定。
Vue2.x中使用的就是Object.defineProperty()
(Vue 3.x改用Proxy
进行实现)
这里只做大概了解。
详细: 参考末尾连接
因此,Vue实例经过数据劫持,代理data对象的属性。咱们能够经过Vue实例来访问data对象中的属性。
上面的代码完整写法
//html代码 <div id="app"> <p>{{this.$data.name}}</p> //经过vm.$data访问源数据 <p>{{$data.name}}</p> //上一种的简写 <p>{{this.name}}</p> //与上等价,Vue实例代理data属性 <p>{{name}}</p> //上一种的简写 </div> //javascript代码 var vm = new Vue({ el: '#app', data: { name: 'huang' } }); //注1:this指向的是挂载在该元素的或是该元素的祖先元素的Vue实例。这里指向vm //注2:data对象中,以$或_开头的属性不会被Vue实例代理,由于它们是Vue定义私有属性的写法可能和 Vue 内置的属性、API 方法冲突。能够经过$data.privateName来访问这些属性 //注3:privateName就是$,_ 开头的属性。
注意:只有这些被实例代理的属性是与视图响应的,代理的属性变化,源数据也会发生变化。同理,源数据变化,代理的属性也会变化
若是是实例被建立后添加新属性给实例,它是不会触发视图更新的。
//html代码 <div id="app"> <p>{{name}}</p> </div> //javascript代码 var mydata = { a: 1, name: 'huang' } var vm = new Vue({ el: '#app', data: mydata }); //视图响应数据,发生变化。代理属性改变,mydata对象name属性也改变 vm.name = 'new'; //建立Vue实例后给实例添加属性,视图对其无响应 vm.age = 22;
指令(Directives)是带有v-前缀的特殊属性。指令属性的值预期是Javascript表达式 (这点很重要 !)v-for例外。
借助尤雨溪的话:基于指令的数据绑定使得具体的DOM操做都被合理地封装在指令定义中
简单来讲,指令的指责就是当其表达式的值改变时相应地将某些行为应用到DOM上。
只须要将指令做为html元素的属性来使用就能够了,
例如:
<div v-if="expression">
指令只对当前所在的这个元素起做用,它在哪一个元素上,就对哪一个元素作出对应的DOM操做。
我更愿意将指令的值叫作指令的"表达式",为何这么说?
例如:
<div v-if="expression">
expression在模板中所对应的是this.expression
眼熟吗?这就是Vue实例代理data的属性。
既然是表达式,那么就必定会有返回值
它的值被传给指令,指令根据表达式返回的结果来决定所在的元素进行怎样的操做。
而表达式的变量
,都来自Vue实例代理的data选项的属性。
v-if:依照起Value
是否为Truthy来决定是否渲染此元素
<div v-if="expression"> {{...}} </div>
若是this.expression值为真,元素则被插入到Dom中,this.expression为假,则当前元素会从Dom中移出。
当咱们有多个元素须要用同一个判断怎么办?
<div v-if="expression"> ..... </div> <p v-if="expression"> ..... </p>
这种写法,有些繁琐。咱们能够用<template>标签,根据元素的株连性
把这个标签做为父元素,操做这个元素,而且此元素在渲染后不会影响到页面结构。
<template v-if="expression"> <div> ..... </div> <p> ..... </p> </template>
v-show:依照起Value
是否为Truthy来决定改变其Css的display属性值。
和v-if
在页面上的效果相同,都是决定元素是否显示,可是二者的渲染方式不一样。
v-if
在初始渲染时条件若为假,则什么也不作,直到第一次条件为真,才会渲染元素并将其插入DOM中
v-show
无论初始条件是什么,都会对元素进行一次初始渲染,在接下来的操做中,就是Css的切换。
那么,咱们知道,移除元素会致使DOM树变化,产生一次回流(reflow)
,它会从新计算样式和渲染DOM树。
而改变Css属性这类值改变某个节点的一些样式,只会引起重绘(repaint)
,只会绘制这个元素。
这么一对比,v-if频繁切换对浏览器性能开销影响更大,因此建议在运行时,若是条件的Truthy
频繁的切换,则咱们应该优先考虑v-show。而运行时条件不多改变,我更以为是条件锁死
,v-if的Truthy为false时,则更推荐v-if,由于它没有初始渲染开销。
v-else:v-if的else语句块,当v-if的expression的值为Truthy,则执行v-else指令,将元素渲染在页面上,不然,不渲染。
使用注意:必须紧跟在v-if后,不然不会有任何做用
v-for:指令基于源数据重复渲染该元素或模板块。
数组迭代: 用 v-for
指令根据一组数组的选项列表进行渲染
支持第二个参数为当前项的索引
语法:
v-for="(every, index) in expression"
every
:能够用任意名字,表示迭代的数组元素的别名,能够用这个别名访问数组元素
index
:任意名称,表示迭代的数组索引的别名,能够用这个别名访问数组索引
expression: 要迭代的源数据数组
实例:
<div v-for="i in arr"> {{i}} </div> var vm = new Vue({ el: '#app', data: { arr: [{ name: 'li' }, { name: 'huanghao' }, { name: 'wang' }] } })
对象迭代:v-for
经过一个对象的属性来迭代
还能够有两个额外参数,第二个参数为键名,第三个参数为索引(这个索引更像是for循环的 i)
语法:
v-for="(value, key, index) in object"
value:任意名称,表示迭代的对象属性值的别名,能够用这个别名访问对象属性值
key:任意名称,表示迭代的对象的键值的别名,能够用这个别名访问对象键值
index:任意名称,表示迭代的对象的索引的别名 ..
object:要迭代的源数据对象。
实例
<div id="app"> <div v-for="(value,key1,index1) in obj"> {{value}} --{{key1}} ---{{index1}} </div> </div> var vm = new Vue({ el: '#app', data: { obj: { name: 'huang', age: 22, sex: 'man' } } })
在v-for
块中,拥有对父做用域属性的彻底访问权限,v-for块中,其内部
的模板语法,能够将v-for块中别名做为变量使用
绑定型指令会有参数,参数是绑定的属性或事件。
v-bind:
绑定一个属性
语法: v-bind:prop="expression
"
prop:绑定的属性
expression:表达式
v-bind绑定一个属性,若是expression的值为真,则表达式的值
被添加到绑定的属性上,不然不被添加
以一个<img>元素的src属性举例
<img alt="" :src="src"> // <img alt="" :src="1.img"> new Vue({ el: '#app', data: { Src:'1.img' } });
v-bind绑定了一个src属性,而且属性值为 this.Src,当表达式的值为真时,src属性的属性值就是this.Src
v-bind绑定class和style有些特殊,可使用对象和数组形式绑定
绑定html元素的class
对象语法:
语法: v-bind:class="{className:expression,className2:expression2...}"
计算expression是否为Truthy,若是为真,则className/className2将被添加到class属性中,不然不会添加.
也能够直接绑定data选项中的一个对象
<div id="app" :class="classObject"></div> var app = new Vue({ el: '#app', data:{ classObject: { active: true, 'text-danger': false } } })
或者绑定一个返回对象
的计算属性
<div id="app" :class="classObject"></div> var app = new Vue({ el: '#app', data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal', } } } })
数组语法:和对象语法有不一样,它添加的类名是被实例代理的data对象中的属性的属性值,而且此属性值必须的字符串。
例子
<div v-bind:class="[app,cls]" //<div class="sss"></div> > new Vue({ el: '#app', data: { cls:"sss", app:true } });
为了更加方便,还能够在数组中使用对象语法,对象语法在模板中照常解析
例子
<div v-bind:class="[app,cls,expression]" //<div class="sss active error click"></div> > new Vue({ el: '#app', data: { name: '黄昊', src:'1.img', expression:{ active:"class1", error:'class2', click:789 }, cls:"sss", app:true } });
关于绑定style
对象语法: v-bind:style="{style1:expression,style2:expression2}"
style1/style2:为style属性添加的样式名
expression/expression2:表达式的值必须为字符串,数字例外。表达式的值符合样式属性。
举例
<div :style="{color:'red'}" //<div style="color: red;"></div> > </div> //上方等同下方 <div :style="{color:red}" > </div> new Vue({ el: '#app', data: { red:'red', } });
或者为了让模板更加清晰,咱们直接给定一个对象表达式
举例
<div :style="styleObject" ///<div style="color: red; font-size: 16px;"></div> > </div> new Vue({ el: '#app', data: { styleObj:{ color:'redd fontSize:'16px'//样式按照Js的写法,由于咱们一切模板语法的操做都是基于挂载的Dom对象 } } });
数组语法:将多个样式对象应用到同一个元素上
须要注意的是,数组语法中的元素必须是对象形式。
例子:
<div :style="[styleObj,styleObj2]" > </div> new Vue({ el: '#app', data: { styleObj:{ color:'red', fontSize:'16px' }, styleObj2:{ width:'100px', height:'100px' } } });
在Vue2.3.0+,style绑定的属性提供一个包含多个值 的数组,经常使用于提供多个带前缀的值
例子
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex','inline','a'] }"></div> //<div style="display: inline;"></div>
这样写只会渲染数组中最后一个被浏览器支持的值
咱们经过computed
选项来添加计算属性
对于任何复杂的逻辑,都应该使用计算属性
当咱们在computed声明一个计算属性时,咱们提供的函数将用做vm.computed_prop的getter函数 当计算属性被调用时,触发这个函数执行。
怎么使用?vm.computed_prop 简化--->computed_prop
组件化思惟
组件化针对的是页面中的整个完整的功能模块划分 (项目的分工)
组件的概念( 一个文件 )
组件是一个html、css、js、image等外链资源,这些部分组成的一个聚合体
优势:代码复用,便于维护
划分组件的原则:复用率高的,独立性强的
组件基础:
vue.js文件中暴露出一个Vue的构造器函数, 这个函数的做用,是用来实例化出来一个实例, 这个实例也是一个组件, 咱们称之为 '根实例'
Vue为了扩展功能, 给了一个方法 , 这个方法叫 extend Vue.extend()
组件的表现形式是标签
使用组件必须遵照H5的标准,组件须要合法,必须注册组件。
组件使用前必须注册
组件的注册
全局注册
局部注册
在使用组件时,要注意会不会与原有的标签冲突