v-model修饰符:
- .number:转换成数字型
- .trim:去掉前后空格
- .lazy:把input事件切换为change事件
当前已学指令:
- v-cloak 防止页面加载时出现vuejs的变量名
- v-text 解决差值表达式闪烁问题
- v-html 渲染HTML
- v-pre 不渲染直接显示
- v-once 渲染一次
- v-model 双向数据绑定
- v-on 绑定事件
- v-bind 绑定属性
- v-if、v-else-if、v-else 条件渲染
- v-for 列表渲染
- v-show 控制显示隐藏
自定义指令:
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
自定义指令名称有多个单词,在定义时用小驼峰,如:Vue.directive(‘sayHello’, { … }),在html元素上使用时用短横线,如:
全局指令和局部指令:
- 通过Vue.directive定义的指令称为全局指令
- 通过new Vue({ …, directives: { … } })定义的指令称为局部指令
- 补充说明:一个Vue实例就是一个组件,局部指令只能在本组件内可用,全局指令在所有组件中都可用
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
//注册局部指令
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
钩子函数
一个指令定义对象可以提供如下几个钩子函数
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
bind 和 inserted 的区别
bind在inserted之前
bind 时父节点el.parentNode为 null
inserted 时父节点el.parentNode存在。
bind是在vue编译解析dom之前调用,inserted在vue编译解析完dom后调用
- 注意:在钩子函数内部的this不是vm实例,可以通过第三个参数vnode.context获取到vm实例
- 特别要注意:指令绑定的属性值,是动态属性绑定,会经过Vue的编译解析
在钩子函数内部可以通过第二个参数binding的value属性,获取到指令绑定的参数 - 在钩子函数内部可以通过第二个参数binding的value属性,获取到指令绑定的参数
- 指令的修饰符可以用来做一些特定的逻辑判断处理
钩子函数参数 - el:指令所绑定的元素,可以用来直接操作 DOM
- binding:一个对象,包含以下属性:
- name:指令名,不包括 v- 前缀
- value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用
- expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”
- modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true,bar: true }
- vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
注意:除了 el 之外,其它参数都应该是只读的,切勿进行修改
计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护
对于任何复杂逻辑,都应当首先使用计算属性
<div id="app">
<input type="text" name="" id="" v-focus.hh='user' v-model='user.name'>
<div>{{ rendeget }}</div>
</div>
new Vue({
el: '#app',
data: {
user: {
name: 'zs',
age: 18,
sex: '男',
color: 'red'
},
styleObj: {
color: 'red'
}
},
computed: {
rendeget: function () {
return this.user.name.split('').reverse().join('')
}
},
})
使用注意点:
- 都定义在computed选项中
- 每个计算属性就是一个函数,函数的返回值就是该计算属性的值
- 在模板中使用计算属性时,不需要加小括号调用(加了会GG),直接把函数名当做data使用就阔以
- 计算属性时依赖数据动态计算值的,也就是说,以来的数据变了,计算属性的值就会跟着变
计算属性和方法的区别
- 计算属性有缓存(基于所依赖的数据,当数据没有发生变化时,多次使用,用的是已缓存的数据,只有当所依赖的数据发生变化后,才会重新计算)
- 方法木有缓存,多次使用都会调用执行内部的代码
- 如果不希望有缓存,请用方法来替代
侦听器:
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的(适合处理异步操作)
注意:侦听器的名字必须和数据名一致
侦听器和计算属性的区别:
- 计算属性的值是需要同步的返回,而侦听器是不需要返回值的
- 计算属性里面不适合做异步操作,而侦听器就适合
- 使用场景:
- 如果没有异步操作,又需要根据数据的变化计算出一个结果,就用计算属性
- 如果有异步操作,或仅需要根据数据的变化响应某种操作,就用侦听器
侦听器和blur事件的区别:侦听器只有当数据真正发生变化时才会触发函数,而blur事件不管数据有没有发生变化(只要失去焦点)都会触发事件处理函数
例如:
<body>
<div id="app">
<div>
<span>用户名:</span>
<span>
<input type="text" v-model.lazy='uname'>
</span>
<span>{{tip}}</span>
</div>
</div>
</body>
<script src="./js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
uname: '',
tip: ''
},
methods: {
chanme: function (uname) {
var that = this
setTimeout(() => {
if (uname === 'admin') {
this.tip = '用户名重复'
} else {
this.tip = '验证通过'
}
}, 200) // 模拟接口调用
}
},
watch: {
uname: function (val) {
this.chanme(val)
this.tip = '正在验证...'
}
},
})
</script>
过滤器:
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 第一个参数是原数据,第二个参数是处理函数(处理函数返回值就是最终渲染显示的值) -->
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
通过Vue.filter定义全局过滤器,通过new Vue({ fitlers: {} })定义局部过滤器
语法:Vue.filter('uppercase', function (originVal) { return newVal })
- 第一个参数是过滤器名称
- 第二个参数是处理函数
- 处理函数的第一个参数是被过滤的源数据
- 处理函数的返回值,就是最终过滤后的值
比如日期处理的过滤器:
定义:Vue.filter('dateformat', (originVal, pattern) => dateformat(originVal, pattern))
使用:<div>{{ user.regAt | dateformat('yyyy-MM-dd hh:mm:ss') }}</div>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{ user.date | Format('yyyy-MM-dd hh:mm:ss') }}</div>
</div>
</body>
<script src="./js/vue.js"></script>
<script>
Vue.filter('Format', (value, arg) => {
function dateFormat(date, format) {
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\)\/)/);
if (mts && mts.length >= 3) {
date = parseInt(mts[2]);
}
}
date = new Date(date);
if (!date || date.toUTCString() == "Invalid Date") {
return "";
}
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小时
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
var v = map[t];
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v;
v = v.substr(v.length - 2);
}
return v;
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return format;
}
return dateFormat(value, arg);
})
var vm = new Vue({
el: '#app',
data: {
user: {
date: new Date()
}
}
})
</script>
</html>
Vue生命周期钩子:
就是Vue实例从出生到死亡的过程,Vue在一些关键的时间节点都给开发者提供了回调函数
分为四个阶段:
-
创建(只会触发一次):beforeCreate、created
-
挂载(只会触发一次):beforeMount、mounted
-
更新(会触发N次,只要数据有更新就会触发):beforeUpdate、updated
-
销毁(只会触发一次):beforeDestroy、destroyed
注意:所有的生命周期钩子自动绑定 this
上下文到实例中,因此你可以访问数据,对属性和方法进行运算。这意味着你不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos()
)。这是因为箭头函数绑定了父上下文,因此 this
与你期待的 Vue 实例不同,this.fetchTodos
的行为未定义。
1.创建
- beforeCreate函数执行在组件创建之前,在该阶段组件未创建,组件中的data、ref均为undefined
- created函数执行在组件创建完成,但是还未渲染成HTML模板,组件中的data对象已经存在,可以对data进行操作了,ref依旧是undefined,一般我们可以将对数据的初始化和初始化页面的请求放到里面
2.挂载
- beforeMount函数在组件挂载之前,在该阶段页面上还没渲染出HTML元素,data初始化完成,ref依旧不可以操作
- mounted函数是页面完成挂载之后执行的,这时就可以操作ref了,一般会用于将组件初始时请求数据的方法,放到这里面,filter也是在这里生效;
3.更新 - beforeUpdate函数在data更新前时触发,在有特殊需求的情况下,可以将更新之前的数据存起来,放到后面去使用;
- updated函数在data更新之后触发,在数据更新之后做一些处理;
4.销毁
- beforeDestroy函数在组件销毁之前触发,这里的```ref````依旧可以操作;可以在这里做清除定时器的操作
- destroyed函数在组件销毁的时候执行,这里的ref不存在;
Vue数组类型数据操作:
- 变异方法Vue直接支持响应式(数据驱动视图)
- 非变异方法是不支持响应式的,但是可以通过重新赋值达到触发视图更新的目的
- 补充说明:数组的变异方法就是调用完该方法后会影响原数组的方法,反之,不会影响原数组的方法就是非变异方法
Vue自带的修改数据直接支持响应式方法:
- Vue.set(data中的对象或数组, 键名或索引, 值)
- vm.$set(data中的对象或数组, 键名或索引, 值) (推荐使用这种)
- 补充说明:
- 如果能拿到实例对象就用vm.$set,否则就用Vue.set
- vm实例在创建时(created阶段)data中已经存在的对象属性,是支持响应式的,而在后续添加的是不支持响应式的