Vue2:组件高级(下)

Vue2:组件高级(下)

Date: May 25, 2023
Sum: 自定义指令、插槽、商品列表、动态组件


目标:

Vue2:组件高级(下)_第1张图片




自定义指令

基础概念:

概念

内置指令:vue 官方提供了 v-for、v-model、v-if 等常用的内置指令。

自定义指令:Vue支持让开发者,自己注册一些指令。这些指令被称为自定义指令。

自定义指令可以封装一些 dom 操作,扩展额外功能。

类型:私有自定义指令和全局自定义指令

语法:

指令中的配置项介绍:

inserted:当指令所绑定的元素,被添加到页面当中时,会自动调用

换句话说,就是被绑定元素插入父节点时调用的钩子函数

el:使用指令的那个DOM元素

局部注册:

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

示例代码如下:

//在Vue组件的配置项中
directives: {
  "指令名": {
    inserted () {
      // 可以对 el 标签,扩展额外功能
      el.focus()
    }
  }
}
directives: {
    //  自定义一个私有指令
    focus: {
      // 当被绑定的元素插入到 DOM 中时,自动触发 mounted 函数
      mounted(el) {
        el.focus() // 让被绑定的元素自动获得焦点
      }
    }
  },

注意:自定义指令在使用的时候以v-开头,但是在声明的时候不需要加v-前缀

全局注册:

//在main.js中
Vue.directive('指令名', {
  "inserted" (el) {
    // 可以对 el 标签,扩展额外功能
    el.focus()
  }
})

全局共享的自定义指令需要通过“单页面应用程序的实例对象”进行声明,示例代码如下:

const app = Vue.createApp({})

// 注册一个全局自定义指令 `v-focue`
app.directive('focus', {
	// 当被绑定的元素插入到 DOM 中时,自动触发 mounted 函数
	mounted(el) {
		// Focus the element
		el.focus()
	}
})

使用自定义指令

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

示例代码如下:




案例:当页面加载时,让元素获取焦点(autofocus在safari浏览器有兼容性

  • Code: 采用局部注册与全局注册两种方式

    App.vue

    
    
    
    
    
    

    main.js

    import Vue from 'vue'
    import App from './App.vue'
    
    Vue.config.productionTip = false
    
    // 全局注册指令
    Vue.directive('focus', {
      inserted(el) {
        el.focus()
      }
    })
    
    new Vue({
      render: h => h(App),
    }).$mount('#app')
    


自定义指令-指令的值

**需求:**实现一个 color 指令 - 传入不同的颜色, 给标签设置文字颜色

语法:

1.在绑定指令时,可以通过“等号”的形式为指令 绑定 具体的参数值

我是内容

2.通过 binding.value 可以拿到指令值,指令值修改会 触发 update 函数

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

updated 函数

mounted或inserted 函数只在元素第一次插入 DOM 时被调用,当 DOM 更新时 mounted或inserted 函数不会被触发。 updated函数会在每次 DOM 更新完成后被调用。

示例代码如下:

app.directive('focus', {
	mounted(el) {  // 第一次插入 DOM 时触发这个函数
		el.focus()
	},
	updated(el) { // 每次 DOM 更新时都会触发 updated 函数
		el.focus()
	}
})

注意:在 vue2 的项目中使用自定义指令时,【 mounted -> bind 】【 updated -> update 】

函数简写

如果 mounted 和updated 函数中的逻辑完全相同,则可以简写成如下格式:

app.directive('focus', (el) => {
	// 在 mounted 和 updated 时都会触发相同的业务处理
	el.focus()
})

案例

Vue2:组件高级(下)_第2张图片

  • Code:

    App.vue

    
    
    
    
    
    


自定义指令-v-loading指令的封装

场景:

开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态 => 用户体验不好

**需求:**封装一个 v-loading 指令,实现加载中的效果

分析:

1.本质 loading效果就是一个蒙层,盖在了盒子上

2.数据请求中,开启loading状态,添加蒙层

3.数据请求完毕,关闭loading状态,移除蒙层

实现:

1.准备一个 loading类,通过伪元素定位,设置宽高,实现蒙层

2.开启关闭 loading状态(添加移除蒙层),本质只需要添加移除类即可

3.结合自定义指令的语法进行封装复用

.loading:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #fff url("./loading.gif") no-repeat center;
}

案例

Vue2:组件高级(下)_第3张图片

  • Code:

    App.vue

    
    
    
    
    
    

总结

  1. 通过指令相关语法,封装了指令 v-loading 实现了请求的loading效果
  2. 核心思路:
    1. 准备类名 loading,通过伪元素提供遮罩层

    2. 添加或移除类名,实现loading蒙层的添加移除

    3. 利用指令语法,封装 v-loading 通用指令

      inserted 钩子中,binding.value 判断指令的值,设置默认状态
      update 钩子中,binding.value 判断指令的值,更新类名状态




插槽

概念

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

Vue2:组件高级(下)_第4张图片

作用:让组件内部的一些 结构 支持 自定义

可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

案例

将需要多次显示的对话框,封装成一个组件

Vue2:组件高级(下)_第5张图片

组件的内容部分,不希望写死,希望能使用的时候自定义。怎么办



体验插槽的基础用法

在封装组件时,可以通过 元素定义插槽,从而为用户预留内容占位符。

注意:给插槽传入内容时,可以传入纯文本、html标签、组件

示例代码如下:

MyCom.vue


App.vue



	
  

~~~用户自定义的内容~~~

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

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

示例代码如下:

MyCom.vue


App.vue


	
	

~~~用户自定义的内容~~~

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

示例代码如下:


案例:对话框复用

Vue2:组件高级(下)_第6张图片

  • Code:


具名插槽

需求:一个组件内有多处结构,需要外部传入标签,进行定制

Vue2:组件高级(下)_第7张图片

上面的弹框中有三处不同,但是默认插槽只能定制一个位置,这时候怎么办呢?

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

示例代码如下:

多个slot使用name属性区分名字

MyCom.vue


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

App.vue

为具名插槽提供内容

通过 元素上使用 v-slot 指令向具名插槽提供内容,并以 v-slot 的参数的形式提供其名称。即,template配合v-slot:名字来分发对应标签。


案例

Vue2:组件高级(下)_第8张图片

  • Code:

    App.vue

    
    
    
    
    
    

    MyDialog.vue

    
    
    
    
    
    

具名插槽的简写形式

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

例如 v-slot:header可以被重写为 #header

App.vue




作用域插槽

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

分类

  • 默认插槽
  • 具名插槽 插槽只有两种,作用域插槽不属于插槽的一种分类

作用:定义slot 插槽的同时, 是可以传值的。给 插槽 上可以 绑定数据,将来 使用组件时可以用

案例

案例1:封装表格组件

Untitled

使用步骤:

1- 给 slot 标签, 以添加属性的方式传值


2- 所有添加的属性, 都会被收集到一个对象中

{ id: 3, msg: '测试文本' }

3- 在template中, 通过 #插槽名= "obj" 接收,默认插槽名为 default


  

  • Code:

    MyTable.vue

    
    
    
    
    
    

    App.vue

     
    
    
    

对于Code的用法的理解

解构作用域插槽的 Prop

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

示例代码如下:


  
  




综合案例:商品列表

需求说明:

效果

Vue2:组件高级(下)_第9张图片

需求说明:

  1. my-tag 标签组件封装

(1) 双击显示输入框,输入框获取焦点

(2) 失去焦点,隐藏输入框

(3) 回显标签信息

(4) 内容修改,回车 → 修改标签信息

  1. my-table 表格组件封装

(1) 动态传递表格数据渲染

(2) 表头支持用户自定义

(3) 主体支持用户自定义



MyTag组件封装

封装内容:MyTag

Vue2:组件高级(下)_第10张图片

完成步骤

(1) 双击显示输入框,输入框获取焦点

关键点:

1-显示输入框:v-if v-else @dbclick

2-自动聚焦: n e x t T i c k → nextTick→ nextTickrefs 获取dom 或者 自定义指令v-focus

(2) 失去焦点,隐藏输入框

关键点:

1-@blur=”isEdit = false”

  • Code:

    App.vue

    
    
    
    
    
    

    MyTag.vue

    
    
    
    
    
    

    main.js

    import Vue from 'vue'
    import App from './App.vue'
    
    Vue.config.productionTip = false
    
    // 全局注册指令
    Vue.directive('focus', {
      inserted(el) {
        el.focus()
      }
    })
    
    new Vue({
      render: h => h(App),
    }).$mount('#app')
    

(3) 回显标签信息

关键点:

1-回显的标签

回显的标签信息是父组件传递过来的

v-model实现功能(简化代码) v-model ⇒ :value 和 @input

(4) 内容修改,回车 → 修改标签信息

关键点:

1-enter子传父

子传父,将回车时,输入框的内容提交给父组件更新

由于父组件是v-model,触发事件,需要触发 input 事件

2-拿到文本框中实时的值:

e.target 指触发事件的事件源

  • Code:

    App.vue

    
    
    
    
    
    

    MyTag.vue

    
    
    
    
    
    


MyTable组件封装

(1) 动态传递表格数据渲染

(2) 表头支持用户自定义

(3) 主体支持用户自定义

关键:插槽(具名插槽、作用域插槽)

  • Code:

    App.vue

    
    
    
    
    
    

    MyTable.vue

    
    
    
    
    
    

    MyTag.vue同上




动态组件

  1. 什么是动态组件

动态组件指的是动态切换组件的显示与隐藏。vue 提供了一个内置的 组件,专门用来实现组件的动态渲染。

① 是组件的占位符

② 通过 is 属性动态指定要渲染的组件名称

  1. 如何实现动态组件渲染

示例代码如下:

data() {
  return {
    comName: 'MyHome' // 1.当前要渲染的组件的名称
  }
},


注意:当我们切换组件时,之前组件会被销毁(所以之前的数据也会被清空)

Vue2:组件高级(下)_第11张图片

  1. 使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 组件保持动态组件的状态。

示例代码如下:


  

你可能感兴趣的:(Vue,vue.js,前端,javascript)