目录
五、class、style绑定 1、绑定HTML class 2、绑定内联样式
一、概述
库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。如从Jquery切换到Zepto,从EJS切换到art-template。
框架:是一套完整的解决方案,对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目。如node中的express。
(1)什么是Vue.js
Vue.js和Angular.js、React.js称为前端三大主流框架。
Vue.js是一套构建用户界面的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。
(2)为什么要学习流行框架
企业中,使用框架,能够提高开发的效率。提高开发效率的发展历程:原生JS -> Jquery之类的类库 -> 前端模板引擎 -> Angular.js / Vue.js。框架能帮我们减少不必要的DOM操作;提高渲染效率;双向数据绑定的概念(通过框架提供的指令,前端程序员只需要关心数据的业务逻辑,不再操作DOM元素)。
(3)MVC和MVVM
MVC是后端的分层开发概念,Model处理数据的CRUD,View视图层页面,Controller业务逻辑层。
MVVM是前端视图层的概念,主要关注于视图层分离,把前端的视图层分为Model、View、ViewModel。
二、安装
下载后用<script>引入,Vue被注册为一个全局变量。在开发环境下使用vue.js,不要使用压缩版本vue.min.js,否则失去所有常见错误相关的警告。
<script src="lib/vue.js"></script>
三、基本代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue</title>
<!-- 1.导入Vue的包 -->
<script src="lib/vue.js"></script>
</head>
<body>
<!-- Vue实例控制这个元素中的所有内容 -->
<div id="app">
<p>{{ msg }}</p>
</div>
<script>
// 2.创建一个Vue实例(导入包后,在浏览器内存中,多了一个Vue构造函数)
// VM:new出来的vm对象,就是MVVM中的VM调度者
var vm=new Vue({
el:'#app', // 表示当前这个Vue实例,要控制页面上的哪个区域
// M:data就是MVVM中的M,专门用来保存每个页面的数据
data:{ // data属性中存放el中要用到的数据
msg:'欢迎学习Vue' // 通过Vue提供的指令,很方便的就能把数据渲染到页面上,不再手动操作DOM元素
},
methods:{ // methods对象存放自定义的方法,如需访问data中数据,使用this
}
});
</script>
</body>
</html>
实例的生命周期钩子
从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的函数,给用户在不同阶段添加自己的代码的机会,这些函数称为生命周期钩子。
创建期间的生命周期函数:
+ beforeCreate:初始化一个空的Vue实例对象,还未初始化data和methods属性
+ created:实例已在内存中创建好,data和methods已初始化,还没有开始编译模板
+ beforeMount:完成了模板的编译(将Vue代码中的指令编译为模板字符串,渲染成内存中的DOM,页面中的元素未被替换),但未挂载到页面中
+ mounted:已将编译好的模板挂载到了页面指定的容器中显示,可以操作DOM元素了
运行期间的生命周期函数(当data发生改变):
+ beforeUpdate:状态更新前执行此函数,data中的状态值是最新的,但是界面上显示的数据是旧的
+ updated:重新渲染内存DOM树和挂载到页面后调用此函数,data中的状态值和界面上显示的数据都已经完成了更新
销毁期间的生命周期函数:
+ beforeDestroy:实例销毁之前调用,此时实例仍然完全可用(data、methods、指令、过滤器等)。
+ destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
<body>
<div id="app">
<h3 id="h3">{{msg}}</h3>
<button @click="msg='hsg';">修改data中的msg为"hsg"</button>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'I love you'
},
methods:{
show(){
console.log('执行了show方法');
}
},
beforeCreate(){
console.log(this.msg); // undefined
this.show(); // 报错
},
created(){
console.log(this.msg); // I love you
this.show(); // 执行了show方法
},
beforeMount(){
console.log(document.getElementById('h3').innerHTML); // {{msg}}
},
mounted(){
console.log(document.getElementById('h3').innerHTML); // I love you
},
beforeUpdate(){
console.log('data中的数据:'+this.msg); // hsg
console.log('界面上元素内容:'+document.getElementById('h3').innerHTML); // I love you
},
updated(){
console.log('界面上元素内容:'+document.getElementById('h3').innerHTML); // hsg
}
});
</script>
</body>
四、插值
插值表达式:只替换自己的占位符,不会把整个元素的内容清空;有闪烁问题。
v-text:覆盖元素中原本的内容;默认没有闪烁问题。
v-html:解析添加至元素的html代码,且会覆盖元素中原本内容。
v-cloak:解决插值表达式闪烁的问题。如果vue.js插在body底部,且网速较慢,会先显示未解析的插值表达式。在<style>标签中添加[v-cloak]{display:none;}隐藏含插值表达式的元素,解析完成再显示。
v-bind:缩写是:,用于绑定属性,其中可以写合法的JS表达式。
<body>
<div id="app">
<p v-cloak>----{{msg}}----</p>
<p v-text="msg">====</p>
<p>{{msg2}}</p>
<p v-text="msg2"></p>
<p v-html="msg2">1212</p>
<button v-bind:title="mytitle+'123'" v-on:click="show">按钮</button>
<button :title="mytitle+'123'" @click="show">按钮</button>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'欢迎学习Vue',
msg2:'<h1>我是h1</h1>',
mytitle:'自定义的title'
},
methods:{ // 定义了当前Vue实例中所有可用的方法
show:function(){
alert('Hello');
}
}
});
</script>
</body>
五、class、style绑定
1、绑定HTML class
class需要使用v-bind做数据绑定。
数组语法:直接传递一个数组。数组中可以使用三元表达式,但为了提高代码的可读性,在数组中使用对象来代替三元表达式。
对象语法:直接使用对象与class绑定。对象的属性是类名,可带也可不带引号;属性的值是一个标识符。
<style>
.red{color:red;}
.thin{font-weight:200;}
.active{letter-spacing:0.5em;}
</style>
<body>
<div id="app">
<h1 class="red thin">这是一个h1</h1>
<h1 :class="['red','thin']">这是一个h1</h1> <!--数组语法-->
<h1 :class="['red','thin',flag?'active':'']">这是一个h1</h1>
<h1 :class="['red','thin',{active:flag}]">这是一个h1</h1>
<h1 :class="{red:true,thin:false,active:flag}">这是一个h1</h1> <!--对象语法-->
<h1 :class="classObj">这是一个h1</h1>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
flag:true,
classObj:{red:true,thin:false,active:true}
}
});
</script>
</body>
2、绑定内联样式
直接在元素上通过:style的形式,书写样式对象;
将样式对象定义到data中,直接引用到:style;
在:style中通过数组,引用多个data上的样式对象。
<body>
<div id="app">
<h1 :style="{color:'red',fontWeight:200}">这是一个h1</h1>
<h1 :style="styleObj1">这是一个h1</h1>
<h1 :style="[styleObj1,styleObj2]">这是一个h1</h1>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
styleObj1:{color:'red','font-weight':200},
styleObj2:{fontStyle:'italic'}
}
});
</script>
</body>
六、事件处理v-on @
v-on:缩写是@,用于绑定事件。v-on指令可写js代码,或调用的方法名称,或调用方法(加()参数)。
修饰符:修饰符可以串联,顺序很重要。
.stop 阻止冒泡
.prevent 阻止默认事件
.capture 添加事件侦听器时使用事件捕获模式,仅针对当前事件捕获,未添加.capture的事件仍然冒泡
.self 只当事件在该元素本身(如不是子元素)触发时触发回调
.once 事件只触发一次
.passive 滚动事件的默认行为(即滚动行为)将会立即触发,而不会等待onScroll完成,包含.prevent的情况
<body>
<div id="app">
<div class="outer" @click="outerHandler">
<div class="inner" @click.self="innerHandler">
<button @click="btnHandler">戳它</button>
</div>
</div>
<a href="http://www.baidu.com" @click.prevent.once="linkClick">百度一下</a>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{},
methods:{
outerHandler(){
console.log("outer的点击事件");
},
innerHandler(){
console.log("inner的点击事件");
},
btnHandler(){
console.log("btn的点击事件");
},
linkClick:function(){
console.log("链接");
}
}
});
</script>
</body>
按键修饰符
在监听键盘事件时,经常需要检查常见的键值,Vue允许为v-on在监听键盘事件时添加按键修饰符。记住所有的keyCode(http://www.cnblogs.com/wuhua1/p/6686237.html)比较困难,所以 Vue 为最常用的按键提供了别名。
.enter .tab .delete(捕获“删除”和“退格”键) .esc .space .up .down .left .right
<!-- 只有在`keyCode`是13时调用`vm.submit()` -->
<input v-on:keyup.13="submit">
<!-- 同上 -->
<input v-on:keyup.enter="submit">
可以通过全局config.keyCodes对象自定义按键修饰符别名,在创建Vue实例之前。
// 可以使用`v-on:keyup.别名`
Vue.config.keyCodes.别名=keyCode
七、双向数据绑定v-model
v-model:用于双向数据绑定。
v-bind只能实现数据的单向绑定,从M自动绑定到V;使用v-model指令,可以实现表单元素和Model中数据的双向数据绑定。
只能运用在表单元素中:input(radio, text, address, email...)、select、checkbox、textarea。
<body>
<div id="app">
<h4>{{msg}}</h4>
<input type="text" v-model="msg">
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:'生如夏花之绚烂'
}
});
</script>
</body>
八、列表渲染v-for和key属性
迭代数组 v-for="(val,index) in list"
迭代对象中的属性 v-for="(val,key,index) in list"
迭代数字,count值从1开始 v-for="count in 10"
<body>
<div id="app">
<p>{{list1[0]}}</p>
<p>{{list1[1]}}</p>
<!-- 迭代数组 -->
<p v-for="item in list1">{{item}}</p> <!-- 普通数组 -->
<p v-for="(item,index) in list1">索引值:{{index}},每一项:{{item}}</p>
<p v-for="user in list2">{{user.name}}</p> <!-- 对象数组 -->
<p v-for="(user,index) in list2">索引值:{{index}},每一项的名字:{{user.name}}</p>
<!-- 迭代对象中的属性 -->
<p v-for="val in user">{{val}}</p>
<p v-for="(val,key) in user">{{key}}:{{val}}</p>
<p v-for="(val,key,index) in user">{{index}}.{{key}}:{{val}}</p>
<!-- 迭代数字 -->
<p v-for="count in 6">这是第{{count}}个<p></p>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
list1:[11,22,33,44,55],
list2:[{name:'yc'},{name:'hsg'}],
user:{
firstName:'Scott',
lastName:'Huo',
age:24
}
}
});
</script>
</body>
当Vue.js用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue将不是移动DOM元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如:表单输入值)的列表渲染输出。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一key属性。
理想的key值是每项都有的唯一id,key 属性只能使用number或string类型,不能使用对象。key在使用的时候,必须使用v-bind属性绑定的形式,指定 key 的值。
建议尽可能在使用v-for时提供key,除非遍历输出的DOM内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。2.2.0+的版本里,当在组件中使用v-for时,key是必须的。
<body>
<div id="app">
<label>id:<input type="text" v-model="id"></label>
<label>name:<input type="text" v-model="name"></label>
<button @click="add">添加</button>
<!-- 假设加载完页面后,勾选了一个复选框,之后通过unshift在数组前面增加一项。
如果不使用key,选中的那一项index不变。此时就需要指定key。 -->
<p v-for="item in list" :key="item.id">
<input type="checkbox">{{item.id}}.{{item.name}}
</p>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
id:'',
name:'',
list:[
{id:1,name:'bcn'},
{id:2,name:'cjf'},
{id:3,name:'cj'},
{id:4,name:'csf'}
]
},
methods:{
add(){
this.list.unshift({id:this.id,name:this.name});
}
}
});
</script>
</body>
九、条件渲染v-if和v-show
v-if:每次都会重新删除或创建元素,有较高的切换性能消耗, 适用于元素可能永远也不会被显示。
v-show:只是切换了元素的display:none,有较高的初始渲染消耗,适用于元素涉及到频繁的切换。
<body>
<div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<h3 v-if="flag">v-if控制的元素</h3>
<h3 v-show="flag">v-show控制的元素</h3>
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
flag:true
},
});
</script>
</body>
十、计算属性和侦听器
computed:计算属性,当其中的任何一个data数据发生改变,都会重新计算该计算属性,更新该属性的值。计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变时才会重新求值,如果不希望有缓存,请用方法methods来替代。计算属性默认只有 getter,需要时也可以提供一个setter。
watch:监听某些特定数据的变化,属性是需要观察的data值,值是对应的回调函数。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
<!-- methods -->
<div id="app">
<input type="text" v-model="firstname" @keyup="getFullname">+
<input type="text" v-model="lastname" @keyup="getFullname">=
<input type="text" v-model="fullname">
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
firstname:'',
lastname:'',
fullname:''
},
methods:{
getFullname(){
this.fullname=this.firstname+' '+this.lastname;
}
}
})
</script>
<!-- watch -->
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">=
<input type="text" v-model="fullname">
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
firstname:'',
lastname:'',
fullname:''
},
watch:{
firstname:function(newVal,oldVal){ // 有两个可选参数
this.fullname=newVal+' '+this.lastname;
},
lastname:function(newVal,oldVal){
this.fullname=this.firstname+' '+newVal;
}
}
})
</script>
<!-- computed -->
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">=
<input type="text" v-model="fullname">
</div>
<script>
var vm=new Vue({
el:'#app',
data:{
firstname:'',
lastname:''
},
computed:{
fullname:function(){
return this.firstname+' '+this.lastname;
}
}
})
</script>