安装使用
直接用 < script > 引入
直接下载并用 < script> 标签引入,Vue 会被注册为一个全局变量;在vue官网直接下载到本地,在项目中使用script标签引入。
Vue1.0.26下载地址:http://v1-cn.vuejs.org/js/vue.js
MVVM模式
- MVVM拆分解释为:
- Model:负责数据存储
- View:负责页面展示
- View Model:负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示
- MVVM要解决的问题是将业务逻辑代码与视图代码进行完全分离,使各自的职责更加清晰,后期代码维护更加简单
- 用图解的形式分析Ajax请求回来数据后直接操作Dom来达到视图的更新的缺点,以及使用MVVM模式是如何来解决这个缺点的
MVC和MVVM的关系图解
创建Vue实例对象
1.导入Vue文件,当Vue.js文件导入后,在浏览器的内存中就多了一个Vue() 构造函数.
当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
data: data
})
// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
值得注意的是只有当实例被创建时就已经存在于 data 中的属性才是响应式的。也就是说如果你添加一个新的属性,那么对 b 的改动将不会触发任何视图的更新。
vm.b = 'hi'
Object.freeze()
阻止修改现有的属性,也意味着响应系统无法再追踪变化。
控制台会警告
[Vue warn]: Error in v-on handler: "TypeError: Cannot assign to read only property 'message' of object '#<Object>'"
<div id="app">
{{message}}
</div>
<script type="text/javascript">
var data = {
message: 'Hello Vue!',
};
Object.freeze(data);
var vm = new Vue({
el: '#app',
data:data,
});
vm.message = 'Hello Vue';
</script>
$watch(‘key’,function(newValue,oldValue){}):监控key的变化,一旦发生改变,就会调用回调函数。
<div id="app">
<p>{{message}}</p>
<button v-on:click="message = 'Hello Vue'">change</button>
</div>
<script type="text/javascript">
var data = {
message: 'Hello Vue!',
};
// Object.freeze(data);
var vm = new Vue({
el: '#app',
data:data,
});
vm.$watch('message',function(newValue,oldValue){
console.log(newValue);//Hello Vue
console.log(oldValue);//Hello Vue!
});
</script>
生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch(‘a’, newValue => this.myMethod())。因为箭头函数并没有 this,this 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。
- 创建期间的生命周期函数:
- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
- created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
- mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
- updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- 销毁期间的生命周期函数:
- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
- destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
<div id="app">
{{msg}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: 'hi vue'
},
//在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
beforeCreate: function() {
console.log('beforeCreate');
},
/* 在实例创建完成后被立即调用。 在这一步, 实例已完成以下的配置: 数据观测(data observer), 属性和方法的运算, watch / event 事件回调。 然而, 挂载阶段还没开始, $el 属性目前不可见。 */
created: function() {
console.log('created');
},
/* 在挂载开始之前被调用:相关的 render 函数首次被调用。
该钩子在服务器端渲染期间不被调用。 */
beforeMount: function() {
console.log('beforeMount');
},
/* el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。 */
mounted: function() {
console.log('mounted');
},
/* 数据更新时调用, 发生在虚拟 DOM 打补丁之前。 这里适合在更新之前访问现有的 DOM, 比如手动移除已添加的事件监 听器。
该钩子在服务器端渲染期间不被调用, 因为只有初次渲染会在服务端进行。 */
beforeUpdate: function() {
console.log('beforeUpdate');
},
updated:function(){
console.log('updated');
},
/* keep-alive 组件激活时调用。
该钩子在服务器端渲染期间不被调用。 */
activated:function(){
console.log('activated');
}
});
模板语法
插值
数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值
例如:Message: {{ msg }}
Mustache 标签将会被替代为对应数据对象上 msg 属性(msg定义在data对象中)的值。
无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
{{}}对JavaScript 表达式支持,例如:
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
但是有个限制就是,每个绑定都只能包含单个表达式,如下表达式无效:
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
指令
- v-text
v-text可以将一个变量的值渲染到指定的元素中,跟插值表达式不同,v-text会覆盖标签中原有的文本值,例如:
<div v-text="msg"></div>
new Vue({
data:{
msg:'hello ivan'
}
});
输出结果:
<div>hello ivan</div>
- v-html
双大括号和v-text会将数据解释为纯文本,而非 HTML 。
为了输出真正的 HTML ,你需要使用 v-html 指令:例如:
<div v-html="rawHtml"></div>
new Vue({
data:{
rawHtml:'< h1 >hello ivan</h1>'
}
})
被插入的内容都会被当做 HTML,但是对于没有HTML标签的数据绑定时作用同v-text和{{}}
注意:使用v-html渲染数据可能会非常危险,因为它很容易导致 XSS(跨站脚本) 攻击,使用的时候请谨慎,能够使用{{}}或者v-text实现的不要使用v-html
- v-pre
跳过编译,显示原文本 - v-cloak
v-cloak指令保持在元素上直到关联实例结束编译后自动移除,v-cloak和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
通常用来防止{{}}表达式闪烁问题
例如:
<style>
[v-cloak] { display: none }
</style>
<!-- 在span上加上 v-cloak和css样式控制以后,浏览器在加载的时候会先把span隐藏起来,直到Vue实例化完毕以后,才会将v-cloak从span上移除,那么css就会失去作用而将span中的内容呈现给用户 -->
<span v-cloak>{{msg}}</span>
new Vue({
data:{
msg:'hello ivan'
}
})
- v-bind
Vue中提供的用于绑定属性的指令
1、作用:可以给html元素或者组件动态地绑定一个或多个特性,例如动态绑定style和class
2、举例:
<img v-bind:src="imageSrc">
<div v-bind:class="{ red: isRed }"></div>
<div v-bind:class="[classA, classB]"></div>
<div v-bind:class="[classA, { classB: isB, classC: isC }]">
<div v-bind:style="{ fontSize: size + 'px' }"></div>
<div v-bind:style="[styleObjectA, styleObjectB]"></div>
3、缩写形式
<img :src="imageSrc">
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
绑定class样式
- 数组
<h1 :class="['red', 'thin']">这是一个邪恶的H1</h1>
- 数组中使用三元表达式
<h1 :class="['red', 'thin', isactive?'active':'']">这是一个邪恶的H1</h1>
- 数组中嵌套对象
<h1 :class="['red', 'thin', {'active': isactive}]">这是一个邪恶的H1</h1>
- 直接使用对象
<h1 :class="{red:true, italic:true, active:true, thin:true}">这是一个邪恶的H1</h1>
绑定内联样式
1. 直接在元素上通过 :style 的形式,书写样式对象
<h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>
2. 将样式对象,定义到 data 中,并直接引用到 :style 中
- 在data上定义样式:
data: {
h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
}
- 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
<h1 :style="h1StyleObj">这是一个善良的H1</h1>
3. 在 :style 中通过数组,引用多个 data 上的样式对象
- 在data上定义样式:
data: {
h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },
h1StyleObj2: { fontStyle: 'italic' }
}
- 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
<h1 :style="[h1StyleObj, h1StyleObj2]">这是一个善良的H1</h1>
v-on
1、作用:绑定事件监听,表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略,用在普通的html元素上时,只能监听 原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
事件直接绑定函数名称
如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数
<button v-on:click="myclick">点击</button>
事件绑定函数调用
如果事件绑定函数调用,事件对象的名称必须是$event
<button v-on:click='myclick($event)'>点击</button>
2、常用事件:
v-on:click
v-on:keydown
v-on:keyup
v-on:mousedown
v-on:mouseover
v-on:submit
....
3、v-on提供了很多事件修饰符来辅助实现一些功能,例如阻止冒泡等
事件修饰符有如下:
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只有当事件是从侦听器绑定的元素本身(比如不是子元素)触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once 事件只触发一次
4、示例:
<!-- 方法处理器 -->
<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>
5、v-on的缩写形式:可以使用@替代 v-on:
<button @click="doThis"></button>
- v-model
1、在表单控件或者组件上创建双向绑定
2、v-model仅能在如下元素中使用:
input
select
textarea
components(Vue中的组件)
3、举例:
<input type="text" v-model="uname" />
new Vue({
data:{
uname:'' //这个属性值和input元素的值相互一一对应,二者任何一个的改变都会联动的改变对方
}
})
4、修饰符(了解):
.lazy - 取代 input 监听 change 事件
.number - 自动将输入的字符串转为数字
.trim - 自动将输入的内容首尾空格去掉
- v-for
1、作用:通常是根据数组中的元素遍历指定模板内容生成内容
2、用法举例:
<div v-for="item in items">
{{ item.text }}
</div>
new Vuew({
data:{
items:[{text:'1'},{text:'2'}]
}
});
3、可以为数组索引指定别名(或者用于对象的键):
Vue1.0写法:
<div v-for="(index,item) in items"></div>
<div v-for="(key,val) in user"></div>
new Vue({
data:{
items:[{text:'1'},{text:'2'}],
user:{uname:'ivan',age:32}
}
});
Vue2.0写法:
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in user"></div>
<div v-for="(val, key, index) in user"></div>
//v-for迭代数字从1开始
<div v-for="count in 10">这是第{{count}}循环</div>
new Vue({
data:{
items:[{text:'1'},{text:'2'}],
user:{uname:'ivan',age:32}
}
});
4、v-for 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性
:
Vue2.0写法:
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
Vue1.0写法:
<div v-for="item in items" track-by="$index">
{{ item.text }}
</div>
5、vue1.0与vue2.0对于v-for使用区别总结:
1、vue1.0中有$index ,而vue2.0中将$index移除
2、vue1.0中 (index,item) in list 而 vue2.0 变成了 (item,index) in list的写法
3、vue1.0中使用 track-by来标记dom对象的唯一性,vue2.0中改成了 :key
- v-if
1、作用:根据表达式的值的真假条件来决定是否渲染元素,如果条件为false不渲染(达到隐藏元素的目的),为true则渲染。在切换时元素及它的数据绑定被销毁并重建
2、示例:
<!-- Handlebars 模板 -->
{{#if isShow}}
<h1>Yes</h1>
{{/if}}
通常我们使用写法居多:
<h1 v-if="isShow">Yes</h1>
也可以用 v-else 添加一个 “else” 块:
<h1 v-if="isShow">Yes</h1>
<h1 v-else>No</h1>
注意:v-else 元素必须紧跟在 v-if 元素否则它不能被识别。
new Vue({
data:{
isShow:true
}
});
- v-show
1、根据表达式的真假值,切换元素的 display CSS 属性,如果为false,则在元素上添加 display:none来隐藏元素,否则移除display:none实现显示元素
2、示例:
<h1 v-show="isShow">Yes</h1>
new Vue({
data:{
isShow:true
}
});
v-if和v-show的总结
v-if和v-show 都能够实现对一个元素的隐藏和显示操作,但是v-if是将这个元素添加或者移除到dom中,而v-show
是在这个元素上添加 style="display:none"和移除它来控制元素的显示和隐藏的
表单基本操作
单选框
<!--
1、 两个单选框需要同时通过v-model 双向绑定 一个值
2、 每一个单选框必须要有value属性 且value 值不能一样
3、 当某一个单选框选中的时候 v-model 会将当前的 value值 改变 data 中的 数据
gender 的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>
<script>
new Vue({
data: {
// 默认会让当前的 value 值为 2 的单选框选中
gender: 2,
},
})
</script>
复选框
<!--
1、 复选框需要同时通过v-model 双向绑定 一个值
2、 每一个复选框必须要有value属性 且value 值不能一样
3、 当某一个单选框选中的时候 v-model 会将当前的 value值 改变 data 中的 数据
hobby 的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<div>
<span>爱好:</span>
<input type="checkbox" id="ball" value="1" v-model='hobby'>
<label for="ball">篮球</label>
<input type="checkbox" id="sing" value="2" v-model='hobby'>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model='hobby'>
<label for="code">写代码</label>
</div>
<script>
new Vue({
data: {
// 默认会让当前的 value 值为 2 和 3 的复选框选中
hobby: ['2', '3'],
},
})
</script>
获取下拉框和文本域中的值
<div>
<span>职业:</span>
<!--
1、 需要给select 通过v-model 双向绑定 一个值
2、 每一个option 必须要有value属性 且value 值不能一样
3、 当某一个option选中的时候 v-model 会将当前的 value值 改变 data 中的 数据
occupation 的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<!-- multiple 多选 -->
<select v-model='occupation' multiple>
<option value="0">请选择职业...</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>
<!-- textarea 是 一个双标签 不需要绑定value 属性的 -->
<textarea v-model='desc'></textarea>
</div>
<script>
new Vue({
data: {
// 默认会让当前的 value 值为 2 和 3 的下拉框选中
occupation: ['2', '3'],
desc: 'nihao'
},
})
</script>
表单修饰符
- .number 转换为数值
- 注意点:
- 当开始输入非数字的字符串时,因为Vue无法将字符串转换成数值
- 所以属性值将实时更新成相同的字符串。即使后面输入数字,也将被视作字符串。
- .trim 自动过滤用户输入的首尾空白字符
- 只能去掉首尾的 不能去除中间的空格
- .lazy 将input事件切换成change事件
- .lazy 修饰符延迟了同步更新属性值的时机。即将原本绑定在 input 事件的同步逻辑转变为绑定在 change 事件上