简介
核心特性
1.数据驱动视图
双向数据绑定是在数据绑定基础上,可自动将元素输入内容更新给数据,实现数据与元素内容的双向绑定(于输入框等可输入元素,可设置双向数据绑定)
Vue.js 的数据驱动视图是基于 MVVM 模型实现的
MVVM (Model – View – ViewModel )( 数据 - 试图模板 - 业务逻辑处理代码 )是一种软件开发思想
• 基于MVVM 模型实现的数据驱动视图解放了DOM操作
• View 与 Model 处理分离,降低代码耦合度
• 但双向绑定时的 Bug 调试难度增大
• 大型项目的 View 与 Model 过多,维护成本高
2.组件化开发
• 组件化开发,允许我们将网页功能封装为自定义 HTML 标签,复用时书写自定义标签名即可。
• 组件不仅可以封装结构,还可以封装样式与逻辑代码,大大提交了开发效率与可维护性。
安装
本地引入
• 开发版本:https://cn.vuejs.org/js/vue.js
• 生产版本:https://cn.vuejs.org/js/vue.min.js
cdn引入
• 最新稳定版: https://cdn.jsdelivr.net/npm/vue
• 指定版本: https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js
npm 安装
• 最新稳定版:
• npm install vue
• 指定版本
• npm install vue@2.6.12
基础语法
实例
Vue 实例是通过 Vue 函数创建的对象,是使用 Vue 功能的基础。
var vm = new Vue({
//选项对象
})
基础选项
1.el 选项
• 用于选取一个 DOM 元素作为 Vue 实例的挂载目标。
• 只有挂载元素内部才会被 Vue 进行处理,外部为普通 HTML 元素。
• 代表 MVVM 中的 View 层(视图)
• 可以为 CSS 选择器格式的字符串 或 HTMLElement 实例,但不能为 html 或 body
• 挂载完毕后,可以通过 vm.$el 进行访问
var vm = new Vue({
el: '#app'
})
console.log(vm.$el)
• 未设置 el 的 vue 实例,也可以通过 vm.$mount() 进行挂载,参数形式与 el 规则相同
var vm = new Vue({});
vm.$mount('#app');
2.插值表达式
• 挂载元素可以使用 Vue.js 的模板语法,模板中可以通过插值表达式为元素进行动态内容设置,写法为 {{ }}。
<div id="app">
<ul>
<li>第一段示例内容:{{ 10 + 20 + 30 }}</li>
<li>第二段示例内容:{{ 22 > 3 ? '22比3大' : '3比22大' }}</li>
</ul>
</div>
注意点:
• 插值表达式只能书写在标签内容区域,可以与其它内容混合。
• 内部只能书写 JavaScript 表达式,不能书写语句。
3. data 选项
用于存储 Vue 实例需要使用的数据,值为对象类
var vm = new Vue({
el: '#app',
data: {
title: '标题文本',
arr: ['内容1', '内容2', '内容3']
}
});
console.log(vm.$data.title);
console.log(vm.title); // 更常用
• data 中的数据可以直接在视图中通过插值表达式访问。
• data 中的数据为响应式数据,在发生改变时,视图会自动更新。
data 中存在数组时,索引操作与 length 操作无法自动更新视图,这时可以借助 Vue.set() 方法替代操作
Vue.set(vm.arr,0,'新的内容')
4. methods 选项
• methods 中的方法可以通过 vm.方法名 访问。
• 方法中的 this 为 vm 实例,可以便捷的访问 vm 数据等功能。
var vm = new Vue({
el: '#app',
data: {
prefix: '处理的结果为:',
},
methods: {
fn (value) {
return this.prefix + value.split('-').join('');
}
}
});
指令
Vue.js的指令就是以v-开头的自定义属性(指令的本质就是HTML自定义属性)
内容处理
v-once
使元素内部的插值表达式只生效一次
<p v-once>此内容不会随数据变化而自动变化: {{ content }}</p>
v-text
元素内容整体替换为指定纯文本数据。
<p v-text="content">这是 p 标签的原始内容</p>
v-html
元素内容整体替换为指定的 HTML 文本
<p v-html="content">这是默认的文本内容</p>
属性绑定
v-bind
用于动态绑定 HTML 属性
<p v-bind:title="myTitle">p标签的内容</p>
<p :title="myTitle">p标签的内容</p> //简写
<p v-bind="attrObj">p标签的内容</p> //一次绑定多个属性
<p :class="'num' + 1 + 2 + 3">p标签的内容</p> //表达式
<p :class="prefix + num"></p>
var vm = new Vue({
el: '#app',
data: {
myTitle: '这是title的内容',
attrObj: {
id:'box',
title:'实例内容'
},
prefix: 'demo',
num: 10
}
});
Class绑定
class 是 HTML 属性,可以通过 v-bind 进行绑定,并且可以与
class 属性共存
<div id="app">
<!-- <p v-bind:class="cls1">标签内容</p> -->
<!-- <p class="a" :class="cls1">标签内容</p> -->
<!-- 下面是错误写法,要注意 -->
<!-- <p class="a b c" :class="cls1 cls2 cls3"></p> -->
<!-- <p :class="cls"></p> -->
<!-- <p :class="bool ? cls1 : cls2"></p> -->
<!-- <p :class="{ x: isX, y: false, z: true }"></p> -->
<p :class="['a', classB, {c: isC}]"></p>
</div>
var vm = new Vue({
el: '#app',
data: {
classB: 'b',
isC: true
// isX: true
/* bool: true,
cls: 'q w e',
cls1: 'x',
cls2: 'y',
cls3: 'z' */
}
});
Style绑定
style 是 HTML 属性,可以通过 v-bind 进行绑定,并且可以与
style 属性共存。
<div id="app">
<!-- <p v-bind:style="{width: '100px', height: '100px'}"></p> -->
<!-- <p :style="styleObj">标签内容</p> -->
<!-- <p style="width: 100px" :style="styleObj"></p>-->
<p :style="[baseStyle, styleObj1]">第一个 p 标签</p>
<p :style="[baseStyle, styleObj2]">第二个 p 标签</p>
</div>
var vm = new Vue({
el: '#app',
data: {
styleObj: {
// width: '200px',
height: '200px',
backgroundColor: 'red',
'font-size': '30px'
},
// 公共样式
baseStyle: {
width: '100px',
height: '100px'
},
styleObj1: {
backgroundColor: 'red'
},
styleObj2: {
backgroundColor: 'blue'
}
}
});
渲染指令
v-for 指令
用于遍历数据渲染结构,常用的数组与对象均可遍历。
<div id="app">
<ul>
<li v-for="(item, index) in itemList" :key="item.id">
输入框{{ item.value }}: <input type="text">
</li>
</ul>
</div>
var vm = new Vue({
el: '#app',
data: {
arr: [1, 2, 3],
itemList: [
{
id: 1,
value: 2
},
{
id: 2,
value:3
},
{
id:3,
value:3
}
]
}
})
使用 v-for 的同时,应始终指定唯一的 key 属性,可以提高渲染性能并避免问题。
• 通过 标签设置模板占位符,可以将部分元素或内容作为整体进行操作。
<div id="app">
<template v-for="item in obj">
<span>{{ item }}</span>
<br>
</template>
</div>
v-show 指令
用于控制元素显示与隐藏,适用于显示隐藏频繁切换时使用
<p v-show="bool">标签内容</p>
<template> 无法使用 v-show 指令
v-if 指令
用于根据条件控制元素的创建与移除
<p v-if="bool">这是标签内容</p>
<p v-else-if="false">这是第二个p标签</p>
<p v-else-if="false">这是第三个p标签</p>
<p v-else>最后一个p标签</p>
给使用 v-if 的同类型元素绑定不同的key
<div id="app">
<div v-if="type==='username'" :key="'username'">
用户名输入框:<input type="text">
</div>
<div v-else :key="'email'">
邮箱输入框:<input type="text">
</div>
</div>
出于性能考虑,应避免将 v-if 与 v-for 应用于同一标签
事件处理
v-on指令
用于进行元素的事件绑定
<div id="app">
<p>{{ content }}</p>
<button v-on:click="content='这是新的内容'">按钮</button>
<!-- 简写 -->
<button @click="content='这是按钮2设置的内容'">按钮2</button>
<button @click="fn">按钮3</button>
<!-- 在视图中可以通过 $event 访问事件对象。 -->
<button @click="fn2(200, $event)">按钮4</button>
</div>
new Vue({
el: '#app',
data: {
content: '这是默认内容'
},
methods: {
fn(event) {
console.log(event);
this.content = '这是按钮3设置的内容';
},
fn2(value, event) {
console.log(value, event);
}
}
})
表单输入绑定
v-model指令
用于给 <input> 、<textarea> 及 <select> 元素设置双向数据
绑定。
1.输入框绑定-----为单行输入框 input 与多行输入框 textarea
<div id="app">
<p>input 输入框的内容为: {{ value1 }}</p>
<input type="text" v-model="value1">
<p>textarea 输入框的内容为: {{ value2 }}</p>
<textarea v-model="value2"></textarea>
</div>
2.单选按钮绑定
<div id="app">
<p>radio 的内容为: {{ value3 }}</p>
<input type="radio" id="one" value="1" v-model="value3">
<label for="one">选项1</label>
<input type="radio" id="two" value="2" v-model="value3">
<label for="two">选项2</label>
</div>
3.复选框绑定
<div id="app">
<!-- 单个复选框进行双向数据绑定的演示 -->
<p>单个复选框的值: {{ value4 }}</p>
<input
type="checkbox"
value="选项内容"
id="one"
v-model="value4">
<label for="one">选项内容</label>
<!-- 多个复选框进行双向数据绑定的演示 -->
<p>多个复选框的值:{{ value5 }}</p>
<input
type="checkbox"
id="cb1"
value="选项1"
v-model="value5"
>
<label for="cb1">选项1</label>
<input
type="checkbox"
id="cb2"
value="选项2"
v-model="value5"
>
<label for="cb2">选项2</label>
<input
type="checkbox"
id="cb3"
value="选项3"
v-model="value5"
>
<label for="cb3">选项3</label>
</div>
4.选择框绑定
<div id="app">
<!-- 单选选择框 -->
<p>单选选择框的内容: {{ value6 }}</p>
<select v-model="value6">
<option value="">请选择</option>
<option value="1">选项1</option>
<option value="2">选项2</option>
<option value="3">选项3</option>
</select>
<!-- 多选选择框 -->
<p>多选选择框的内容:{{ value7 }}</p>
<select v-model="value7" multiple>
<option value="1">选项1</option>
<option value="2">选项2</option>
<option value="3">选项3</option>
</select>
</div>
小结:
• input 输入框:绑定字符串值。
• textarea 输入框:绑定字符串值。
• radio:绑定字符串值。
• checkbox:单个绑定布尔值,多个绑定数组。
• select:单选绑定字符串,多选绑定数组。
修饰符
修饰符是以点开头的指令后缀,用于给当前指令设置特殊操作。
1.事件修饰符
.prevent
修饰符
用于阻止默认事件行为,相当于 event.preventDefault()。
<!-- <a @click.prevent="fn" href="https://kaiwu.lagou.com/">链接</a> -->
<a @click.prevent href="https://kaiwu.lagou.com/">链接</a>
.stop
修饰符
用于阻止事件传播,相当于 event.stopPropagation()。
Vue.js 中允许修饰符进行连写,例如:@click.prevent.stop
<!-- <button @click.stop="fn2">按钮</button> -->
<a @click.prevent.stop="fn2" href="https://kaiwu.lagou.com/">链接</a>
.once
修饰符
用于设置事件只会触发一次。
<button @click="fn">按钮1</button>
<button @click.once="fn">按钮2</button>
2.按键修饰符
按键码指的是将按键的按键码作为修饰符使用以标识按键的操作方式
特殊按键指的是键盘中类似 esc、enter、delete 等功能按键,
为了更好的兼容性,应首选内置别名
<div id="app">
<!-- <input type="text" @keyup="fn"> -->
<!-- <input type="text" @keyup.49="fn"> -->
<!-- <input type="text" @keyup.a="fn"> -->
<!-- <input type="text" @keyup.esc="fn"> -->
<input type="text" @keyup.a.b.c="fn">
</div>
3.系统修饰符
系统按键指的是 ctrl 、alt 、shift 等按键
单独点击系统操作符无效,系统按键通常与其他按键组合使用
.ctrl
修饰符
.alt
修饰符
.shift
修饰符
<input type="text" @keyup.ctrl.q="fn" v-model="inputValue">
4.鼠标修饰符
用于设置点击事件由鼠标哪个按键来完成。
.left
修饰符
.right
修饰符
.middle
修饰符
<div id="app">
<button @click.left="fn">按钮1</button>
<button @click.right="fn">按钮2</button>
<button @click.middle="fn">按钮3</button>
</div>
5.v-model 修饰符
.trim
修饰符
用于自动过滤用户输入内容首尾两端的空格
.lazy
修饰符
用于将 v-model 的触发方式由 input 事件触发更改为 change
事件触发
.number
修饰符
用于自动将用户输入的值转换为数值类型,如无法被
parseFloat() 转换,则返回原始内容
<div id="app">
<!-- <input type="text" v-model.trim="inputValue">
<p>{{ inputValue }}</p> -->
<!-- <input type="text" v-model.lazy="inputValue">
<p>{{ inputValue }}</p> -->
<input type="text" v-model.number="inputValue">
<p>{{ inputValue }}</p>
</div>
自定义指令
指令用于简化 DOM 操作,相当于对基础 DOM操作的一种封装
当我们希望使用一些内置指令不具备的 DOM功能时,可以进行自定义指令设置
1. 自定义全局指令
指的是可以被任意 Vue 实例或组件使用的指令。
Vue.directive('focus', {
inserted (el, binding) {
// console.log(el);
console.log(binding);
el.focus();
}
});
2. 自定义局部指令
指的是可以在当前Vue实例或组件内使用的指令
new Vue({
el: '#app',
data: {},
directives: {
focus: {
inserted (el) {
el.focus();
}
}
}
过滤器
过滤器用于进行文本内容格式化处理。
过滤器可以在插值表达式和 v-bind 中使用
1. 全局过滤器
可以将一个数据传入到多个过滤器中进行处理
一个过滤器可以传入多个参数
<div id="app">
<p v-bind:title="value | filterA">这是标签</p>
<p>{{ value2 | filterA }}</p>
<!-- <p>{{ value | filterA | filterB }}</p> -->
<p>{{ value | filterC('lagou-', 200) }}</p>
<p>{{ value | filterC('qqq-', 200) }}</p>
</div>
/* Vue.filter('filterA', function (value) {
console.log(value, 'filterA');
return value.split('-').join('');
});
Vue.filter('filterB', function (value) {
console.log(value, 'filterB');
return value[0].toUpperCase() + value.slice(1);
}) */
Vue.filter('filterC', function (par1, par2, par3) {
return par2 + par1.split('-').join('');
});
2. 局部过滤器
局部过滤器只能在当前 Vue 实例中使用
new Vue({
el: '#app',
data: {
content: 'a-b-c',
content2: 'x-y-z'
},
filters: {
filterA: function (value) {
return value.split('-').join('');
},
filterB: function (value) {
return value.split('').reverse().join('');
},
filterC (value, prefix) {
return prefix + value;
}
}
});
全局过滤器和局部过滤器名称相同时采用就近原则
// 全局过滤器 filterA 设置翻转字符串功能
Vue.filter('filterA', function (value) {
return value.split('').reverse().join('');
});
new Vue({
el: '#app',
data: {
content: 'a-b-c-d-e-f'
},
// 局部过滤器 filterA 设置去除 - 的功能
filters: {
filterA (value) {
return value.split('-').join('');
}
}
});
其他选项
计算属性
Vue.js 的视图不建议书写复杂逻辑,这样不利于维护
封装函数是很好的方式,但有时重复的计算会消耗不必要的性能。
提高执行效率:
<p>{{ getResult }}</p>
var vm = new Vue({
el: '#app',
data: {
arr: [1, 2, 3, 4, 5]
},
computed: {
getResult () {
console.log('执行了计算属性');
var arr = this.arr;
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
}
})
methods 与 computed 区别
• computed 具有缓存型,methods 没有。
• computed 通过属性名访问,methods 需要调用。
• computed 仅适用于计算操作
计算属性的 setter
计算属性默认只有 getter,Vue.js 也允许给计算属性设置
setter
var vm = new Vue({
el: '#app',
data: {
firstName: '张',
lastName: '三'
},
computed: {
// 默认书写方式:
/* fullName () {
return this.firstName + this.lastName;
} */
// 分开书写 getter 与 setter
fullName: {
get () {
return this.firstName + this.lastName;
},
set (newValue) {
console.log(newValue)
var nameArr = newValue.split(' ');
this.firstName = nameArr[0];
this.lastName = nameArr[1];
}
}
}
});
侦听器
侦听器用于监听数据变化并执行指定操作
为了监听对象内部值的变化,需要将 watch 书写为对象,并设置选项 deep: true,这时通过 handler 设置处理函数
var vm = new Vue({
el: '#app',
data: {
title: '这是内容',
obj: {
content1: '内容1',
content2: '内容2'
},
arr: [1, 2, 3, 4, 5]
},
watch: {
title (val, oldVal) {
console.log('title 被修改了', val, oldVal);
},
/* obj () {
console.log('obj 被修改了');
} */
obj: {
deep: true,
handler (val, oldVal) {
console.log('obj 被修改了', val, oldVal);
console.log(val === oldVal);
}
},
arr (val, oldVal) {
console.log('arr 修改了', val, oldVal)
},
/* arr: {
deep: true,
handler (val, oldVal) {
console.log('arr 修改了', val, oldVal)
}
} */
}
});
• 注意:当更改(非替换)数组或对象时,回调函数中的新值与旧值相同,因为它们的引用都指向同一个数组 、对象。
• 注意:数组操作不要使用索引与length,无法触发侦听器函数。
Vue DevTools
Vue.js 官方提供的用来调试 Vue 应用的工具
注意事项:
• 网页必须应用了 Vue.js 功能才能看到 Vue DevTools
• 网页必须使用 Vue.js 而不是 Vue.min.js
• 网页需要在 http 协议下打开,而不是使用 file 协议本地打开
Vue.js 生命周期
Vue.js 生命周期指的是 Vue 实例的生命周期
Vue 实例的生命周期,指的是实例从创建到运行,再到销毁的过程
通过设置生命周期函数,可以在生命周期的特定阶段执行功能
生命周期函数也称为生命周期钩子
• 创建阶段:
• beforeCreate:实例初始化之前调用。
• created: 实例创建后调用。
• beforeMount:实例挂载之前调用。
• mounted: 实例挂载完毕。
特点:每个实例只能执行一次。
运行阶段:
• beforeUpdate:数据更新后,视图更新前调用。
• updated: 视图更新后调用。
• 特点:按需调用。
销毁阶段:
• beforeDestroy:实例销毁之前调用。
• destroyed: 实例销毁后调用。
特点:每个实例只能执行一次。