1.vue自定义指令
概念
自己模拟vue官方实现一个指令
作用
对原生指令的补充和扩展,可以用于定义任何dom操作,并且可以复用
分类
全局自定义指令,可以供整个页面使用
局部自定义指令,只作用于它定义的那个vue实例,
语法
全局自定义指令(绑定到vue上)
Vue.directive('指令名称', 处理函数)
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
// 创建根实例
new Vue({
el: '#app'
})
局部自定义指令(绑定到vue实例上)
new Vue({el:'#app',directives:{指令名称,处理函数}})
new Vue({
el: '#app', // app绑定了,app1没绑定
directives: {
// 注册一个局部的自定义指令 v-focus
focus: {
// 指令的定义
inserted: function (el) {
// 聚焦元素
el.focus()
el.style.color = 'red' // 局部属性,只对绑定的vue实例服务
}
}
}
})
全局属性,每个vue实例都可以共用
局部属性,只对绑定的vue实例服务
钩子函数
钩子函数为在特定事件或者是条件发生的时候被调用的函数
指令定义函数提供了几个钩子函数(可选):
- bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
- inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
- update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
- componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
- unbind: 只调用一次, 指令与元素解绑时调用。
练习:传参数改变样式
<div id="app">
<h1 v-color="'blue'">albedo</h1> <!-- 把blue传到value中,所以传成字符串格式 -->
<p v-color="'pink'">lily</p>
<p v-size="'100'">China</p><!-- 100的单引号可以省略 -->
</div>
<script>
new Vue({
el: '#app',
data: {
},
directives:{
color(el,v){ // el代表添加了指令的元素
console.log(v)
// v其实是对象,传递的颜色在value中
//{name: 'color', rawName: 'v-color', value: 'blue', expression: "'blue'", }
el.style.color = v.value
},
size(el,v){
el.style.fontSize = v.value + 'px'
}
}
})
2.computed计算属性深入
计算属性有两个函数,get用来获取,set用来设置,这里必须用计算属性完整写法
get函数是获取计算属性的值
set函数是设置计算属性的值
完整格式
computed:{属性名:{get(){语句体},set(){语句体}}}
如果只用get函数
computed:{属性名:{方法体}}
<div id="app">
<input type="text" v-model="firstName"><br>
<input type="text" v-model="lastName"><br>
<input type="text" v-model="fullName">
</div>
<script>
new Vue({
el: '#app',
data: {
firstName:'张',
lastName:'三',
fullName:'张三'
},
/* 其实计算属性有两个函数,get用来获取,set用来设置,这里必须用计算属性完整写法 */
computed:{
/* fullName(){
return this.firstName + this.lastName
} */
fullName:{
// get函数是获取计算属性的值
get(){
return this.firstName + this.lastName
},
// set函数是设置计算属性的值
set(value){
console.log(value) // 代表你输入的内容(文本框的值)
this.firstName = value.slice(0,1) // 截取
this.lastName = value.slice(1) // 从索引为1的地方截取到尾
}
}
}
})
3.watch监听属性深入
获取新旧值
想获取新旧值,只需要在函数中添加两个参数,第一个参数代表新值,第二个参数代表旧值(默认使用新值)
watch:{
firstName(newValue,oldValue){ // 接收的两个第一个是新值,第二个是旧值
console.log(newValue)
console.log(oldValue)
this.fullName = this.firstName + this.lastName
},
lastName(newValue,oldValue){
console.log(newValue)
console.log(oldValue)
this.fullName = this.firstName + this.lastName
}
}
监听属性和计算属性的区别
计算属性需要返回数据,在异步操作中不能实现数据的返回
监听属性不需要返回数据,可以用在异步操作中
计算属性弊端
无法处理异步逻辑,比如定时器等
监听属性没有return,可以实现异步需要
定时器里需要用箭头函数,箭头函数中的this代表了vue对象,而普通函数中的this代表window
watch:{
firstName(){
setTimeout(() => {
console.log(this.firstName) // this应该是vue对象
this.fullName = this.firstName + this.lastName
},3000)
},
lastName(){
setTimeout(() => {
console.log(this.lastName) // this应该是vue对象
this.fullName = this.firstName + this.lastName
},3000)
}
}
深度监听
完整格式
watch:{属性名:{handler(newValue,oldValue){函数体},immediate:true,deep:true)}}
<div id="app">
<button @click="count++">按钮</button>
<h1 v-show="show">新中地</h1>
</div>
<script>
new Vue({
el: '#app', // 设置vue接管的区域
data: {
show: false,// 没有对初始值进行监听
count:0
},
watch: { // 监听原始数据,当count值发生改变,执行对应操作
count() {
if (this.count%2 == 0) {
this.show = false
} else {
this.show = true
}
}
}
})
立即监听
正常情况下应该是显示,此处没有显示,因为监听器只在变化的时候监听,没有监听到初始值0
采用监听器完整写法进行监听,在其中使用immediate属性,进行立即监听——设置immediate属性为true,他就可以在页面加载完成后,执行handler函数
简写形式,无法设置其他属性
完整形式,可以设置属性(handler:属性值发生改变会触发的函数)
深度监听
将count的值使用对象{number:0}来表示,则普通监听只能在表面监听到count,无法深度监听到内部的number
解决方式1:将监听对象换成count.number
弊端:如果count里面有很多属性,难以监听
解决方式2:使用deep属性开启深度监听
watch: {
count: {
handler: function () {
if (this.count % 2 == 0) {
this.show = true
} else {
this.show = false
}
},
immediate : true
// 开启深度监听
deep:true
}
}
- 普通监听:直接监听
- 有初始值的监听:immediate : true
- 深度监听:deep:true
4.filter过滤属性
概念
提供管道服务,对数据进行过滤(vue3已废弃)
语法
filters:{函数名或过滤器名(参数){默认第一个参数就是要处理的字符串}}
<div id="app">
<h1>{{msg | toUp}}</h1> <!-- 内容 管道 过滤器 -->
</div>
<script>
new Vue({
el: '#app',
data: {
msg:'xzd'
},
filters: { /* 过滤属性 */
toUp(e){
console.log(e) // 代表xzd
return e.toUpperCase() // 变成大写
}
}
})
5.全局方法和实例方法
概念
Vue 不能检测到对象属性的添加或删除,最好的方式就是在初始化实例前声明根级响应式属性,哪怕只是一个空值。
如果我们需要在运行过程中实现属性的添加或删除,则可以使用全局 Vue,Vue.set 和 Vue.delete 方法。
Vue.set
Vue.set 方法用于设置对象的属性,它可以解决 Vue 无法检测添加属性的限制,语法格式如下:
Vue.set( target, key, value )
this.$set(target, key, value)
- target: 可以是对象或数组
- key : 可以是字符串或数字
- value: 可以是任何类型
Vue.set可以简写为this.$set,其中的this指向的就是new Vue
删除
this.$delete(target, key)
<div id="app">
<button @click="add()">添加属性</button>
<button @click="del()">删除属性</button>
<p>{{stu.name}}</p>
<p>{{stu.age}}</p>
<p>{{stu.gender}}</p>
<p>{{stu.height}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
stu:{
name:'zc',
age:23,
gender:'male'
},
},
methods: {
// 实现添加属性的方法
add(){
// Vue.set(this.stu,'height',180) // 静态方法
this.$set(this.stu,'height',180) // 实例方法
},
// 实现删除属性的方法
del(){
this.$delete(this.stu,'age')
}
}
})
<div id="app">
<ul>
<li v-for="item in num">{{item}}</li>
</ul>
<button @click="sortN()">排序数字</button>
<button @click="reverseN()">翻转顺序</button>
<button @click="filteN()">过滤小于8的值</button>
<button @click="subN()">截取前4个值</button>
<button @click="updateN()">修改第一个值</button>
</div>
<script>
new Vue({
el: '#app',
data: {
num:[3, 15, 10, 1, 19, 32, 20]
},
methods: {
sortN(){
this.num.sort((a , b) => a - b)
},
reverseN(){
this.num = this.num.reverse()
},
filteN(){
this.num = this.num.filter((num) => num > 8)
},
subN(){
this.num = this.num.slice(0 , 3)
},
updateN(){
this.$set(this.num , 0 , 188)
},
}
})
数组push(),pop(),shift(),unshift(),splice(),sort(),reverse()会触发数组的改变,v-for能监测到并更新
slice(),filter(),contact() 或者使用索引修改值,vue监测不到
需要使用Vue.set或者覆盖原数组才能实现