动态组件 & 插槽 & 自定义指令


一、动态组件

(一) 什么是动态组件

  • 动态组件指的是动态切换组件的显示与隐藏

(二)如何实现动态组件渲染

vue 提供了一个内置的 <component> 组件,专门用来实现动态组件的渲染。

示例代码如下:

<template>
  <div class="app-container">
    <h1 ref="myh12">App 根组件</h1>
    <component :is="comName"></component>

    <button @click="comName = 'Left'">展示Left</button>
    <button @click="comName = 'right'">展示Right</button>
  </div>
</template>

<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'
export default {
  data() {
    return {
      comName: 'Left'
    }
  },
  components: { Left, Right },//必须引入组件,否则找不见位置
}
</script>

(三)使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组件的状态。示例代码如下:

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

(四)keep-alive 对应的生命周期函数

  • 当组件被缓存时,会自动触发组件deactivated 生命周期函数。
  • 当组件被激活时,会自动触发组件activated 生命周期函数。
export default {
  name:'Left',
  created() {
    console.log('组件被创建了')
  },
  destroyed() {
    console.log('组件被销毁了')
  },

  activated() {
    console.log('组件被激活了')
  },
  deactivated() {
    console.log('组件被缓存了')
  }
}

(五) keep-alive 的 include、exclude 属性

  • include 属性用来指定:只有名称匹配的组件被缓存
  • exclude属性用来指定:只有名称匹配的组件不会被缓存
  • 多个组件名之间使用英文的逗号分隔
  • 两个属性不要同时使用
<keep-alive include="Left,Right">
  <component :is="comName"></component>
</keep-alive>

或者

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

(六)了解注册名称和组件中name的区别

  • 注册名称:以标签形式把组件渲染到页面中
  • 组件中声明的name:结合<keep-alive>实现组件缓存功能

二、插槽

(一) 什么是插槽

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

(二) 体验插槽的基础用法

在封装组件时,可以通过 <slot> 元素定义插槽,从而为用户预留内容占位符。示例代码如下:

//父组件
<Left>这是个插槽</Left>

//子组件--Left
<div class="left-container">
    <slot></slot>
</div>

1、 没有预留插槽的内容会被丢弃

如果在封装组件时没有预留任何 <slot> 插槽,则用户提供的任何自定义内容都会被丢弃

//父组件
<Left>没有预留插槽,这段文字会被丢弃</Left>

//子组件--Left
<div class="left-container">
</div>

2、后备内容

封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。

//父组件
<Left></Left>

//子组件--Left
<div class="left-container">
    <slot>这是插槽默认内容,没有提供具体内容时显示</slot>
</div>

(三) 具名插槽

如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。

<div class="left-container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

注意:没有指定 name 名称的插槽,会有隐含的名称叫做 “default”。

1、 为具名插槽提供内容

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot参数的形式提供其名称。

// left组件
<Left>
  <template v-solt:header>
    <h1>
      滕王阁序
    </h1>
  </template>
  
  <template v-solt:default>
   <p>默认</p>
   <p>默认</p>
   <p>默认</p>
  </template>
  
  <template v-solt:footer>
   <p>尾部</p>
  </template>
</Left>

2、 具名插槽的简写形式

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header可以被重写为 #header

// left组件
<Left>
  <template #header>
    <h1>
      滕王阁序
    </h1>
  </template>
  <template #default>
   <p>默认</p>
   <p>默认</p>
   <p>默认</p>
  </template>
  <template #footer>
   <p>尾部</p>
  </template>
</Left>

(四) 作用域插槽

封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据,这种带有 props 数据的 <slot> 叫做“作用域插槽”。

<main>
  <slot v-for="item in list" :user="item"></slot>
</main>

1、使用作用域插槽

可以使用 v-slot: 的形式,接收作用域插槽对外提供的数据

<Left>
  <template #default="scope">
    <p>默认{{ scope.user }}</p>
  </template>
</Left>

2、 解构插槽 Prop

作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程

<Left>
  <template #default="{ user }">
    <p>默认{{ user }}</p>
  </template>
</Left>

三、自定义指令

(一)什么是自定义指令

vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令

(二)自定义指令的分类

vue 中的自定义指令分为两类,分别是:

  • 私有自定义指令
  • 全局自定义指令

(三)私有自定义指令

在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。

directives: {
   color: {
     bind(el) {
       el.style.color = 'red'
     }
   }
 },

(四)使用自定义指令

在使用自定义指令时,需要加上 v- 前缀。

// 指令的名字是color
<h1 v-color>App 根组件</h1>

(五)为自定义指令动态绑定参数值

在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值:

<h1 ref="myh12" v-color="color">App 根组件</h1>

data() {
  return {
    color: 'red',
  }
},

(六)通过 binding 获取指令的参数值

在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值:

directives: {
  color: {
    bind(el, binding) {
      el.style.color = binding.value
    }
  }
},

(七)update 函数

bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时bind 函数不会被触发。 update 函数会在每次 DOM 更新时被调用

directives: {
  color: {
    // 只调用一次
    bind(el, binding) {
      el.style.color = binding.value
    },
    // Dom更新时调用
    update(el, binding) {
      el.style.color = binding.value
    }
  }
}

(八)函数简写

如果 insert 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式

directives: {
 color(el, binding) {
   el.style.color = binding.value
 },
},

(九)全局自定义指令

全局共享的自定义指令需要通过“Vue.directive()”进行声明。

Vue.directive('color', function(el, binding) {
  el.style.color = binding.value
})
组件Vue.js 中最重要的概念之一。组件可以让我们将 UI 拆分为独立、可复用的部件,使得代码更加清晰、易于维护。在 Vue.js 中,组件可以分为全局组件和局部组件,其中全局组件可在任何地方使用,而局部组件只能在其父组件中使用。 定义组件时,需要使用 Vue.component() 方法,该方法需要传入两个参数:组件名称和组件配置对象。组件名称应该采用 kebab-case(短横线分隔命名)格式,以便在 HTML 中使用。 示例代码如下: ```javascript // 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' }) ``` 在上述代码中,我们定义了一个名为 button-counter 的组件,该组件包含一个计数器,每次点击按钮计数器加一。 在 HTML 中使用组件时,需要使用组件名称作为自定义标签来调用组件。示例代码如下: ```html <div id="app"> <button-counter></button-counter> </div> ``` 在上述代码中,我们调用了 button-counter 组件,并将其渲染到了 id 为 app 的 div 元素中。 除了组件的 data 和 template 属性外,还可以使用 props 属性来传递组件之间的数据。使用 props 时,需要在组件的配置对象中定义 props 属性,并在 HTML 中使用 v-bind 指令来传递数据。 示例代码如下: ```javascript // 定义一个名为 todo-item 的新组件 Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) // 创建一个 Vue 实例 var app = new Vue({ el: '#app', data: { groceryList: [ { id: 0, text: '蔬菜' }, { id: 1, text: '水果' }, { id: 2, text: '奶酪' } ] } }) ``` 在上述代码中,我们定义了一个名为 todo-item 的组件,并使用 props 属性定义了一个名为 todo 的 prop。在 HTML 中,我们使用 v-bind 指令将 groceryList 数组中的每个对象传递给了 todo-item 组件。示例代码如下: ```html <div id="app"> <ul> <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id"></todo-item> </ul> </div> ``` 在上述代码中,我们使用 v-for 指令遍历 groceryList 数组,并使用 v-bind 指令将数组中的每个对象传递给了 todo-item 组件。注意,我们还需要使用 v-bind:key 指令来为每个列表项指定一个唯一的 key 值。 插槽Vue.js 中另一个重要的概念。插槽可以让父组件在子组件中插入任意的 HTML 内容,使得组件更加灵活、可复用。 在子组件中,使用 <slot> 标签来定义插槽。在父组件中,使用子组件的自定义标签来调用组件,并在标签内部插入 HTML 内容。示例代码如下: ```javascript // 定义一个名为 alert-box 的新组件 Vue.component('alert-box', { template: ` <div class="alert-box"> <strong>Error!</strong> <slot></slot> </div> ` }) // 创建一个 Vue 实例 var app = new Vue({ el: '#app' }) ``` 在上述代码中,我们定义了一个名为 alert-box 的组件,并在组件中定义了一个插槽。在 HTML 中,我们调用了 alert-box 组件,并在标签内部插入了一些 HTML 内容。示例代码如下: ```html <div id="app"> <alert-box> <p>Something bad happened.</p> </alert-box> </div> ``` 在上述代码中,我们调用了 alert-box 组件,并在标签内部插入了一些 HTML 内容。该 HTML 内容会被插入到 alert-box 组件插槽中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值