Vue 插槽

519 阅读4分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

1.组件-插槽

目标

用于实现组件的内容分发, 通过 slot 标签, 可以接收到写在组件标签内的内容

讲解

vue 提供组件插槽能力, 允许开发者在封装组件时,把不确定的部分定义为插槽

语法口诀:

  1. 组件内用占位
  2. 使用组件时夹着的地方, 传入标签替换 slot

总结: 组件内容分发技术, slot 占位, 使用组件时传入替换 slot 位置的标签

2.组件-插槽-默认内容

目标

如果外面不给传, 想给个默认显示内容

讲解

口诀: 夹着内容默认显示内容, 如果不给插槽 slot 传东西, 则使用夹着的内容在原地显示

<slot>默认内容</slot>

小结

  1. 如何给插槽设置默认显示内容?

    slot 标签内写好默认要显示内容

  2. 什么时候插槽默认内容会显示?

    当使用组件并未给我们传入具体标签或内容时

3.组件-具名插槽

目标

当一个组件内有 2 处以上需要外部传入标签的地方

讲解

传入的标签可以分别派发给不同的 slot 位置

要求: v-slot 一般用跟 template 标签使用 ( template 是 html5 新出标签内容模板元素, 不会渲染到页面上, 一般被 vue 解析内部标签)

v-slot 可以简化成 # 使用

v-bind 可以省略成: v-on: 可以省略成@ 那么 v-slot: 可以简化成#

总结: slot 的 name 属性起插槽名, 使用组件时, template 配合#插槽名 传入具体标签

小结

  1. 组件内多处不确定的标签如何做?

    slot 占位, 给 name 属性起名字来区分 template 配合 v-slot:name 分发要替换的标签

  2. v-slot: 可以简化成什么?

    #号

4.组件-作用域插槽

目标

子组件里值, 在给插槽赋值时在父组件环境下使用

讲解

复习: 插槽内 slot 中显示默认内容

例子: 默认内容在子组件中, 但是父亲在给插槽传值, 想要改变插槽显示的默认内容

口诀:

  1. 子组件, 在 slot 上绑定属性和子组件内的值
  2. 使用组件, 传入自定义标签, 用 template 和 v-slot="自定义变量名"
  3. scope 变量名自动绑定 slot 上所有属性和值
<!-- slot标签, 自定义属性和内变量关联 -->
<slot name="body" :row="defaultObj">{{ defaultObj.One }}</slot>
<script>
data() {
    return {
      defaultObj: {
        One: "无名氏",
        Two: "小传同学"
      }
    };
 },
</script><!-- 需求: 插槽时, 使用组件内变量 -->
<!-- scope变量: {row: defaultObj} -->
<template #body="scope">
  //这里不传值,就是默认的 defaultObj.One 值
  <p>{{ scope.row.Two }}</p>
</template>

总结: 组件内变量绑定在 slot 上, 然后使用组件 v-slot="变量" 变量上就会绑定 slot 身上属性和值

小结

  1. 作用域插槽什么时候使用?

    使用组件插槽技术时, 需要用到子组件内变量

  2. 作用域插槽使用口诀?

    子组件在 slot 身上添加属性和子组件的值 使用组件处 template 配合 v-slot=“变量名”(收集 slot 身上的所有属性和值)

5.自定义指令-注册

  • 全局

    在 main.js 用 Vue.directive() 方法来进行注册, 以后随便哪个.vue 文件里都可以直接用 v-fofo 指令

    // 全局指令 - 到处"直接"使用
    Vue.directive("fofo", {
        //当元素被插入到 DOM 树上时执行该函数
        inserted(el) {
            el.focus() // 触发标签的事件方法
        }
    })
    
  • 局部

    directives: {
        (名字可以随便起-规范即可)
        foc: {
                inserted(el){
                    //创建 "自定义指令", 让输入框自动聚焦
                    el.focus()
                }
        }
    }
    

总结: 全局注册自定义指令, 哪里都能用, 局部注册, 只能在当前 vue 文件里用

在标签上使用自定义指令 v-指令名

6.v-model 原理

  • :value="vue 变量"
  • @input="形参 => vue 变量 = 形参"

小结

  1. v-model实际上实现的是什么?

    向标签内的value属性赋值

    给标签绑定input事件, 并把收到的值, 赋予给vue变量

7.$refs-获取DOM

目标

利用 ref 和 $refs 可以用于获取 dom 元素

还可以获取组件对象, 调用组件里方法

讲解

<template>
  <div>
      <p>1. 获取原生DOM元素</p>
      <h1 id="h" ref="myH">我是一个孤独可怜又能吃的h1</h1>
  </div>
</template><script>
// 目标: 获取组件对象
// 1. 创建组件/引入组件/注册组件/使用组件
// 2. 组件起别名ref
// 3. 恰当时机, 获取组件对象
export default {
    mounted(){
        console.log(document.getElementById("h")); // h1
        console.log(this.$refs.myH); // h1
    }
}
</script><style></style>

总结: 通过id / ref, 都可以获取原生DOM标签

8.$nextTick使用

  • ref 与$refs

    • ref

      • 作用:给标签或者组件添加一个标记(引用)

        <div ref="a">
        
        <Demo ref="b">
        
    • this.$refs

      • 作用:获取当前组件中所有的 ref 引用

        • this.$refs.a
        • this.$refs.b
  • $nextTick

      1. 现象:数据发生改变,DOM 会发生更新,但是是异步的
      1. 问题:修改完了数据后,无法立即操作 DOM
      1. this.$nextTick

      • 作用:等待 DOM 更新后,回调函数会立即执行
      • this.$nextTick(function(){})
      • this.$nextTick().then(() => {})
      • await this.$nextTick()

小结

  1. data改变更新DOM是同步还是异步的?

    异步

  2. 我们可以在哪里访问到更新后的DOM呢?

    this.$nextTick 里的函数体 updated 生命周期钩子函数

今日总结

  1. 组件插槽默认使用
  2. 插槽默认显示的内容
  3. 多个插槽时, 具名插槽如何使用
  4. 作用域插槽如何使用以及目的
  5. 自定义命令如何使用
  6. refsrefs和nextTick的作用
  7. 知道v-model的本质是什么
  8. 会给自定义组件使用v-model