動態組件和插槽

組件進階 - props 校驗

props 校驗

普通格式:props: ["propA", "propB"]。沒有類型檢查

高階格式:

props: {
    // 基礎的類型檢查 (`null` 和 `undefined` 會通過任何類型驗證)
    propA: Number,
    // 多個可能的類型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 帶有默認值的數字
    propD: {
      type: Number,
      default: 100
    },
    // 帶有默認值的對象
    propE: {
      type: Object,
      // 對象或數組默認值必須從一個工廠函數獲取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函數
    propF: {
      validator: function (value) {
        // 這個值必須匹配下列字符串中的一個
        return ['success''warning''danger'].indexOf(value) !== -1
      }
    }
  }
複製代碼

組件進階 - 動態組件

目標效果

需求: 完成一個註冊功能頁面, 2 個按鈕切換, 額外封裝兩個組件:一個填寫註冊信息, 一個填寫用戶簡介信息

目標: 多個組件使用同一個掛載點,並可以動態切換,這就是動態組件

目錄結構

根組件
├── App.vue
└── components
    ├── UserName.vue # 用戶名和密碼輸入框
    └── UserInfo.vue # 人生格言和自我介紹框
複製代碼

格式

<component :is="comName"></component>

操作

UserName.vue

<template>
  <div>
    <h2>UserName</h2>
    <p>用戶名:<input /> </p>
    <p>密碼:<textarea /> </p>
  </div>
</template>

<script>
export default {

}
</script>
複製代碼

在父組件 App.vue 中使用

<template>
  <div>
    <button @click="comName = 'UserName'">賬號密碼填寫</button>
    <button @click="comName = 'UserInfo'">個人信息填寫</button>

    <p>下面顯示註冊組件:</p>
    <div style="border: 1px solid red">
      <!-- vue內置的組件component, 可以動態顯示組件 -->
      <component :is="comName"></component>
    </div>
  </div>
</template>

<script>
import UserName from "./UserName";
import UserInfo from "./UserInfo";
export default {
  data() {
    return {
      comName: "UserName",
    };
  },
  components: {
    UserName,
    UserInfo,
  },
};
</script>
複製代碼

注意

小結

vue 內置 component 組件, 配合 is 屬性, 設置要顯示的組件標籤名字

組件進階 - keep-alive 組件

目標

掌握組件緩存的使用

背景

組件切換會導致組件被頻繁銷燬和重新創建, 大多數情況下是有自己的意義的,但也可能會導致不必要的性能損耗

演示 1: 可以先給 UserName.vue 和 UserInfo.vue 註冊 created 和 destroyed 生命週期事件, 觀察創建和銷燬過程

keep-alive

使用 Vue 內置的keep-alive組件, 可以讓包裹的組件保存在內存中不被銷燬

格式

演示 2: 使用 keep-alive 內置的 vue 組件, 讓動態組件緩存而不是銷燬

補充生命週期:

<keep-alive>
    <!-- vue內置的組件component, 可以動態顯示組件 -->
    <component :is="comName"></component>
</keep-alive>
複製代碼

小結

keep-alive 可以提高組件的性能, 內部包裹的標籤不會被銷燬和重新創建, 觸發激活和非激活的生命週期方法

組件進階 - keep-alive 組件 - 指定緩存

目標

掌握 keep-alive 的 include 屬性的用法

語法

  1. `include="組件名1,組件名2..."`
  2. `:include="['組件名1', '組件名2']"`
<keep-alive include="name1,name2">
    <!-- vue內置的組件component, 可以動態顯示組件 -->
    <component :is="comName"></component>
</keep-alive>
複製代碼

注意:

  1. 匹配首先檢查組件自身的 name 選項,如果 name 選項不可用,則匹配它的局部註冊名稱 (父組件 components 選項的鍵值)

組件進階 - 默認插槽

目標

掌握組件插槽的使用

理解

生活中的插槽

vue 中的插槽

  1. 組件通過插槽傳入自定義結構

  2. 用於實現組件的內容分發, 通過 slot 標籤, 可以接收到寫在組件標籤內的內容

  3. vue 提供組件插槽能力, 允許開發者在封裝組件時,把不確定的部分定義爲插槽

格式

在定義組件時,在 template 中用 slot 來佔個坑;

使用時,將組件之間的內容來填坑;

示例

組件進階 - 具名插槽

目標

掌握具名插槽的使用

背景

當一個組件內有 2 處以上需要外部傳入標籤的地方

格式

定義:

使用:

圖示:

  1. 傳入的標籤可以分別派發給不同的 slot 位置

  2. v-slot 一般跟 template 標籤使用 (template 是 html5 新出標籤內容模板元素, 不會渲染到頁面上, 一般被 vue 解析爲內部標籤)

示例

  1. 子組件-Pannel2.vue
<div class="container" v-show="isShow">
    <slot ></slot>
    <slot ></slot>
</div>
複製代碼

2 . 父組件 - UseSlot2.vue

v-slot 可以簡化成 #使用

v-bind 可以省略成:

v-on: 可以省略成 @

v-slot: 可以簡化成#

寫法 1:

<Pannel2>
    <template v-slot:one>
  <img src="../assets/mm.gif" alt="" />
    </template>
    <template v-slot:two>
  <span>我是文字哦</span>
    </template>
</Pannel2>
複製代碼

寫法 2:

<Pannel2>
    <!-- 簡化寫法 -->
    <template #one>
  <div>
            <p>寒雨連江夜入吳,</p>
            <p>平明送客楚山孤。</p>
            <p>洛陽親友如相問,</p>
            <p>一片冰心在玉壺。</p>
        </div>
    </template>
    <template #two>
  <img src="../assets/mm.gif" alt="" />
    </template>
</Pannel2>
複製代碼

小結

  1. slot 有可以設置多個

  2. 定義組件時:slot 的 name 屬性起插槽名

  3. 使用組件時, template 配合 #插槽名傳入具體 html 標籤或組件

組件進階 - 作用域插槽(難點)

目標

掌握作用域插槽的用法

目標: 子組件中的數據, 在給插槽賦值時在父組件環境下使用 => 子傳父 =》傳數據

步驟

示例

具名插槽, 給 slot 綁定屬性和值

<template>
  <div style="border:1px solid #ccc; margin:5px;padding:5px">
    <h2>子組件</h2>
    <!-- 給slot上補充自定義的屬性 -->
    <slot >
      默認內容
    </slot>
  </div>
</template>

<script>
export default {
}
</script>
複製代碼
  1. 父組件
<template>
  <div style="border:1px solid #ccc; margin:5px;padding:5px">
    <h1>45-插槽-作用域插槽</h1>


    <MyCom>
      <!-- 
        v-slot:插槽名="對象" 
      對象會自動接收這個插槽傳遞回來自定義屬性
      -->
      <template v-slot:content="scope">
        <!-- <h1>自定義的內容,填坑, {{scope}}</h1> -->
        <h3>{{scope.a}}</h3>
        <p>{{scope.b}}</p>
      </template>
    </MyCom>
  </div>
</template>

<script>

// 父傳子
//  1.傳數據。 自定義屬性    (父)  props()
//  2.傳結構。 在組件中寫內容(父)  slot ()

import MyCom from './MyCom.vue'
export default {
  components: { MyCom }
}
</script>

<style scoped>
.content{
background-color: #ccc;
}
</style>
複製代碼

小結

組件內變量綁定在 slot 上, 然後使用組件 v-slot: 插槽名字 ="變量" ,變量上就會綁定 slot 傳遞的屬性和值

自定義指令 - 基本使用

自定義指令文檔 [1](瞭解)

除了核心功能默認內置的指令 (v-model 和 v-show) 等,Vue 也允許註冊自定義指令 =》 v-xxx

  1. html+css+js 的複用的主要形式是組件

  2. 你需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令

作用

擴展標籤額外的功能

自定義指令 - 定義方式

{
  data(){},
  methods: {},
  directives: {
    focus: { // 自定義指令名
        inserted(el){ // 固定配置項 - 當指令插入到標籤自動觸發此函數
            el.focus()
        }
    },
  },
}
複製代碼

示例 自動獲取焦點

<template>
  <div>
    <input type="text" v-focus />
  </div>
</template>

<script>
export default {
  // 註冊
  directives: {
    focus: { // 自定義指令名
        inserted(el){ // 固定配置項 - 當指令插入到標籤自動觸發此函數
            el.focus()
        }
    }
  }
}
</script>
複製代碼

自定義指令 - 傳值和更新

目標: 使用自定義指令, 傳入一個值

需求: 定義 color 指令 - 傳入一個顏色, 給標籤設置文字顏色

main.js 定義處修改一下

directives: {
  "color":{
    inserted(el, binding){ // 插入時觸發此函數
      el.style.color = binding.value;
    },
    update(el, binding){ // 更新綁定的變量時觸發此函數=》手動更新
      el.style.color = binding.value;
    }
  }
}
複製代碼

Direct.vue 處更改一下

<p v-color="theColor" @click="changeColor">使用v-color指令控制顏色, 點擊變藍</p>

<script>
  data() {
    return {
      theColor: "red",
    };
  },
  methods: {
    changeColor() {
      this.theColor = 'blue';
    },
  },
</script>
複製代碼

總結: v-xxx, 自定義指令, 獲取原生 DOM, 自定義操作

關於本文

作者:pain_past_is_pleasur

https://juejin.cn/post/7095716277196587039

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ablEN3hqg1gqU7J4-2mADQ