[TOC]
Vue前端框架
前端三大流行框架:Vue、React、Angular
Vue是个渐进式的Javascript框架
Vue是国人开发的框架,可以无障碍阅读
Vue核心特性是数据驱动,也就是说是数据和元素双向绑定
-
数据驱动是通过MVVM模型实现的
-
M:Model层,代表数据
-
V:View层,代表视图模板
-
VM:ViewModel层,代表业务逻辑处理代码
其次是组件化开发
- 将网页功能封装为自定义的 HTML 标签
- 使用时写自定义标签名就可以了
- 组件化代码可以封装 结构、样式、逻辑,便于维护
安装方式
本地引入
通过script标签引入,有两种路径引入:
生产版(上线):cn.vuejs.org/js/vue.min.…
CDN引入
也是通过script标签引入
最新稳定版:cdn.jsdelivr.net/npm/vue
指定版本:cdn.jsdelivr.net/npm/vue@2.6…
npm安装
控制台输入
# 最新稳定版
npm i vue
# 指定版本
npm i vue@2.6.12
# 这里建议开发人员安装vue脚手架(vue-cli)
npm i -g vue-cli
Vue基础语法
Vue 实例
Vue是通过创建实例化的Vue对象来实现Vue功能,所以说使用时必须先实例化
// 这里部分使用ES6+语法
let vm = new Vue({
.......
})
实例属性——el
用于选取一个DOM元素作为Vue实例对象(或者说是Vue挂载对象)
使用方式:通过CSS选择器或 element 实例对象
// CSS选择器
let vm = new Vue({
el:"#app"
})
// element实例对象
let app = document.getElementById("app");
let vm = new Vue({
el:app
})
挂载完成后可以访问:
let vm = new Vue({
el:"#app"
})
console.log(vm.$el)
也可以通过外部方法进行挂载
let vm = new Vue({})
vm.$mount("#app");
插值表达法
挂载元素可以使用Vue.js的模板语法
模板中可以通过插值表达式为元素进行动态内容设置,写法为 {{ }}。
<div id="app">
<ul>
<!-- 运算 -->
<li>第一段示例内容:{{ 10 + 20 + 30 }}</li>
<!-- 逻辑判断 -->
<li>第二段示例内容:{{ 22 > 3 ? '22比3大' : '3比22大' }}</li>
<!-- 字符串(数据)显示 -->
<li>第三段示例内容:{{ "hello world" }}</li>
</ul>
</div>
<script src="https://cn.vuejs.org/js/vue.js"></script>
<script>
new Vue({
el: '#app'
});
</script>
注意:
- 差值表达式只能在被挂载的元素内使用
- 内部只支持Javascript表达式,不能书写语句
数据——data属性
用于存储数据,类似于 自变量
使用时,data属性值是对象字面量
let vm = new Vue({
el: "#app",
data: {
title:"hello world",
name: "test",
num: 12
}
})
外部可以通过 vm.$data.数据 或者 vm.数据 方式访问
console.log(vm.$data.title);
console.log(vm.name);
也可以通过插值表达式直接绑定在元素内
<div id="app">
<h1>{{ title }}</h1>
</div>
并且数据发生改变时可以及时更新
技巧:
当data内部存在数组时,索引操作与 length 操作无法自动更新视图,需要使用Vue.set方法替换操作
使用方法
Vue.set(/*变量名*/ vm.arr,/*顺序位置*/ 0,/*要修改的值*/ "hello")
例子:
<div id="app">
<ul>
<li v-for="i in arr">{{ i }}</li>
</ul>
<button onclick="test()">test</button>
</div>
<script src="https://cn.vuejs.org/js/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
title: "hello wrold",
arr: ["arr1","arr2","arr3","arr4"]
}
});
function test() {
Vue.set(vm.arr,1,"123456");
}
</script>
方法——methods属性
用于储存Vue实例中使用到的函数属性
let vm = new Vue({
el: "#app",
data: {
title:"hello world",
name: "test",
num: 12
},
methods: {
fn(value) {
return value.split('-').join('');
}
}
})
使用方式:
<div id="app">
<ul>
<li>{{ fn("a-b-c-d-e") }}</li>
<li>{{ fn("s-t-u-v-w") }}</li>
</ul>
</div>
其中方法可以内部调用(通过 this.方法名执行 )
let vm = new Vue({
el: '#app',
data: {
},
methods: {
fn (index) {
this.test()
console.log(index);
return
},
test () {
console.log("test方法已经被执行")
}
}
});
Vue指令
指令本质就是 标签自定义属性
指令就是以 "v-" 开头的自定义属性
v-once 指令
使元素内部的插值表达式只生效一次,不会随着数据改变而改变
<div id="app">
<p>此内容会随数据变化而自动变化:{{ content }}</p>
<p v-once>此内容不会随数据变化而自动变化: {{ content }}</p>
</div>
<script src="lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
content: '内容文本'
}
})
</script>
v-text 指令
元素内容整体替换为指定纯文本数据
<div id="app">
<p v-text="100">这是 p 标签的原始内容</p>
<p v-text="content">这是 p 标签的原始内容</p>
<p v-text="content2"></p>
</div>
<script src="lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
content: '内容文本',
// 即使写了标签,也不会将标签表示出来,与innerText相识
content2: '<span>span的内容</span>'
}
});
</script>
v-html 指令
元素内容整体替换为指定的 HTML 文本
<div id="app">
<p v-html="content">这是默认的文本内容</p>
</div>
<script src="lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
// content: '这是指令设置的新内容'
content: '<span>span的内容</span>'
}
});
</script>
v-bind 指令——Vue属性绑定
用于动态绑定的html属性,其中属性值为Vue内部的数据
写法:
<div id="app">
<p v-bind:title="title">
设置title属性
</p>
<p :title="title">
可以简写为 :+属性名 的方式
</p>
<p :class="name123">
不光title可以使用,其他的如class、src等属性也可以使用
</p>
</div>
<script src="./lib/vue.min.js"></script>
<script>
new Vue({
el:"#app",
data: {
title:"这是title",
name123:"这是class"
}
})
</script>
当然,若绑定属性过多,可以将这些属性打包为对象方式绑定
new Vue({
el:"#app",
data: {
obj:{
id:"id",
name:"name",
title:"title",
class:"class"
}
}
})
<div id="app">
<p v-bind="obj">
一次性绑定多个属性时,可以用对象方式搞定
</p>
</div>
class绑定
原标签属性可以与 Vue的 v-bind:class 标签共存
<p class="a" :class="cls1">标签内容</p>
当然,vue的css标签还支持特殊处理(如逻辑处理)
<p :class="1+2>3?'class12':'class3'">123</p>
<p :class=['a','classb',{'c':false}]>345</p>
style绑定
style 是 HTML 属性,可以通过 v-bind 进行绑定,并且可以与 style 属性共存,但原来 style 属性中重名部分会被 :style(或v-bind:style) 替换掉
<div id="app">
<p style="background:#000000;color:#fff;width:300px" :style="obj">
123
</p>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
obj:{
height:"400px",
width:"200px"
}
}
})
</script>
:style属性能使用样式对象以及多样式数组
<div id="app">
<p :style="[style1, style2]"> p 标签</p>
</div>
<script src="./lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
style1: {
width: '100px',
height: '100px'
},
style2: {
backgroundColor: 'blue'
}
}
});
</script>
指令渲染
v-for——循环指令
有多个数据(比如说一个数组内所有元素)需要渲染时,可以通过 v-for 进行多次渲染
语法:
<div id="app">
<ul>
<li v-for="item in arr">item的值为{{item}}</li>
</ul>
<hr>
<ul>
<li v-for="(item , index) in arr">内容为:{{item}},索引号为:{{index}}</li>
</ul>
<hr>
<ul>
<li v-for="(item , key , index) in obj">值:{{item}},键{{key}},索引号:{{incex}}</li>
</ul>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data: {
arr:["data1","data2","data3","data4","data5"],
obj:{
content1:"内容1",
content2:"内容2",
content3:"内容3",
content4:"内容4"
}
}
})
</script>
当使用数组时:
- 单个变量:v-for="item in arr" 只会获取内容
- 两个变量:v-for="(item , index) in arr" 会获得内容及索引号
- 其中前者获取内容,后者获取索引号
当使用对象时:
- 单个变量:v-for="item in obj" 只会获取值
- 两个变量:v-for="(item,key) in obj" 会获取键值对
- 其中前者获取值,后者获取键
- 三个变量:v-for="(item,key,index) in obj" 会获取键值对以及索引号
- 其中前者获取值,中者获取键,后者获取索引号
v-show——显示隐藏指令
用于控制元素显示与隐藏,适用于显示隐藏频繁切换时使用
<div id="app">
<p v-show="check">
hello world
</p>
<button @click="check=!check">显示/隐藏</button>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data: {
check: true
}
})
</script>
隐藏时,不会删除元素
注意: template 标签无法使用 v-show 指令
v-if——创建移除元素
用于根据条件控制元素的创建与移除
<div id="app">
<ul>
<li v-if="false">第一个li</li>
<li v-if="true">第二个li</li>
</ul>
</div>
也可以使用 v-else-if和v-else表示其他情况,与JavaScript的 else if和else用法一致
<div id="app">
<p v-if="bool">这是标签内容</p>
<p v-else-if="false">这是第二个p标签</p>
<p v-else-if="false">这是第三个p标签</p>
<p v-else>最后一个p标签</p>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data: {
bool: false
}
})
</script>
当然,v-if还可以进行逻辑判断,与v-show一样:
<div id="app">
<p v-if="2+3>5">这是第一个p标签</p>
<p v-if="type=='hello'">这是第二个p标签</p>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
type:"hello"
}
})
</script>
注意:避免 v-if 与 v-for 应用于同一标签,否则会消耗性能!!
事件处理
v-on指令
用于进行元素的事件绑定
<div id="app">
<button v-on:click="fn('123')">
点击弹出123
</button>
<!--也可以省略为 @click=""-->
<button @click="fn('123')">
点击弹出123
</button>
<!-- 只有v-on指令能加载methods内的方法 -->
<button @click="fn()">
Vue内部的方法
</button>
</div>
当然,事件不止一种,比如说 mouseover、mouseout、mouseup、mousedown、doubleclick等等
在视图中可以通过 $event 访问事件对象
<p @click="fn($event)">
事件对象
</p>
......
<script>
......
methods:{
fn(event){
console.log(event);
}
}
......
</script>
表单输入绑定
v-model指令
用于给 input 、 textarea及 select 元素设置双向数据 绑定
<div id="app">
<p>元素内容为:{{ value }}</p>
<input type="text" v-model="value">
<textarea v-model="value"></textarea>
</div>
<script src="lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
value: ''
}
});
</script>
注意:每个元素的v-model对应的数据最好内容不一致
单选:
<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>
<script src="./lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
value3: ''
}
});
</script>
多选:
<div id="app">
<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>
<script src="lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
value5: []
}
});
</script>
单选框&多选框:
<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>
<script src="lib/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
value6: '',
value7: []
}
});
</script>
修饰符
事件修饰符
prevent修饰符
用于阻止默认事件行为,相当于 event.preventDefault()
用于事件后面,如: @click.prevent、@mouseup.prevent
<div id="app">
<!-- 阻止默认事件并且调用fn方法 -->
<a @click.prevent="fn" href="https://kaiwu.lagou.com/">链接</a>
<!-- 阻止默认事件,不做任何处理 -->
<a @click.prevent href="https://kaiwu.lagou.com/">链接</a>
</div>
stop 修饰符
用于阻止事件传播(冒泡),相当于 event.stopPropagation()
Vue.js 中允许修饰符进行连写,例如:@click.prevent.stop
<div id="app">
<div @click="fn1">
<button @click.stop="fn2">按钮</button>
<a @click.prevent.stop="fn2" href="https://kaiwu.lagou.com/">链接</a>
</div>
</div>
<script src="lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {},
methods: {
fn1 () {
console.log('div 的点击事件');
},
fn2 () {
console.log('a 的点击事件');
}
}
})
</script>
once修饰符
用于设置事件只会触发一次
<div id="app">
<button @click="fn">按钮1</button>
<button @click.once="fn">按钮2</button>
</div>
<script src="lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
},
methods: {
fn () {
alert('按钮被点击了');
}
}
})
</script>
按键修饰符
按键码
按键码指的是将按键的按键码作为修饰符使用以标识按键的操作方式
<div id="app">
<input type="text" @keyup="fn">
<!-- 输入 1 执行fn -->
<input type="text" @keyup.49="fn">
<!-- 输入 a 执行fn -->
<input type="text" @keyup.a="fn">
<!-- 输入 esc 执行fn -->
<input type="text" @keyup.esc="fn">
<!-- 输入 a或b或c 执行fn -->
<input type="text" @keyup.a.b.c="fn">
</div>
<script src="lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {},
methods: {
fn (event) {
console.log(event);
console.log('输入了对应内容');
}
}
});
</script>
注意:
- 特殊按键应该首选内置别名
- 特殊按键:esc、enter、delete、insert等功能性按键
<p @keyup.esc="fn">test</p>
- 系统修饰符单次点击无效,必须与其他按键组合使用
- 系统按键:ctrl、shift、alt等
<p @keyup.ctrl.q="fn">test</p>
鼠标按键修饰符
设置点击事件由鼠标哪个按键来完成
修饰符分为:left、right、middle 三类
分别代表:左键、右键、滑轮中键
<button @click.left="fn">按钮1</button>
<button @click.right="fn">按钮2</button>
<button @click.middle="fn">按钮3</button>
v-model 修饰符
trim修饰符:自动过滤输入内容首尾的空格
lazy修饰符:触发方式由 input 事件触发更改为 change 事件触发(退出/离开输入框后才触发)
number修饰符:将用户输入内容转换为数值形式,若无法通过parseFloat()转换,则会显示原内容
自定义指令
指令用于简化 DOM 操作,相当于对基础 DOM 操作的一种封装
当我们希望使用一些内置指令不具备的 DOM 功能时,可以进行自定义指令设置
自定义指令分为两部分:自定义全局指令、自定义局部指令
自定义全局指令
所用的指令为:
directive(/*触发类型,如聚焦focus*/'focus',{
inserted(el,binding) {
//函数内容
el.focus();
}
})
例子:
<div id="app">
<input type="text" v-focus.a.b="100+1">
</div>
<script src="lib/vue.js"></script>
<script>
Vue.directive('focus', {
inserted (el, binding) {
console.log(el);
console.log(binding);
el.focus();
}
});
new Vue({
el: '#app',
data: {}
});
</script>
效果:
- 在本html文件内可以随意使用,不会受限制
- 直接进入input输入框,可以直接输
自定义局部指令
所用的指令为:
new Vue({
......
directives: {
focus:{
inserted(el,binding) {
// 函数内容
el.focus();
}
}
}
})
例子:
<div id="app">
<input type="text" v-focus>
</div>
<div id="app2">
<input type="text" v-focus>
</div>
<script src="lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {},
directives: {
focus: {
inserted (el) {
el.focus();
}
}
}
});
new Vue({
el: '#app2'
});
</script>
效果:
- 只能在
#app内使用,其他地方使用会报错
过滤器
用于对文本内容进行格式化处理
全局过滤器
js中定义方法:
Vue.filter(/*定义名称*/'filter1',function(value) {
// 自定义内容,这里举 字符串倒输方法
return value.split("").reverse().join("");
})
html中使用方法:
<!-- content为Vue内数据,filter1为全局过滤器 -->
<!-- 在标签内容中使用 -->
<p>
{{ content | filter1 }}
</p>
<!-- 标签内部属性中使用 -->
<p :title="content|filter1">
hello world
</p>
例子:
<div id="app">
<p v-bind:title="value | filterA">这是标签</p>
<p>{{ value2 | filterA }}</p>
</div>
<div id="app2">
<p>{{ value | filterA }}</p>
</div>
<script src="lib/vue.js"></script>
<script>
// 设置全局过滤器
Vue.filter('filterA', function (value) {
return value.split('-').join('');
});
new Vue({
el: '#app',
data: {
value: 'a-b-c',
value2: 'x-y-z'
}
});
new Vue({
el: '#app2',
data: {
value: 'q-w-e'
}
})
</script>
效果:在html文件内都能使用,不会因为绑定对象不同而不执行
其中全局过滤器还有其他神奇操作
操作1:多次使用过滤器
<p>
{{ value | filterA | filterB }}
</p>
操作2:自定义过滤器传参数量
<p>
{{ value | filter1('xiaoxiao',300) }}
</p>
<!-- 注意: 函数中 第一个传参为 value ,第二个才是 'xiaoxiao',以此类推 -->
......
<script>
Vue.filter("filter1",function(v1,v2,v3){
return v2+v1.split("").reverse().join("");
})
new Vue({
el:"#app",
data: {
value:"界世的我"
}
})
</script>
局部过滤器
只能在实例化的Vue内部使用
new Vue({
......
filters: {
过滤器名称: function(value) {
......
return '处理结果'
}
}
})
使用方法请参照全局过滤器
计算属性
虽然可以通过插值表达式来进行数据实时运算,但过于复杂的运算不方便书写,并且也不利于后期维护
<p>
{{ Math.sqrt(number) }}
</p>
使用函数的返回值,能解决书写问题,也能解决后期维护,但反复调用函数会降低机器性能
<p>
{{ out(number) }}
</p>
......
<script>
new Vue({
......
data:{
number:380
},
methods: {
out(val) {
return praseInt(Math.sqrt(val));
}
}
})
</script>
Vue提供了computed属性,访问时会自动执行对应函数
使用方式:
<div id="app">
<p>
{{ result }}
</p>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
arr:[1,2,3,4,5,6]
},
computed:{
result(){
let sum=0;
for(let i=0;i<this.arr.length;i++)
sum+=this.arr[i]
return sum;
}
}
})
</script>
methods 与 computed 区别
| computed | methods |
|---|---|
| 具有缓存 | 无 |
| 通过属性名访问 | 必须通过函数形式调用 |
| 只能用于计算 | 可以用于绑定事件等操作 |
computed内部还有 get 和 set 方法,其中 get 方法用于返回计算结果,Vue 提供了 set 方法来定义输入,默认写法为:
XX_Name(){
......
}
// 使用get、set时,要用对象形式写
XX_Name{
get(){
return ......
},
set(...){
......
}
}
侦察器
用于监听数据变化并执行指定操作
使用方法:
new Vue({
el:"#app",
data:{
value:""
},
watch:{
value(newValue, oldValue){
// 注意:名称与data内相对应
// 代码。。。。。。
}
}
})
例子:
<div id="app">
<input type="text" v-model="value">
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el:"#app",
data: {
value:""
},
watch:{
value(newValue,oldValue) {
console.log("新数据:"+newValue);
console.log("旧数据:"+oldValue);
}
}
})
</script>
deep属性
deep属性译为深度,实际用于监听对象数据中的属性值变化,只适用于对象,不适用于其他地方
使用时会将侦察器变为对象形式
watch:{
// 原:
obj(val,oldVal){
......
}
// 转换为对象时:
obj:{
// 开启深度侦察
deep:true,
// 原来的方法全部由 handle 执行
handle(val,oldVal){
......
}
}
}
注意:
- 当更改(非替换)数组或对象时,回调函数中的新值与旧 值相同,因为它们的引用都指向同一个数组 、对象
- 数组操作不要使用索引与length,无法触发侦听器函数
Vue DevTools调试工具
这个是加载在浏览器的插件,可以通过插件来反映代码问题所在
注意:
- 网页必须应用了 Vue.js 功能才能看到 Vue DevTools
- 网页必须使用 Vue.js 而不是 Vue.min.js
- 网页需要在 http 协议下打开,而不是使用 file 协议本地打开。
生命周期
Vue.js 生命周期指的是 Vue 实例的生命周期
也就是实例从 创建 => 运行 => 销毁 的过程
生命周期函数(生命周期钩子)
通过设置生命周期函数,可以在生命周期的特定阶段执行功能
| 钩子 | 阶段 |
|---|---|
| 创建阶段 | 创建阶段 |
| beforeCreate | Vue实例化之前调用 |
| created | 实例化创建后调用 |
| beforeMount | 实例挂载之前调用 |
| mounted | 实例化挂载后调用 |
| 运行阶段 | 运行阶段 |
| beforeUpdate | 数据更新后,视图更新前调用 |
| Updated | 视图更新前调用 |
| 销毁阶段 | 销毁阶段 |
| beforeDestroy | 实例销毁前调用 |
| destroyed | 实例销毁后调用 |
注意:每个Vue实例都会执行一遍,且只执行一遍
TodoMVC
TodoMVC 是一个经典项目,让开发者快速实 践到框架开发方式
官网地址:todomvc.com/
准备工作
- 克隆github上面的模板
# 找到合适路径,使用git克隆
git clone https://github.com/tastejs/todomvc-app-template.git
- 进入项目目录,安装依赖
npm i
# 或者yarn
yarn
-
安装vue.js
npm i -S vue # -S 可以省略 # yarn方法 yarn add vue
需求分析
-
事项状态切换
- 单个事项切换
- 多个事项切换
-
事项新增
- 内容检测
- 回车新增
-
事项删除
- 单个事项删除
- 已完成事项删除
-
事项编辑
- 触发编辑
- 取消编辑
- 保存编辑
-
事项筛选
- 点击切换显示类别
- 更新渲染所有事项
-
事项数据持久化
- 读取本地存储
- 更新本地存储