一、Vue的基本认识
Vue是一款渐进式的JavaScript框架库,作者是尤雨溪,作用是的动态的构建用户界面
1.1 Vue特点
- 遵循MVVM模式
- 编码简洁,体积小,运行效率高,适合移动端和PC端开发
- 本身是关注UI,可以轻松的引入Vue插件或者其他第三方库
1.2 与其他的前端Js框架的关联
Vue的作者尤雨溪在开源此框架的时候,就说Vue是借鉴了angular的模板和数据绑定技术和react的虚拟dom以及组件化
1.3 Vue的扩展插件
- vue-cli:vue的脚手架,下载基于Vue的项目 声明好了一些配置依赖
- vue-resource(axios官方推荐):ajax请求
- vue-router:路由
- vuex:状态管理
- vue-lazyload:图片懒加载
- vue-scoller:页面滑动相关
- mint-ui:基于vue的UI组件库(移动端)
- element-ui:基于vue 的UI组件库(PC端)
二、Vue的基本使用
2.1 效果
实现数据的双向绑定的案例
2.2 如何引入Vue.js
初学者建议使用CDN引入Vue.js的方式来使用,官网也是建议初学者这样来学习Vue。后期我们可以使用Vuecli来创建Vue的项目来实现
【引入Vue】
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
当然也可以下载Vue的js文件,通过script标签来引入Vue
2.3 声明式渲染 v-model
【官网案例】
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<script src="./js/vue.js"></script> <!--也可以使用CDN来引入,需要网络环境-->
<!-- MVVM 模型中的V(View视图)-->
<div id = "app">
<input type="text" v-model="username"/>
<p>{{ username }}</p>
</div>
<script>
const vm = new Vue({ // 配置对象 实例化一个Vue的实例对象 VM 视图对象
el: '#app', // id选择器 el:元素 值是一个选择器 实例的
data: { // 数据Model M data的只是一个对象
username: 'Hello Vue! '
}
})
</script>
【案例解析】:
-
引入Vue.js
-
创建Vue实例对象 一般使用Const 声明一个常量
MVVM中的VM 虚拟对象
- el:指定根element(选择器)
- data:初始化数据(页面可以访问)
MVVM中的M 数据
-
双向绑定数据:
v-model
-
显示数据:{{xxx}}
-
理解Vue的MVVM实现
2.4 理解MVVM模型
【MVVM】模型解读
-
model:M 模型
—> Data 数据对象,可以自动给View显示使用(Vue的实例) -
View:V 视图
—> 模板页面- 指令:Vue提供的一些标签属性,例如v-model (数据绑定)…
- {{}} 大括号表达式:用于显示数据
-
View Model VM
—>Vue的实例对象
- 通过数据绑定 将M的数据动态的传输给View
VM 是Vue的实例对象,不是Vue
那么Vue是如何实现数据的双向绑定的呢?
三、模板语法
3.1 效果
3.2 模板的理解
【官网解释:】
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
【总结】
模板就是动态的Html页面
,包含了一些JavaScript语法代码、双大括号表达式、指令(以v-打头的自定义标签属性)
3.3 双大括号表达式 {{}}
<h1>双大括号插值语法</h1>
<h3>你好{{msg}}</h3>
<p>全部大写:{{msg.toUpperCase()}}</p>
<p v-text="a_tip"></p> <!--会将绑定的数据作为纯文本解析 类似于innerText-->
<p v-html="a_tip"></p> <!--会识别Html标签 类似于innerHtml-->
- {{}}:数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的
文本插值
- 使用双大括号绑定的数据
- 既然绑定的是对象,那么就可以先弄个Js一样调用函数
- 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用
v-html
- 双大括号语法有一个等效的指令:
v-text
3.4 指令一:强制数据绑定 v-bind
<div id="root">
<h1>强制数据绑定</h1>
<img :src="imgUrl" alt="">
<a v-bind:href="url">点我去被百度</a>
<div :id="show?'div':''"></div>
<hr>
</div>
<script type="text/javascript">
const vm = new Vue({
el:"#root",
data:{
show:true,
}
</script>
<style type="text/css">
#div{
width: 200px;
height: 200px;
background-color: #4caf50;
}
</style>
- 普通的插值语法不能做用在Html属性上,如果需要动态绑定属性需要使用
v-bind
- v-bind可以简写为
:
- v-bind就可以实现数据的双向绑定
3.5 指令二:绑定事件监听 v-on
<div id="root">
<h1>事件绑定监听</h1>
<button v-on:click="test">test</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el:"#root", // 指定容器
data:{}, // 用于绑定数据
methods:{ // 用于绑定事件
test(){
alert(111)
}
}
})
</script>
- v-on语法用于绑定vue的事件
- 需要在script里面写一个methods:{}来进行事件的声明
- v-on的缩写形式是
@
3.6 指令三:条件渲染 v-show|v-else-if
<div id="root">
<h1>逻辑判断</h1>
<p v-show="show">我显示了</p>
<p v-show="!show">我没显示了</p>
<p v-if="Math.random()>0.5">you win,l am lose</p>
<p v-else> I am lose ,you win</p>
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
</div>
<script type="text/javascript">
const vm = new Vue({
el:"#root",
data:{
type:'B',
},
</script>
- v-show:根据表达式之真假值 触发显示与否
- v-if:
当和 v-if 一起使用时,v-for 的优先级比 v-if 更高。
v-else可以和v-if搭配使用
,和Java的if-else一样的用法前一兄弟元素必须有 v-if 或 v-else-if。
- v-else-if 前置条件:
必须有 v-if 或 v-else-if
3.7 列表渲染 v-for
列表渲染指令
- 数组:v-for/index
- 对象:v-for/key
<div id="app">
<label>遍历数组</label>
<br>
<span v-for="item in list">{{item}} </span>
<hr>
<label>遍历数组对象</label>
<br>
<li v-for="(user,index) in list1" :key="index">
用户编号:{{user.userid}}--;用户姓名:{{user.username}}--;索引:{{index}}
<button @click="del(index)">删除</button>
<button @click="upd(index,{userid:2,username:'李老头'})">更新</button>
<button @click="add(index,{userid:5,username:'小王'})">添加</button>
</li>
<hr>
<label>遍历对象</label>
<br>
<li v-for="(value,key,index) in list2">对象的键:{{key}}--;对象的值:{{value}}-- ;索引:{{index}}</li>
</div>
<script>
var vm = new Vue({
// vue本身是监视list1的改变 而非监视的是list1内部的内容
// vue重新给了数组中一些列改变数组内部数据的方法
// 逻辑:先调用原生的 在更新页面--->数组内部改变
el: '#app',
data: {
list: [1, 2, 3, 4, 5, 6, 7, 8],
list1: [
{userid: 1, username: 'zs1'},
{userid: 2, username: 'zs2'},
{userid: 3, username: 'zs3'},
{userid: 4, username: 'zs4'}
],
list2: {
id: 1232,
name: '托尼.琼斯',
gender: 'female'
}
},
methods:{
del(index){
this.list1.splice(index,1)
},
upd(index,obj){
console.log(this.list1[index].userid,this.list1[index].username)
// this.list1[index] = obj // 并没有改变list1本身,数组内部发生了变化,但是并没调用变异方法,所有vue不会更新页面
this.list1.splice(index,1,obj)
},
add(index,obj){
this.list1.splice(index+1,0,obj)
}
}
});
</script>
注意: Vue重写了数组中改变数组内部数据的一些方法,并取名为变异方法
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
【小结】:如上例,当我在修改一个数组的元素的时候,当我们使用this.list1[index] = obj的时候,其实时将数组中的内部的数据改了,但是这样并没有让list1知道,因为并没有调用变更方法。所以页面数据不会变
3.7.1 列表过滤和排序案例
<div id="app">
<label for="condition">过滤条件</label>
<input type="text" id="condition" placeholder="请输入过滤条件"
v-model="queryByName">
<ul>
<li v-for="(p,index) in filterPersons" :index="index">
{{p.username}}--{{p.age}}
</li>
</ul>
<button @click="updateOrderType(1)">年龄升序排序</button>
<button @click="updateOrderType(-1)">年龄降序排序</button>
<button @click="updateOrderType(0)">原本排序</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
orderType: 0, // 0表示原本顺序 ;1代表升序 ;-1代表降序
persons: [
{userid: 1, username: 'Tom', age: 21},
{userid: 2, username: 'Jack', age: 45},
{userid: 3, username: 'Rose', age: 23},
{userid: 4, username: 'Kappy', age: 21},
{userid: 5, username: 'Sendy', age: 18},
{userid: 6, username: 'Loray', age: 36},
{userid: 7, username: 'Jessay', age: 39},
{userid: 8, username: 'Navie', age: 28},
],
queryByName: '',
},
methods:{
updateOrderType(orderType){
this.orderType = orderType;
}
},
computed: {
filterPersons() { // 过滤条件后新的数组对象
// 取出相关的数据
const {queryByName, persons, orderType} = this
// 最终需要显示的数组
let fpersons;
// 对persons进行过滤
fpersons = persons.filter(ps => ps.username.indexOf(queryByName) !== -1);
// 排序
if (orderType !== 0) {
// 排序函数 sort 传入对比对象
fpersons.sort(function (p1, p2) { // 如果返回负p1在前,代表升序
// 升序 1 降序 -1
if (orderType == 1) {
return p1.age-p2.age;
} else {
return p2.age - p1.age;
}
})
}
return fpersons;
}
}
});
</script>
3.8 表单数据交互 v-model🔥🔥
v-model指令可以在表单 input、textarea以及select元素上创建双向数据绑定;
3.8.1 v-model的原理
官方有说到,v-model的原理其实是背后有两个操作:
- v-bind绑定value属性的值;
- v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;
<input v-model="Text" type="text"/>
<!--等效于-->
<input type="text" :vlaue="Text" @input="Text=$event.target.value">
- v-model 绑定textarea的时候,其绑定的数据即为输入的文本内容
- v-model 绑定checkbox的时候
- 选中单个复选框:数据是布尔类型,选中则为true,否则为false
- 选中多个复选框:对应的data是一个数组
- v-model绑定select下拉列表
- 选中一个下拉列表:数据时该列表的value值
- 选中多个下来列表:数据是选中的列表的value组成的数组
- v-model绑定radio的时候,数据即为选中的value值
<div id="root">
<div>
男<input type="radio" value="male" v-model="gender">
女<input type="radio" value="female" v-model="gender">
<span>当前的性别是:{{gender}}</span>
</div>
<div>
<select name="" id="" v-model="hobbies" multiple>
<option value="苹果">苹果</option>
<option value="栗子">栗子</option>
<option value="西瓜">西瓜</option>
<option value="香蕉">香蕉</option>
</select>
<span>当前选中的:{{hobbies}}</span>
</div>
</div>
四、计算属性和监听
4.1 效果
4.2 计算属性🔥🔥
说的通俗一点:就是相互依赖
一个数据, 依赖另外一些数据计算而来的结果
<div id="app">
姓:<input type="text" placeholder="First Name" v-model="firstName"><br>
名:<input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向):<input type="text" placeholder="Full Name1" v-model="fullName"><br>
姓名2(单向):<input type="text" placeholder="Full Name2" v-model="fullName1"><br>
姓名3(双向):<input type="text" placeholder="Full Name3"><br>
</div>
<script>
Vue.config.productionTip = false;
var vm = new Vue({
el: "#app",
data: {
firstName: "A",
lastName: 'B',
fullName: 'A B'
},
computed: { // 计算属性 相当于是一个函数一样 可以监听
// 什么时候执行:初始化显示/相关的data属性发生变化
fullName1() {//计算属性的一个方法 返回一个值作为属性值
return this.firstName + ' ' + this.lastName // 会将值存入缓存中 只要first Name或者lastName中任意一个改变,则重新计算
}
}
})
</script>
- 计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。
- 给计算属性赋值:需要使用set:set接受赋予的值
- 返回结果需要用到get
export default {
computed: {
fullName2: {
set(val) {
console.log(val)
},
get() { // 计算并返回当前属性的值
return this.firstName + ' ' + this.lastName
}
}
}
}
4.3 监听属性
watch: { [key: string]: string | Function | Object | Array }
一个对象,键是需要观察的表达式,值是对应回调函数。
值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个 property。
<div id="app">
姓:<input type="text" placeholder="First Name" v-model="firstName"><br>
名:<input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名2监视(单向):<input type="text" placeholder="Full Name2" v-model="fullName2"><br>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: "#app",
data: {
firstName: "A",
lastName: 'B',
fullName: 'A B',
},
watch: { // 配置监视
firstName: function (value) { // first的值发生变化 需要修改fullName1
this.fullName2 = value + ' ' + this.lastName
}
}
})
// 监听方法 $开头的
vm.$watch('lastName',function (newVal) {
console.log(this) // vue的实例对象vm
this.fullName2 = this.firstName+' '+newVal
})
</script>
vm.$watch( expOrFn, callback, [options] )
- 参数:
- {string | Function} expOrFn :监视的对象
- {Function | Object} callback :回调函数 监视对象发生变化时的操作
- {Object} [options]
- {boolean} deep :为true时表示发现监听监听对象发生化,默认是true
- {boolean} immediate :为true时,立即触发回调
4.3.1 深度监听 deep
<!--view层 模板-->
<div id="app">
<p>{{num.a}}</p>
<button @click="num.a++">点我a+1</button>
<p>{{num.b}}</p>
<button @click="num.b++">点我b+1</button>
</div>
</body>
<!--导入js-->
<script src="./js/vue.js"></script>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: "#app",
data: {
num:{
a:1,
b:1,
}
},
methods: {},
watch: {
//监视多级结构中所有属性的变化
num:{
deep:true,
handler(){
console.log('a的值改变了',this.num.a)
console.log('b的值改变了',this.num.b)
}
}
}
})
</script>
【小结】
Vue所提供的深度监听属性,可以帮助我们监听一些层级比较深的值,比如说一个对象、多级数组等。
- vue默认是不支持深度监听的,只有我们设置了
deep:true
才会监视深层的对象数据 - 我们在使用数据监听的时候,根据需要配置是否开启深度监听
- 但是监听一般没有计算属性好用(个人认为),但是功能比较灵活。
4.4 计算属性高级
🔥🔥计算属性存在缓存,多次读取相同的条件表达式只执行一次getter计算
<div id="app">
姓:<input type="text" placeholder="First Name" v-model="firstName"><br>
名:<input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名3(双向):<input type="text" placeholder="Full Name3" v-model="fullName3"><br>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: "#app",
data: {
firstName: "A",
lastName: 'B',
fullName: 'A B',
},
computed: { // 计算属性 相当于是一个函数一样 可以监听
fullName3: {
get() {
return this.firstName + " " + this.lastName
},
set(value) {
const names = value.split(" ")
this.firstName = names[0]
this.lastName = names[1]
}
}
}
})
</script>
五、class和style的绑定
5.1 效果
5.2 理解
- 在应用界面中,某个元素的样式是变化的
- class/style绑定就是专门来实现动态样式效果的技术
5.3 class绑定
【绑定语法】::class=xxx
- xxx是一个字符串
- xxx是一个对象
- xxx是一个数组
<div id="root">
<h2>1.Class绑定::class='xxx'</h2>
<!--绑定的是个字符串-->
<h4>xxx是字符串</h4>
<p :class="bgRed">背景色红色</p>
<button @click="update">切换为粉色背景,字号30px</button>
<!--绑定的只是一个对象-->
<hr>
<h4>xxx是对象</h4>
<!--对象名:是一个类名:值是布尔类型 为true显示,否则不显示-->
<p :class="{red:isRed,pink:isPink}">背景色红色</p>
<button @click="update2">切换为粉色背景,字号30px</button>
<hr>
<h4>xxx是数组</h4>
<p :class="['red','pink']">背景色红色</p>
</div>
<script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
bgRed: 'red',
isRed: true,
isPink: false,
},
methods: {
update() {
this.bgRed = 'pink font30'
},
update2() {
this.isRed = false
this.isPink = true
},
}
})
</script>
<style type="text/css">
#root {
color: darkgreen;
}
.red {
background-color: red;
}
.pink {
background-color: pink;
font-size: 30px;
}
</style>
5.4 style绑定
【绑定语法】::style="{color:‘red’,backgroundColor:activeBgc,....}"
其中的activeBgc是一个data属性
<div id="root">
<h2>1.style绑定</h2>
<p :style="{fontSize:'30px',width:width,height:height,backgroundColor:bgc}">111</p>
<button @click="update3">点我改变</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el: "#root",
data: {
width:'100px',
height:30,
bgc:'skyblue'
},
methods: {
update3(){
this.width = '200px'
this.height= 45
this.bgc = 'yellow'
}
}
})
</script>
六、事件处理
6.1 绑定监听 v-on
可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
前面讲过,这里主要介绍下$event
这个属性。
$event
是指当前触发的是什么事件(鼠标事件,键盘事件等)$event.target
则指的是事件触发的目标,即哪一个元素触发了事件,这将直接获取该dom元素
下面是例子:
eve(event){
console.log(event)
}
6.2 事件修饰符
原生JS中,我们在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。但是 这样在vue里仍不时最佳实践
vue提供的:
但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
.stop
:阻止事件冒泡.prevent
:阻止默认的事件发生.capture
:添加事件监听器时使用事件捕获模式.self
:只有当前元素才触发.once
:事件只会被触发一次 [2.1.4新增特性].passive
:告诉浏览器你不i想阻止的事件的默认行为,所以不要和.prevent连用 [2.1.4新增特性]
<div id="root">
<h2>2. 事件修饰符</h2>
<div style="width: 200px;height: 200px;background-color: red;" @click="test2">
<div style="width: 100px;height: 100px;background-color: blue;" @click.stop="test3">
</div>
</div>
<a href="http://www.baidu.com" @click.prevent="testa($event)">百度</a>
</div>
<script>
Vue.config.productionTip = false;
// 创建Vue实例
const vm = new Vue({
el: '#root',
data: {},
methods: {
test2() {
alert("out")
},
test3(event) {
alert("in")
// event.stopPropagation() // 原生的方式
},
testa(event){
// 阻止默认提交事件
// event.preventDefault()
alert(111)
},
}
});
</script>
6.3 按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
<input v-on:keyup.page-down="onPageDown">
在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
我认为Vue的人性化的一点,帮我们声明了一些常用的按键别名
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
<div id="root">
<h2>3. 按键修饰符</h2>
<button @click="eve($event)" name="哈哈">单击</button>
<input type="text" @keyup.13="enter" placeholder="按下enter(13)弹出提示">
<input type="text" @keyup.space="enter" placeholder="按下space弹出提示">
<input type="text" @keyup.65="enter" placeholder="按下a弹出提示">
<input type="text" @keyup.enter="enter" placeholder="按下enter弹出提示">
</div>
<script>
Vue.config.productionTip = false;
// 创建Vue实例
const vm = new Vue({
el: '#root',
data: {},
methods: {
enter(event){
// enter键的ascii码为13
// if (event.keyCode === 13) {
// alert(event.target.value)
// } // 原生写法
alert(event.target.value)
}
}
});
</script>
七、Vue实例生命周期
7.1 效果
7.2 生命周期流程图
官网为我们提供了一个Vue实例的生命周期流程图
7.3 生命周期分析
【流程分析】:
- 当我们new Vue()的时候,首先在初始化之前有一个beforeCreate,就是在初始化生命周期之前的一些比如说参数的设置等操作。
- 在早一些的版本中,在beforeCreate之后还有一个observe监视的环节,目的就是用于监视数据的变化(set)
- 初始化后,也就是created之后,进入一个判断,判断有没有
el
有的话在判断有没有template
这个东西。没有el
的话需要我们手动配置vm.$mount(el)
- 在判断是否有template中,如果没有则
在内存中先编译
我们绑定的内部的el容器里的所有模板元素;有的话则直接在内存中编译已有模板元素
并渲染进一个函数中 - 将内存中编译好的数据,在mounted挂载到页面上。在挂在之前有一个beforeMount,在挂载之后有一个
mounted。
至此,第一个阶段,初始化就完毕
- 当数据被挂载到页面了之后,当数据发生了变化之后,我们需要对页面进行更新操做,这时候,我们就需要用到update方法,同理,在更新之前有一个beforeUpdate,在更新之后有一个updated方法
- 最后一个阶段:死亡,这里和React不一样的是,此时的页面数据仍然会在,但是,此时的VM已经不起作用了
7.4 常用的生命周期方法
【小结】
vue对象的声明周期:
- 初始化显示
- beforeCreate()
- created()
- beforeMount()
- mounted()
- 更新显示:this.xxx = value 修改数据的操做
- beforeUpdate()
- updated()
- 销毁Vue是对象,vm.$destroy()
- beforeDestroy()
- destroyed()
【案例演示】
<div id="root">
<button @click="destroyVm">按钮--destory vm</button>
<p v-show="isShow">尚硅谷Vue2.x教程</p>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
isShow:true
},
methods: {
destroyVm(){
this.$destroy()
}
},
// 初始化阶段
beforeCreate(){
console.log("beforeCreate执行了")
},
created(){
console.log("Created执行了")
},
beforeMount(){
console.log("beforeMount执行了")
},
mounted(){
console.log("mounted执行了")
this.timer = setInterval(()=> { // 初始化显示之后立即调用一次 使用匿名函数 否则this变成window
console.log("-------")
// 匿名函数的特点是本身没有this 所以这里的this就是vm
this.isShow=!this.isShow
},1000)
},
// 更新阶段
beforeUpdate(){
console.log("beforeUpdate执行了")
},
update(){
console.log("update执行了")
},
// 销毁阶段
beforeDestroy(){ // 销毁之前调用一次
console.log("beforeDestroy执行了")
clearInterval(this.timer)
},
destroyed(){
console.log("销毁方法执行了")
}
})
</script>
常用的Vue声明周期函数:
mounted()
:发送Ajax请求,启动定时器等异步操作,在后面我们使用Axios完成异步请求的发送的时候,就用到mounted方法。
beforeDestroy()
:收尾工作,如:消除定时器等
八、过度与动画
8.1 Vue动画的理解
记住一点:世界的本质就是套娃,任何高大上的技术都离不开最原始的技术。
- vue的动画操做实际上就是对Css的Trasition或者animation的封装
- 动画的产生就是在起始的时候加一个样式,在切换另一个事件过渡期间,再换上另外一个终止样式,Vue也不例外。
- 过渡的相关类名:
- xxx-enter-active: 指定显示的transition
- xxx-leave-active: 指定隐藏的transition
- xxx-enter/xxx-leave-to: 指定隐藏时的样式
8.2 官网案例分析
【单元素组件过渡】
<div id="root">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="myTransition">
<p v-if="show">hello</p>
</transition>
</div>
<style type="text/css">
/*这里是什么意思???*/
.myTransition-enter-active, .myTransition-leave-active {
transition: opacity .5s;
}
.myTransition-enter, .myTransition-leave-to /* .myTransition-leave-active below version 2.1.8 */ {
opacity: 0;
}
</style>
<script src="js/vue.js"></script>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el:"#root",
data(){
return {
show:true
},
})
</script>
🙅🙅🙅在看源码的初期,我们可能会有这样一个疑问,css样式里的代码我好像熟悉,但是又不熟悉,哈哈哈哈,这难道就是最熟悉的陌生“人”么❓❓❓
8.2.1 分析
对于这些在过渡中切换的类名来说,如果你使用一个没有名字的
<transition>,则 v- 是这些类名的默认前缀。
🔥🔥🔥:如果你使用了<transition name="my-transition">
,那么v-enter
会替换为my-transition-enter。
,比如我在案例中将transition的name属性修改为了myTransition则后续的所有xxx将被替换为myTransition
v-enter-active 和 v-leave-active 可以控制进入/离开过渡的不同的缓和曲线
,在下面章节会有个示例说明。
搞清楚之一点之后,我们回过头来再看之前那段那一理解的代码🧧
将他拆分成两部分,❤️红色区域和 💚绿色区域
- ❤️ 两个类名 分别是
进入和离开的过程中
的过渡动画 含义是一个持续时间为0.5s的透明动画 - 💚 两个类名,分别是
进入之前
和离开之后
透明度为0 也就是隐藏时的样式
这么一看,嗨嗨,原来如厕儿🕵️
8.3 基本动画的步骤
- 在目标的元素外包裹<transition name=“xxx”>
- 定义class样式
- 指定过渡样式 transition
- 指定隐藏时的样式 opacticy / 其他
8.4 Vue的animation
CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在animationend 事件触发时删除。
<div id="root">
<button @click="Change=!Change">text Change</button>
<transition name="textChange">
<p v-if="Change" id="div">富裕国家古迹看</p>
</transition>
</div>
<style type="text/css">
/*显示/隐藏的过渡效果*/
.textChange-enter-active {
animation: fade-big .5s;
}
.textChange-leave-active {
animation: fade-big .5s reverse;
}
@keyframes fade-big {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
/*隐藏式的样式*/
.textChange-enter, .textChange-leave-to {
opacity: 0;
}
button {
margin: 10px 0;
}
#div {
width: 600px;
height: 100px;
background-color: orangered;
}
</style>
<script src="js/vue.js"></script>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data() {
return {
Change: true,
}
},
})
</script>
九、过滤器
Vue的过滤器:是对我们要显示的数据进行格式化的一个技术点
9.1自定义过滤器
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind
表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
9.1.1 语法格式
- 定义过滤器
<script>
Vue.filter(filterName,function(value[,arg1,arg2,...]){
// 进行一定的数据处理
return newValue;
)
</script>
- 使用过滤器
<!-- 在双花括号中 -->
{{ message | filterName}}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | filterName(args)"></div>
先来看如何定义过滤器,从官网给出的实例我们可以知道filter是Vue的方法,但是你会发现有点怪 为什么是Vue.filter,那么就要把Vue的过滤器分一下类了:
- 全局过滤器:全局过滤器是通过Vue.filter()来定义的,
定义好后,它在所有组件中都可以使用。
- 组件过滤器:定义在组件内部
filters
属性上.它只能在此组件内部使用,有时也叫做局部过滤器。
【全局过滤器】
Vue.filter('filterName', function (value,...args) {
// 相关的处理
// 返回一个格式化好的数据
return newValue; // 返回的新值
});
filterName
是过滤器名称。函数第一个参数value
是需要过滤的数据。函数第二个参数args
是给过滤器传递的值,是一个可变形参。
【局部过滤器】
var app = new Vue({
el: '#app',
data: {
oldValue: '原始数据'
},
methods: {},
// 定义组件过滤器
filters: {
// 过滤器需要处理的方法
priceFmt(val,...args) {
return newValue;
}
}
})
注意: 在局部过滤器中使用的
filters
需要加上s
。而全局过滤器是filter
9.1.2 案例格式化时间
<div id="root">
<h1>显示日期格式化</h1>
<p>原始的时间格式:{{date}}</p>
<p>格式化的时间格式:{{date | dateFilter}}</p>
<p>格式化的时间格式:{{date | dateFilter('YYYY年MM月DD日')}}</p>
<p>格式化的时间格式:{{date | dateFilter('HH时mm分ss秒')}}</p>
</div>
<script src="js/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.3/moment.js"></script>
<script type="text/javascript">
// 这里的value参数是我们即将要格式化的时间数据
Vue.filter('dateFilter', function (value,format) {
// 格式化时间 moment库 一个js的时间库
// 返回一个格式化好的数据
return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss');
});
Vue.config.productionTip = false;
const vm = new Vue({
el:"#root",
data:{
date:new Date()
}
})
</script>
这里应用了一个时间的javaScript库—moment库
moment官网地址:http://momentjs.cn/
9.2 过滤器应用场景
- 单位转换
- 数字打点
- 文本格式化
- 时间格式化
- 货币格式化
- …