自定义指令directives
对底层dom进行操作的封装,目前封装一个自定义指令,作用是:谁用这个指令就会变成对应的颜色。
Examples
11111111
22222222
333333333333333
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:卸载的时候会执行。
指令钩子函数会被传入以下参数:
(inserted(el,bind,newVnode,oldVnode)
)
-
el
:指令所绑定的元素,可以用来直接操作 DOM。 -
binding
:一个对象,包含以下 property:-
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
钩子中可用。
指令函数的简写
Examples
11111111
22222222
333333333333333
再举一个例子:
也可以如下编写:
指令轮播
Examples
轮播-nextTick
直接解决(避免)了swiper初始化过早的问题。并且防止了多次反复执行指令勾子函数更新的问题。
Examples
过滤器
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。
首选准备一个加载数据json文件。
{
"coming": [],
"movieIds": [248172, 1218727, 346629, 1228776, 1239544, 672279, 1211727, 1230152, 1211412, 672379, 1205909, 1234116,
883196, 1243904, 1207260, 1263355, 1239281, 476263, 1212492, 1217701, 1237437, 1162868, 346765, 1229702,
1239844, 337896, 1216383, 507792, 1167831, 1206939, 248123, 245881, 1206415
],
"stid": "576591972453269000",
"stids": [{
"movieId": 248172,
"stid": "576591972453269000_a248172_c0"
}, {
"movieId": 1218727,
"stid": "576591972453269000_a1218727_c1"
}, {
"movieId": 346629,
"stid": "576591972453269000_a346629_c2"
}, {
"movieId": 1228776,
"stid": "576591972453269000_a1228776_c3"
}, {
"movieId": 1239544,
"stid": "576591972453269000_a1239544_c4"
}, {
"movieId": 672279,
"stid": "576591972453269000_a672279_c5"
}, {
"movieId": 1211727,
"stid": "576591972453269000_a1211727_c6"
}, {
"movieId": 1230152,
"stid": "576591972453269000_a1230152_c7"
}, {
"movieId": 1211412,
"stid": "576591972453269000_a1211412_c8"
}, {
"movieId": 672379,
"stid": "576591972453269000_a672379_c9"
}, {
"movieId": 1205909,
"stid": "576591972453269000_a1205909_c10"
}, {
"movieId": 1234116,
"stid": "576591972453269000_a1234116_c11"
}],
"total": 33,
"movieList": [{
"id": 248172,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "v3d imax",
"nm": "复仇者联盟4:终局之战",
"preShow": false,
"sc": 9.1,
"globalReleased": true,
"wish": 1849927,
"star":"王麻子",
"rt": "2019-04-24",
"showInfo": "今天107家影院放映3177场",
"showst": 3,
"wishst": 0
}, {
"id": 1218727,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "何以为家",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 94818,
"star":"王麻子",
"rt": "2019-04-29",
"showInfo": "2019-04-29 下周一上映",
"showst": 4,
"wishst": 0
}, {
"id": 346629,
"haspromotionTag": false,
"img":"http://w.h/xxxxxx",
"version": "v3d imax",
"nm": "大侦探皮卡丘",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 181370,
"star":"王麻子",
"rt": "2019-05-10",
"showInfo": "2019-05-10上映",
"showst": 4,
"wishst": 0
}, {
"id": 1228776,
"haspromotionTag": false,
"img":"http://w.h/xxxxxx",
"version": "",
"nm": "下一任:前任",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 284385,
"star":"王麻子",
"rt": "2019-05-01",
"showInfo": "2019-05-01 下周三上映",
"showst": 4,
"wishst": 0
}, {
"id": 1239544,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "调音师",
"preShow": false,
"sc": 9.1,
"globalReleased": true,
"wish": 14608,
"star":"王麻子",
"rt": "2019-04-03",
"showInfo": "今天60家影院放映155场",
"showst": 3,
"wishst": 0
}, {
"id": 672279,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "雪暴",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 24301,
"star":"王麻子",
"rt": "2019-04-30",
"showInfo": "2019-04-30 下周二上映",
"showst": 4,
"wishst": 0
}, {
"id": 1211727,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "反贪风暴4",
"preShow": false,
"sc": 9.1,
"globalReleased": true,
"wish": 161080,
"star":"王麻子",
"rt": "2019-04-04",
"showInfo": "今天55家影院放映129场",
"showst": 3,
"wishst": 0
}, {
"id": 1230152,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "撞死了一只羊",
"preShow": false,
"sc": 8,
"globalReleased": true,
"wish": 8422,
"star":"王麻子",
"rt": "2019-04-26",
"showInfo": "今天38家影院放映81场",
"showst": 3,
"wishst": 0
}, {
"id": 1211412,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "v3d",
"nm": "神奇乐园历险记",
"preShow": false,
"sc": 8.8,
"globalReleased": true,
"wish": 4779,
"star":"王麻子",
"rt": "2019-04-19",
"showInfo": "今天39家影院放映63场",
"showst": 3,
"wishst": 0
}, {
"id": 672379,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "v3d",
"nm": "悟空奇遇记",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 11472,
"star":"王麻子",
"rt": "2019-05-01",
"showInfo": "2019-05-01 下周三上映",
"showst": 4,
"wishst": 0
}, {
"id": 1205909,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "祈祷落幕时",
"preShow": false,
"sc": 9,
"globalReleased": true,
"wish": 11057,
"star":"王麻子",
"rt": "2019-04-12",
"showInfo": "今天16家影院放映40场",
"showst": 3,
"wishst": 0
}, {
"id": 1234116,
"haspromotionTag": false,
"img":"http://128.180/xxxxxx",
"version": "",
"nm": "猫公主苏菲",
"preShow": false,
"sc": 0,
"globalReleased": false,
"wish": 6533,
"star":"王麻子",
"rt": "2019-05-01",
"showInfo": "2019-05-01 下周三上映",
"showst": 4,
"wishst": 0
}]
}
Examples
-
{{data.nm}}
{{ data.img | kerwinpath }}
过滤器其实就是一种函数写法,把第一个参数写到|
符号前面,如果还有其他参数,就写到函数名的后面。只不过这个函数方法必须写到filers
中。
过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,capitalize 过滤器函数将会收到 message 的值作为第一个参数。
过滤器可以串联:
{{ message | filterA | filterB }}
在这个例子中,filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。
相当于:
function filterB (function filterA (message ))
过滤器是 JavaScript 函数,因此可以接收参数:
{{ message | filterA('arg1', arg2) }}
这里,filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
相当于:
function filterA(message ,'arg1',arg2)
传送门Teleport
如下例子,比如想点击按钮给页面增加一个蒙层。
lesson 30
点击按钮出现如下情况:
因为在css样式
mask
中,absolute
绝对定位是相对父元素的,所以遮罩和上下左右移动都不会超出area
标签的范围。如果想要在组件内实现全遮罩的效果,这时候就需要用到传送门Teleport:
lesson 30
效果如下:
render函数
如下代码:
lesson 31
如何把如上代码写得更加优雅,修改组件代码:
render function
template -> render -> h -> 虚拟DOM(JS对象)-> 真实 DOM -> 展示到页面上
app.component('my-title', {
props: ['level'],
render() {
//创建一个vue的h函数
const { h } = Vue;
//这是一个虚拟DOM。返回一个h函数的返回值,传递的第一个参数是标签名,第二个参数为标签的自定义或者自带的属性和属性值,第三个参数为具体标签内的内容。
//这里通过` this.$slot `获得各式各样的插槽,这里我们没有具体指向,想使用默认插槽,语法就是` this.$slots.default()`。
//这里第三个参数可以写成一个数组,相当于往下无限地嵌套的js对象。
return h('h' + this.level, {}, [
this.$slots.default(),
h('h4', {}, 'dell')
])
}
})
我们在组件中写的template 都会被编译成render。
插件
我们都知道vue有很多第三方插件,那么插件的基本原理是什么?
mixin可以对代码进行很好的封装,但是使用插件的功能,能进行更好的封装。
比如定义一个myPlugin的插件:
一定要定义一个install方法,这是插件走的一个必备逻辑。
const myPlugin = {
//支持2个参数:app:根实例,有这个可扩展任何想要的实例。
//options:额外的参数会传到options中
install(app, options) {
})
使用插件:
// plugin 插件, 也是把通用性的功能封装起来
const myPlugin = {
//支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
//options:额外的参数会传到options中
install(app, options) {
})
})
}
}
const app = Vue.createApp({
template: `
`
});
app.component('my-title', {
template: `hello world`
})
app.use(myPlugin, { name: 'dell'});
既然得到app的实例,那么可以进行很多操作,比如设置全局变量:
// plugin 插件, 也是把通用性的功能封装起来
const myPlugin = {
//支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
//options:额外的参数会传到options中
install(app, options) {
app.provide('name', 'Dell Lee');
})
})
}
}
const app = Vue.createApp({
template: `
`
});
app.component('my-title', {
inject: ['name'],
template: `{{name}}`
})
app.use(myPlugin, { name: 'dell'});
也可以扩展自定义指令:
// plugin 插件, 也是把通用性的功能封装起来
const myPlugin = {
//支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
//options:额外的参数会传到options中
install(app, options) {
app.provide('name', 'Dell Lee');
})
app.directive('focus', {
mounted(el) {
el.focus();
}
})
})
}
}
const app = Vue.createApp({
template: `
`
});
app.component('my-title', {
inject: ['name'],
template: `{{name}}`
})
app.use(myPlugin, { name: 'dell'});
也可以扩展其他内容:
lesson 32
对数据做校验的插件编写
lesson 33