1. <dd id="mhwbf"><track id="mhwbf"></track></dd>

  2. <em id="mhwbf"></em><dd id="mhwbf"></dd>
  3. <rp id="mhwbf"><object id="mhwbf"></object></rp>

    1. <em id="mhwbf"><ruby id="mhwbf"></ruby></em>
      <button id="mhwbf"><acronym id="mhwbf"></acronym></button>

          <dd id="mhwbf"></dd>

          『前端工程』—— 封裝Vue第三方組件的三板斧

          來源:掘金
          2021-03-26
          1850
          導語:本專欄將介紹三種技巧來使用第三方組件的Attributes(屬性)、Events(自定義事件)、Slots(插槽),至于使用第三方組件的Methods(方法)的技巧還待優化,所以稱為三板斧哈。
          閱讀本文大概需要6分鐘

          前言

          在封裝第三方組件中,經常會遇到一個問題,如何通過封裝的組件去使用第三方組件的Attributes(屬性)、Events(自定義事件)、Methods(方法)、Slots(插槽)。

          當然這個問題并不是難以解決,用普通方法解決難免陷入繁瑣重復的工作中,而且封裝的組件代碼可讀性也不高。

          本專欄將介紹三種技巧來使用第三方組件的Attributes(屬性)、Events(自定義事件)、Slots(插槽),至于使用第三方組件的Methods(方法)的技巧還待優化,所以稱為三板斧哈。

          一、使用第三方組件的屬性

          image.png

          封裝一個elementUI的el-input輸入框組件稱為myInput,若要在myInput組件上添加一個disabled屬性來禁用輸入框,要如何實現呢?一般同學會這么做

          //myInput.vue
          <template>
            <div>
              <el-input v-model="inputVal" :disabled="disabled"></el-input>
            </div>
          </template>
          <script>
          export default {
            props: {
              value: {
                type: String,
                default: '',
              },
              disabled: {
                type: Boolean,
                default: false
              }
            },
            computed: {
              inputVal: {
                get() {
                  return this.value;
                },
                set(val) {
                  this.$emit('input', val);
                }
              }
            }
          }
          </script>
          復制代碼

          過一段時間后又要在myInput組件上添加el-input組件的其它屬性,el-input組件總共有27個多屬性,那該怎么呢,難道一個個用prop傳進去,這樣不僅繁瑣而且可讀性差,可以用$attrs一步到位,先來看一下attrs的官方定義。

          $attrs: 包含了父作用域中不作為 prop 被識別 (且獲取) 的 attribute 綁定 (class 和 style 除外)。當一個組件沒有聲明任何prop 時,這里會包含所有父作用域的綁定 (class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內部組件

          //myInput.vue
          <template>
            <div>
              <el-input v-model="input" v-bind="$attrs"></el-input>
            </div>
          </template>
          復制代碼

          這還不夠,還得把inheritAttrs選項設置為false,為什么呢,來看一下inheritAttrs選項的官方定義就明白了。

          默認情況下父作用域的不被認作 props 的 attribute 綁定 (attribute bindings) 將會“回退”且作為普通的 HTML attribute 應用在子組件的根元素上。當撰寫包裹一個目標元素或另一個組件的組件時,這可能不會總是符合預期行為。通過設置 inheritAttrsfalse,這些默認行為將會被去掉。而通過 $attrs 可以讓這些 attribute 生效,且可以通過 v-bind 顯性的綁定到非根元素上。注意:這個選項不影響 class 和 style 綁定。

          簡單來說,把inheritAttrs設置為false,避免給myInput組件設置的屬性被添加到myInput組件的根元素div上。

          //myInput.vue
          <template>
            <div>
              <el-input v-model="input" v-bind="$attrs"></el-input>
            </div>
          </template>
          <script>
          export default {
            inheritAttrs: false,
            props: {
              value: {
                type: String,
                default: '',
              },
            },
            computed: {
              inputVal: {
                get() {
                  return this.value;
                },
                set(val) {
                  this.$emit('input', val);
                }
              }
            }
          }
          </script>
          復制代碼

          這樣設置后,在myInput組件上就可以直接使用el-input組件的屬性,不管后續el-input組件再增加了多少個屬性。

          二、使用第三方組件的自定義事件


          若在myIpput組件上使用el-input組件上自定義的事件呢,可能你的第一反應是this.$emit。

          //myInput.vue
          <template>
            <div>
              <el-input v-model="input" v-bind="$attrs" @blur="blur"></el-input>
            </div>
          </template>
          <script>
          export default {
            inheritAttrs: false,
            props: {
              value: {
                type: String,
                default: '',
              },
            },
            computed: {
              inputVal: {
                get() {
                  return this.value;
                },
                set(val) {
                  this.$emit('input', val);
                }
              }
            },
            methods: {
              blur() {
                this.$emit('blur')
              }
            }
          }
          </script>
          復制代碼
          <myInput v-model="value" @blur="handleBlur"></myInput>
          復制代碼

          el-input組件有4個自定義事件,還不算多,假如遇到自定義事件更多的第三方組件,要怎么辦,難道一個一個添加進去,這樣會增加一堆非必要的methods,其實可以用$listeners一步到位,先來看一下$listeners的官方定義。

          $listeners:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。它可以通過 v-on="$listeners" 傳入內部組件。

          //myInput.vue
          <template>
            <div>
              <el-input v-model="input" v-bind="$attrs" v-on="$listeners"></el-input>
            </div>
          </template>
          復制代碼

          那么在myInput組件中給el-input組件添加上v-on="$listeners",就可以在myInput組件上使用el-input組件自定義的事件。

          三、使用第三方組件的插槽

          若在myIpput組件上使用el-input組件上定義的插槽呢?這個沒有多少取巧的方法,第三方組件定義多少個插槽,在封裝的時候都得用slot標簽暴露出去。比如暴露el-input組件中的prefix插槽,代碼如下所示:

          //myInput.vue
          <template>
            <div>
              <el-input v-model="input" v-bind="$attrs" @blur="blur">
                <template #prepend>
                  <slot name="prepend"></slot>
                </template>
              </el-input>
            </div>
          </template>
          復制代碼

          四、使用第三方組件的方法

          利用ref來實現,首先在myInput組件中的el-input組件上添加一個ref="elInput"屬性,

          //myInput.vue
          <template>
            <div>
              <el-input ref="elInput></el-input>
            </div>
          </template>
          <script>
          export default {
            mounted(){
               this.elInput = this.$refs.elInput;
            }
          }
          </script>
          復制代碼

          這里要注意父子組件的mounted的執行時機,因為一般el-input組件是全局引入的,相當同步引入組件,此時el-input組件的mounted會比myInput組件的mounted先執行,所以可以在myInput組件的mounted中把this.$refs.elInput賦值到myInput組件的this的一個屬性上。

          myInput組件如何使用el-input組件的方法分兩種情況,跟myInput組件的引入有關系。

          假如myInput組件是同步引入的

          <template>
            <div>
              <myInput ref="myInput"></myInput>
            </div>
          </template>
          <script>
          import myInput from './myInput.vue';
          export default {
            data() {
              return {
              }
            },
            components: {
              myInput,
            },
            mounted() {
              //調用el-input組件的focus方法
              this.$refs.myInput.elInput.focus();
            }
          }
          </script>
          復制代碼

          假如myInput組件是異步引入的

          <template>
            <div>
              <myInput ref="myInput"></myInput>
            </div>
          </template>
          <script>
          export default {
            data() {
              return {
              }
            },
            components: {
              myInput: () => import('./myInput.vue')
            },
            mounted() {
              //調用el-input組件的focus方法
              setTimeout(() => {
                 this.$refs.myInput.elInput.focus();
              })
            }
          }
          </script>



          免費獲取專屬 《策劃方案 》及報價
          免費體驗我們的業務系統、OA系統、在線教育、電商系統、智慧辦公等產品定制化方案,助力您的信息化發展之路
          即時交流
          在線咨詢 電話咨詢
          在線咨詢
          產品經理

          一對一產品經理

          180 8812 7777
          電話咨詢

          電話咨詢

          0871-6718 6978
          到訪面聊
          返回頂部
          欧美人妻久久精品,久久国产色av免费看,女人国产香蕉久久精品,伊人久久综在合线亚洲