「Vue自我检验」Vue 组件进阶知识,你了解多少?

本文深入探讨Vue.js中的组件进阶特性,包括动态组件的使用,利用keep-alive进行状态缓存,详细解析插槽的默认、具名及自定义指令的应用,以及混入(Mixin)和插件的实现方式,帮助开发者提升Vue组件开发能力。
摘要由CSDN通过智能技术生成

vue 组件进阶

动态组件

vue 提供了内置的 <component> 组件用于动态切换组件。

<!-- 通过 is 属性指定要渲染的组件,传递的是字符串 -->
<component :is="comName"></component>

<button @click="comName = 'Left'">展示Left组件</button>
<button @click="comName = 'Right'">展示Right组件</button>

keep-alive

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组件的状态,对被包裹的组件进行状态缓存。

<keep-alive> 包裹的组件会多出两个生命周期函数:当组件被激活时,触发 activated 钩子;当组件被缓存时,触发 deactivated 钩子。

<keep-alive>
  <component :is="comName"></component>
</keep-alive>

<keep-alive>includeexclude 属性,分别用于指明哪些组件要缓存、哪些组件不要缓存。

<keep-alive include="Left, Right">
  <component :is="comName"></component>
</keep-alive>

插槽

何为插槽

插槽可以理解为组件封装期间,为用户预留的内容占位符。它是 vue 为组件封装者提供的能力,允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

插槽基本用法

基础使用:

<!-- 子组件中预留插槽 -->
<template>
  <div class="contianer">
    <h1>这是子组件</h1>
    <slot></slot>
  </div>
</template>

<!-- 父组件使用子组件时,向插槽填充内容 -->
<child-comp>
  <p>填充到插槽的内容</p>
</child-comp>

如果子组件没有预留插槽,那么父组件填充给子组件的自定义内容会被丢弃:

<!-- 子组件没有预留插槽 -->
<template>
  <div class="contianer">
    <h1>这是子组件</h1>
  </div>
</template>

<!-- 父组件的自定义内容会被丢弃 -->
<child-comp>
  <p>这段自定义内容会被丢弃</p>
</child-comp>

子组件可以为插槽提供后备内容,当父组件没有提供自定义内容时,后备内容就会生效。

<!-- 子组件提供后备内容 -->
<template>
  <div class="contianer">
    <h1>这是子组件</h1>
    <slot>这是后备内容,父组件没有提供自定义内容就会生效</slot>
  </div>
</template>

<!-- 父组件没有提供自定义内容 -->
<child-comp> </child-comp>

具名插槽

组件在预留插槽时可以设置 name 属性,为插槽指定名称,这种有具体名称的插槽就叫具名插槽。 没有设置 name 名称的插槽默认名称为 default

<!-- 子组件预留多个具名插槽 -->
<template>
  <div class="contianer">
    <h1>这是子组件</h1>

    <slot name="title">title 具名插槽</slot>
    <hr />
    <slot name="content">content 具名插槽</slot>>
    <hr />
    <slot>没有设置 name 名称则默认为 default</slot>
    <slot name="default"></slot>
  </div>
</template>

父组件向具名插槽提供自定义内容

  • 新的写法:包裹一个 <template> 标签,同时在 <template> 中通过 v-slot:名称 指明插槽的名称。简写形式为 #名称 ,且 v-slot 只能使用在 <template> 和组件标签上,普通 HTML 标签不行
  • 组件标签使用具名,需要 v-slot
  • 旧的写法:slot="名称" 指明插槽名称
  • 如果不指定插槽名称,那么自定义内容会被填充到所有的 default 插槽当中
  • 同一插槽填充多个内容,是追加不是覆盖
<!-- 父组件向具名插槽提供自定义内容 -->
<child-comp>
  <h1 slot="title">《赠汪伦》</h1>
  <h1 slot="title">《唐诗》</h1>   <!-- 追加不覆盖 -->
    
  <template v-slot:title>
    <h1>《静夜思》</h1>
  </template>

  <!-- 简写形式 -->
  <template #content>
    <p>床前明月光,疑是地上霜。</p>
    <p>举头望明月,低头思故乡。</p>
  </template>

  <template>
    <p>这段内容没有指定名称,会被填充到所有 default 插槽中。</p>
  </template>
</child-comp>

自定义指令

分类

  • 私有自定义指令:在组件的 directives 节点声明
  • 全局自定义指令:在 main.js 文件中声明

完整写法

<input type="text" v-focus="content" />
data() {
  return {
    content: 666
  }
},
directives: {
  focus: {
    // 指令与元素成功绑定时执行,执行一次
    bind(el, binding) {
      el.value = binding.value
    }

    // 指令所在元素插入页面时执行,执行一次
    inserted(el, binding) {
      // 一进入页面输入框获得焦点
      el.focus()
    }

    // 指令所在元素重新渲染时执行,执行 0+N 次
    update(el, binding) {
      el.value = binding.value
    }
  }
}

// 全局写法
Vue.directive('focus', {
  bind(el, binding) {
    el.value = binding.value
  }
  inserted(el, binding) {
    el.focus()
  }
  update(el, binding) {
    el.value = binding.value
  }
})

简写形式

  • bind 函数和 update 函数里的逻辑完全相同时,可以简写
  • 不需要定义 inserted 函数才使用简写形式
  • 因此简写形式的调用时机是初次绑定和 DOM 更新
<h2 v-color="'red'">简写形式</h2>
directives: {
  color(el, binding) {
    el.style.color = binding.value
  }
}

// 全局写法
Vue.directive('color', (el, binding) => {
  el.style.color = binding.value
}))

注意事项

  • 自定义指令使用时需要添加 v- 前缀
  • 指令名如果是多个单词,要使用 kebab-case 短横线命名方式,不要用 camelCase 驼峰命名
  • 自定义指令三个函数里的 this 指向 window
<span v-big-number="n"></span>
data() {
  return {
    n: 1
  }
},
directives: {
  // 添加引号才是对象键名完整写法
  // 平时不加引号都是简写形式
  // 遇到短横线的键名就必须添加引号
  'big-number': {
    bind(el, binding) {
      console.log(this) // Window
      el.innerText = binding.value * 10
    }
  }
}

Mixin 混入

  • Mixin 可以把多个组件共用的配置提取成一个混入对象
  • 混入和组件自身的配置会合并
  • datamethods 若冲突以自身为准
  • 对于生命周期钩子,执行动作会合并,且先执行 Mixin 里的动作

定义混入:

// mixin.js
export const mixin = {
  methods: {
    showName() {
      alert(this.name)
    },
  },
  mounted() {
    console.log('hello mixin')
  },
}
export const mixin2 = {
  data() {
    return {
      x: 100,
      y: 200,
    }
  },
}

使用局部混入:

import { mixin, mixin2 } from '../mixin.js'

export default {
  name: 'School',
  data() {
    return {
      schoolName: '北大',
    }
  },
  mixins: [mixin, mixin2],
}

使用全局混入:

// main.js
import { mixin, mixin2 } from './mixin.js'

Vue.mixin(mixin)
Vue.mixin(mixin2)

插件

  • 用于增强 Vue
  • 本质是包含 install 方法的一对象,install 第一个参数是 Vue 构造函数,第二个以后的参数是插件使用者传递的数据

定义插件:

// pay.vue写我们的组件
import vpay from './pay'

// 定义我们的插件
const myPlugin = {    
    // 该插件有一个install方法
    // 方法的第一个参数是传入的Vue,第二个参数可以插件的自定义参数
    install (Vue, options) {
        // 将其注册为vue的组件,'vpay'是组件名,keyboard是我们开发的组件
        Vue.component('vpay', vpay)    
    }
}

// 最后将插件导出,并在main.js中通过Vue.use()即可使用插件
export default myPlugin

使用插件:

// 引入插件
import vpay from './lib/vpay'
// 使用插件
Vue.use(vpay);

而后在我们的页面中就可以直接像使用组件的方式使用插件:

<!--支付密码弹窗-->
<vpay    
    ref="pays"    
    v-model="show"               
    @close="close"    
    @forget="forget"    
    @input-end="inputEnd"
></vpay>

在插件里可以定义的方法有:

MyPlugin.install = function (Vue, options) {
    // 第一种方法. 添加全局方法或属性
    Vue.myGlobalMethod = function () {
        // 逻辑...
    }

    // 第二种方法. 添加全局资源
    Vue.directive('my-directive', {
        bind (el, binding, vnode, oldVnode) {
            // 逻辑...
        }
        ...
    })

    // 第三种方法. 注入组件
    Vue.mixin({
        created: function () {
        // 逻辑...
        }
         ...
    })

    // 第五种方法. 添加实例方法
    Vue.prototype.$myMethod = function (methodOptions) {
        // 逻辑...
    }

    // 第六种方法,注册组件
    Vue.component(组件名, 组件)
}

$nextTick

  • 语法:this.$nextTick(回调函数)
  • 作用:在下一次 DOM 更新结束后执行其指定的回调
  • 什么时候用:当改变数据后,要基于更新后的 DOM 进行操作时,要在 nextTick 指定的回调函数中执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值