[Vue深入組件-邊界情況處理] 模板定義的替代品

1. 內聯模板

即將要說的是一個很有意思的Vue邊界應用。

Vue開發者,通常都有着很敏感的組件規則。 我們寫的組件全部都是以一個個組件組裝到一起的。

當涉及組件之間通信,調用時,會出現各種招數應對各種場景。 如果你要寫一個嵌套組件。

你必然會先創建兩個單獨的組件,然後在其中一個引入註冊另一個(當然,我們剛說過了組件的互相循環調用)。 註冊好之後,爲了我們的組件易於維護。 我們嚴格的分清,什麼應該寫在調用組件中, 哪些內容又應該寫在子組件中,我們會考慮數據怎麼傳遞,嵌套組件的是怎麼協同工作的。

但是,假如,你可以在父組件中,寫子組件的dom呢?

這麼說,可能很疑惑,我一開始因爲完全不明白,因爲這種模式,以往我們從未遇見過。

以下是一個示例,看完就知道了:

//index
<template>
  <div>
    <Child></Child>
  </div>
</template>
<script>
import Child from "./comps/index.vue";
export default {
  components: {
    Child,
  },
};
</script>
<template>
  <div>
    <p>
      <progress :value="count" max="100"> </progress>
    </p>
    <button @click="count++">click download</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
};
</script>

這是一個再簡單不過的父子組件了:

img

我們在子組件中定義了一個進度條元素,這是H5的原生元素,然後我們通過點擊,讓進度條變化。

現在,我們子組將中dom 上<template><template/> 包裹的所有內容,都叫做這個子組件的模板,我們跟習慣叫他dom, 即便它實際上編譯成html文件中真正的dom還需要很複雜底層Vue實現的過程。

Vue 允許我們有一種邊界的應用方式,可以將模板內容不寫在子組件,而寫到父組件中去。

要做到這樣只需要:

  1. 在父組件中需要調用的地方,給子組件註冊標籤元素,指定inine-template 屬性,將其標記爲一個行內模板。
  2. 將子組件中模板內容盡數剪切到template元素中間。

即:

//index
<template>
  <div>
    <Child inline-template>
      <div>
        <p>
          <progress :value="count" max="100"> </progress>
        </p>
        <button @click="count++">click download</button>
      </div>
    </Child>
  </div>
</template>
<script>
import Child from "./comps/index.vue";
export default {
  components: {
    Child,
  },
};
</script>
//Child
<template> </template>
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
};
</script>
<style></style>

它完全能夠如期運行。

image-20210926233346064

是不是非常神奇且有意思?

注意,你僅能在<Child></Child> 標籤內方式 該子組件的實例內容。但是不能訪問父組件中的實例內容。 也不能在父組件中訪問這個子組件實例的內容。

這意味着,直接想當然的像下面這樣操作是不行的哦:

<template>
  <div>
    <Child inline-template>
      <div>
        <p>
          <progress :value="count" max="100"> </progress>
        </p>
        <!-- vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'toString')" -->
        {{ name.toString }}
        <button @click="count++">click download</button>
      </div>
    </Child>
    <!-- [Vue warn]: Property or method "count" is not defined -->
    <button @click="count++">click download outside</button>
  </div>
</template>
<script>
import Child from "./comps/index.vue";
export default {
  components: {
    Child,
  },
  data() {
    return {
      num: 123,
    };
  },
};
</script>

想想看,是不是表現的就像是,除了把子組件的模板內容換到了父組件中去寫,似乎沒有任何差異?

就是如此,父子組件依然是不能直接互相訪問彼此實例的

是不是想問, 那這樣寫有個球用 ? 我幹嘛還單獨寫個子組件? 直接寫一個組件裏不就好了?

實際上,確實一般情況下是用不着的。 Vue 文檔也提醒我們,這樣使用會讓我們閱讀起來不友好,不易維護,作用域甚至可能會用的很混亂。 但是好處是,如果你的子組件數據處理邏輯很龐大,這麼寫,就可以滿足在父組件中寫子組件模板的同時,又能分隔開來父子組件的數據處理。

用不用是一回事,知不知道是另一回事嘛。

2. X-Template

<script type="text/x-template" />

實際上,這並不是一個官方的MIME type , stackoverflow 有大佬給出瞭如下解釋:

image-20210926235934762

https://stackoverflow.com/a/31460171

Vue 文檔中,使用了這種特例。

實際上,被標記爲type="text/x-template" 的script 標籤並不會被標準解析執行。

Vue 會在dom渲染後再對其進行額外處理,注意,是Vue 處理。

Vue 提供這樣一個接口的目的是怎麼被使用的?

其實,這是在你不使用webpack 、gulp 等工具的時候纔會用得到,爲了方便在那種模式下在js 中寫模板繁瑣而出現的。 假如組件的template的內容很冗長,如果都在JavaScript裏面拼接腳本,效率是非常低的,因爲不能像寫HTML那樣舒服。因此,Vue 提供了另外一種定義模板的方法:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Vue之X-Templates的使用</title>
 </head>
 <body>
  <div id="app">
  <my-component></mycomponent>
  <script type="text/x-template" id="my-component">
   <div>這是組件的內容</div>
  </script>
 </div>
<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 
<script>
 Vue.component('my-component',{
  template:'#my-component'
 });
 var app = new Vue({
  el:'#app'
 })
</script>
 </body>

參考自 link

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章