Vue基础知识 -过滤器、样式绑定、slot插槽内容分发
习惯了使用React, 偶尔接手Vue项目,使用的时候有点别扭,故做此笔记,以供时不时查看。
1. 过滤器
插值或绑定表达式。
<p>{{name|formatValue}}</p>
<my-info :name="name|formatValue" />
// ...
export default{
data(){
return {
name:""
}
},
filters:{
formatValue(val){
return val.toLocaleUpperCase()
}
}
}
1.1 全局过滤器与局部过滤器重名时,采用局部过滤器
1.2 可接受多个过滤器,前一个过滤器的结果值作为第一个参数
<p>{{name|formatValue|formatValue2}}</p>
// ...
export default{
data(){
return {
name:""
}
},
filters:{
formatValue(val){
return val.toLocaleUpperCase()
},
formatValue2(val){
return val.substring(1)
}
}
}
1.3 接受额外参数,目标过滤的值为第一个参数
<p>{{name|formatValue("-")}}</p>
// ...
export default{
data(){
return {
name:""
}
},
filters:{
formatValue(val,join){
return val.splice("").join(join)
}
}
}
2. 事件默认参数
通过事件绑定,并可传入指定的其他参数。
<button @click="hanleClick($event,'view')"></button>
$event
则是事件对象。如果是自定义组件,抛出的事件时,为传入的参数。
不需要自定义传入参数时,则监听函数默认接受事件抛出的参数。
<button @click="hanleClick"></button>
//...
export default{
dat(){
return {}
},
methods:{
hanleClick(event){}
}
}
2.1 事件修饰器
事件修饰符定义:
-
.stop
阻止事件冒泡 -
.prevent
阻止事件默认行为 -
.capture
使用事件的捕获模式 -
.self
只在当前元素上触发事件时触发。 -
.once
触发一次事件 -
.passive
监听的事件会立即触发。提升移动端的性能
按键修饰符:.enter \ .tab \ .delete \ .esc \ .space \ .up \ .down \ .left \ .right
. 也可自定义按键修饰符
系统修饰符 :.ctrl \ .alt \ .shift \ .meta
.exact
可以更精确的控制组合按键。
<!-- 按下alt或shift键也会触发点击事件 -->
<button @click.ctrl="handle"></button>
<!-- 仅只有ctrl键会按下才会触发 -->
<button @click.ctrl.exact="handle"></button>
2.2 .native
可以将原生事件绑定到组件上
3. 访问data属性的初始值
通过$optoins
实例属性访问初始化选项。
// 访问 data的初始值
this.$options.data()
4. 手动对某些数据进行监听
通过实例方法$watch
检测一个值或键值表达式的变化。
export default{
data(){
return {
name:""
}
},
mounted(){
this.$watch('name',function(newVal,oldVal){})
}
}
4.1 第一个参数为函数,用于处理更复杂的值得计算
export default{
data(){
return {
firstName:"",
lastName:""
}
},
mounted(){
this.$watch(funtion(){
return this.firstName+this.lastName
},
function(newVal,oldVal){})
}
}
4.2 返回一个取消函数,用来停止触发回调
var unwatch = vm.$watch('a', cb)
// 之后取消观察
unwatch()
4.3 第三个参数配置监听的逻辑处理
this.$watch('name',function(newVal,oldVal){
// ...
},{
// 深度检测,检测对象内部的值
deep:true,
// 立即触发检测变化的回调函数
immediate:true
})
5. 手动调用生命周期
通常我们通过组建的选项定义生命周期,
export default{
data(){
return {}
},
mounted(){},
destory(){}
}
如果我们要即时定义在组建销毁时处理某些事件监听器被销毁或者对象清空
export default{
data(){
return {}
},
mounted(){
let event = new Event()
//
this.$once('hook:beforeDestroy', function () {
event.off()
})
},
destory(){}
}
6. 可动态绑定属性、绑定事件
<template>
<div>
<a :[key]="url" @[event]="handleClick"></a>
</div>
</template>
<script>
export default{
data(){
return {
key:'virtual-href',
url:'',
event:'click'
}
},
mounted(){
// 可以判断URL是否可访问,
let img = new Image()
img.onload = function () {
// 转换为真实的URL地址
this.key = href
}
img.onerror = function () {
// 可备用访问地址
this.url = ""
}
img.src = url
},
methods:{
handleClick(){}
}
}
</script>
7. class 与 style的绑定
7.1 class对象属性绑定。
<div class="box" :class="{active:isActive}" />
可通过对象绑定
<div :class="styleObj" />
// ...
export default {
data(){
return {
isActive:false
}
},
computed:{
styleObj(){
return {
box,
active:this.isActive
}
}
}
}
7.2 数组绑定
多个属性进行绑定
<div :class="[activeClass,errorClass]" />
// ...
export default {
data(){
return {
activeClass:'active',
errorClass:'text-error'
}
},
}
使用三元表达式进行绑定
<div :class="[isActive?activeClass:'',errorClass]" />
// 可数组内使用对象进行绑定
<div :class="[{activeClass:isActive},errorClass]" />
7.3 自定义组件上绑定的class属性会被自动绑定到根元素上
MyTable.vue
<template>
<div class="my-tabl"></div>
</template>
使用自定义组件
<my-table class="table-box" />
// 渲染后, 绑定属性合并
<div class="my-tabl table-box"></div>
7.4 style绑定基本使用class绑定的模式
style绑定可指定浏览器的前缀
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
根据浏览器支持情况,渲染出支持的模式。
7.5 通过inheritAttrs:false
定义阻止属性绑定到根元素上
export default{
inheritAttrs:false
}
对于class和style的绑定,是不生效的。除此之外$attrs
可以绑定到其他子元素上。
8. Props类型定义
props:{
name:String,
// 多个类型定义
value:[String,Number],
// 默认值对象
info:{
type:Object,
default:()=>{}
},
// 自定义验证函数
age:{
validator: function (value) {
// 验证失败时,产生一个警告
return value.match(/^0-9$/)
}
}
}
9. slot 作用于插槽
实现内容分发,用于封装公共组件的关键API。
9.1 默认内容的分发
my-info.vue
<template>
<div>
<p>slot内容分发</p>
<slot></slot>
</div>
</template>
在使用时,组件内部的呢日用会被插槽放置到slot 的位置
<my-info>
<div>
自定义的内容会被放置在slot中
</div>
</my-info>
9.2 当有多个slot内容需要分发时,通过name定义位置名称
通过定义slot
name属性,
<template>
<div>
<p>slot内容分发</p>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
使用时,则通过v-slot
占位空间,放置内容。
<my-info>
<div v-slot:header>
自定义的内容会被放置在slot中 header处。
</div>
</my-info>
v-slot:header
可简写 为#header
<my-info>
<div #header>
自定义的内容会被放置在slot中 header处。
</div>
</my-info>
9.3 作用于插槽,访问子组件中的数据
<template>
<div>
<p>slot内容分发</p>
<slot v-bind:params="user"></slot>
</div>
</template>
在使用时,通过v-slot获取到绑定的属性
<my-info>
<div v-slot="{params}">
自定义的内容会被放置在slot中 - {{params.name}}
</div>
</my-info>
在简写时,则不能省略插槽名,默认插槽必须追加#default
<my-info>
<div #default="{params}">
自定义的内容会被放置在slot中 - {{params.name}}
</div>
</my-info>
9.4 只有提供了默认插槽内容时,自定义组件才能当做插槽的模板使用。
info-detail.vue
自定义组件 , my-info
只有默认的插槽内容
<my-info>
<info-detail v-slot="{params}">
自定义的内容会被放置在slot中 - {{params.name}}
</info-detail>
</my-info>
9.5 当有多个插槽内容时,v-slot默认插槽不能缩写,书写为v-slot:default
<my-info>
<div v-slot:header="{params}">
在slot中, header位置放置内容- {{params.name}}
</div>
<div v-slot:default="{params}">
自定义的内容会被放置在slot中 - {{params.name}}
</div>
</my-info>
9.6 定义动态的插槽名,通过数据状态不同,展示不同数据内容。
<my-info>
<template v-slot:[dynamicSlotName]>
// ...
</template>
</my-info>
10. 动态组件、异步组件
切换组件展示,
<component v-bind:is="activeComponent"></component>
可通过动态定义的activeComponent
展示不同的组件。
10.1 缓存已创建的组件,提高性能 keep-alive
这样组件不会被销毁,状态也不会销毁。
<keep-alive>
<component v-bind:is="activeComponent"></component>
</keep-alive>
10.2 异步加载组件,优化打包
Vue.component('my-info', function (resolve) {
// 全局注册组件是,异步加载,编译时构建多个包
require(['./my-info'], resolve)
})
// 或者使用import
Vue.component('my-info', ()=>import('./my-info'))
如果是局部组件注册
new Vue({
// ...
components: {
'my-info': () => import('./my-info.vue')
}
})
10.3 异步加载时,定义加载状态
定义异步组件加载的配置对象,可定义加载时的展示组件、加载失败后的组件
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
11. 进入/离开、过渡效果
11.1 单组件过度效果 transition
- 条件渲染v-if、v-show
- 动态组件
- 可用于组件根节点
<transition name="fade">
<p v-if="bool"></p>
</transition>
则会在适当的实际追加class,如果没有指定name,则以v-
为前缀
-
v-enter
进入过渡的开始状态。在元素插入前生效 -
v-enter-active
定义过渡中的状态 -
v-enter-to
元素插入之后的状态。 -
v-leave
定义元素离开的开始状态 -
v-leave-active
定义元素离开过渡生效时的状态。 -
v-leave-to
定义元素离开过渡完成的状态
11.2 如果使用第三方动画库,可直接定义各阶段的class
在需要过渡的元素定义过渡的class名。
enter-class
enter-active-class
enter-to-class
leave-class
leave-active-class
leave-to-class
这些优先级高于普通的类名。
11.3 通过钩子函数定义过渡执行的时机回调
可以手动控制元素,使用JS动画。
可通过设置v-bind:css="false"
跳过css过渡的检测,避免影响JS多度
v-on:before-enter
v-on:enter
v-on:after-enter
v-on:enter-cancelled
...
在完成过渡的时候,在enter和leave中必须使用done进行回调。否则过渡会被同步调用,立即完成。
11.4 通过过渡模式定义新、旧元素的切换
<transition name="fade" mode="out-in">
<p v-if="bool"></p>
</transition>
-
in-out
新元素先过渡,完成之后当前元素多度离开。 -
out-in
当前元素先过渡,完成之后新元素过渡进入
11.5 transition-group
处理渲染多个元素的过渡效果
- 会议真实的节点元素渲染,默认为
span
. 也可指定tag
属性, - 不可使用过渡模式
- 内部元素需要提供唯一key键值
- css过渡类会应用内部的每一个元素上。
了解新的一个过渡类v-move
用与设置过度的切换时机和过渡曲线。
12. 状态过渡
- 数字和运算
- 颜色的显示
- SVG 节点的位置
- 元素的大小和其他的 property
13. CreateElement
参数
通常会简写为 h
h(tag,options,children)
主要的是options设置
{
// 定义class名
class:{},
// 定义内联style样式
style:{},
// 普通的html元素属性设置
attrs:{
id:"",
},
// 组件的props 设置,自定义组件
props:{
info:{}
},
// DOM 自身属性
domProps:{},
// 事件监听器
on:{
click:this.handleClick
},
// DOM 原生事件,非组件内部触发`$emit.on()`
nativeOn:{
click:this.handleNativeClick
},
// 自定义指令,
directives:[
{
name: 'my-directive',
value: '2',
expression: '1 + 1',
arg: 'foo',
modifiers: {
bar: true
}
}
],
// 作用于插槽
// slotName:props=>定义的组件
scopedSlots:{
default:props=>VNode
},
// 如果组件是其他组件的子组件按,指定插槽名称
slot:"",
key:"",
ref:"box",
// 在创建其他元素时,是否应用了一样的ref名称,
// `$refs.box`变成一个数组
refInFor: true
}
还是喜欢使用JSX风格书写组件
14. 使用插件
自定义组件或者开发公共组件需要提供一个install
方法。然后通过Vue.use()
注册。
// 第一个参数为当前Vue实例对象,第二个为配置项
export default {
install:(app,option)=>{
// 注册全局属性、方法
app.globalAttrs = ""
// 全局组件注册
app.component(Component.name,Component)
// 组件实例可访问的方法
app.prototype.$myFn = (){
// ...
}
}
}