1. 程式人生 > >Vue——元件封裝天龍八步

Vue——元件封裝天龍八步

關鍵詞:
data/$data         資料依賴
props/$props       父元件傳值通道
slot                分發
created             Vue生命週期
$listeners         靜態函式傳遞
$emit              事件傳遞
$on                    事件繫結
watch               監聽資料變化
provide             向父元件傳遞資料
inject              子元件接受接收
$attrs             靜態資料傳遞
inheritAttrs        標籤美化
中心思想

子元件擁有自身狀態的同時,允許父元件對自身進行任何操作

生命週期

元件的進階封裝,需要對Vue生命週期有簡單的瞭解

需要了解的小夥伴請檢視我的另一篇部落格:

本文以button元件封裝為例

基礎元件
export const GlobelButton = {
  template: `
  <div>
    <button type="button" :style="style">
      {{title}}
    </button>
  </div>
  `,
  data
() { return { style: { backgroundColor: '#b50136', fontSize: '12px', color: '#fff' }, title: 'title' } } }

暴露出一個button元件,已經在子元件內部寫好樣式,父元件可以直接引用

允許父元件控制title屬性
export const GlobelButton = {
  template: `
  <div>
    <button type="button"
:style="style">
{{title}} </button> </div>
`, data () { return { style: { backgroundColor: '#b50136', fontSize: '12px', color: '#fff' } #################### // title: 'title' #################### } }, #################### props: { // innerHtml 文案 title: { type: String, default: function () { return '暫未定義title' } } } ##################### }

允許父元件傳入的title值覆蓋子元件本身資料,併為子元件提供預設資料 #區域為修改區域

為元件增加插槽
export const GlobelButton = {
  template: `
  <div>
      ###########
      <slot name="first"></slot>
      ########
        <button type="button" :style="style">
          {{title}}
        </button>
      ###########
      <slot name="end"></slot>
      #############
  </div>
  `,
  data () {
    return {
      style: {
        backgroundColor: '#b50136',
        fontSize: '12px',
        color: '#fff'
      }
    }
  },
  props: {
    // innerHtml 文案
    title: {
      type: String,
      default: function () { return '暫未定義title' }
    }
  }
}

插槽的新增很多程度上擴充套件了元件的靈活性,允許父元件任意的增加DOM

將樣式控制交給父元件
export const GlobelButton = {
  template: `
  <div>
      <slot name="first"></slot>
        <button type="button" :style="style">
          {{title}}
        </button>
      <slot name="end"></slot>
  </div>
  `,
  ######################
  created () {
    const styled = this.styled || {}

    if (!styled) return

    if (styled instanceof Object || JSON.stringify(styled) !== '{}') {
      for (const key in styled) {
        this.style[key] = styled[key]
      }
    }
  },
  #######################
  data () {
    return {
      style: {
        backgroundColor: '#b50136',
        fontSize: '12px',
        color: '#fff'
      }
    }
  },
  props: {
    // innerHtml 文案
    title: {
      type: String,
      default: function () { return '暫未定義title' }
    },
    ########################
    // 樣式
    styled: {
      type: Object,
      default: function () { return {} }
    }
    #######################
  }
}

元件中的樣式是通過物件style來控制的,如何才能做到讓父元件動態控制style物件的值呢?在Vue——神祕的生命週期一文中我們知道,created生命週期中dataprops都已經準備完畢,那麼我們就可以在這裡做一些改變。

改變父元件狀態
export const GlobelButton = {
  template: `
  <div>
      <slot name="first"></slot>
      ################
        <button type="button" :style="style"  @click="changeBg">
      #################
          {{title}}
        </button>
      <slot name="end"></slot>
  </div>
  `,
  created () {
    const styled = this.styled || {}

    if (!styled) return

    if (styled instanceof Object || JSON.stringify(styled) !== '{}') {
      for (const key in styled) {
        this.style[key] = styled[key]
      }
    }
  },
  data () {
    return {
      style: {
        backgroundColor: '#b50136',
        fontSize: '12px',
        color: '#fff'
      }
    }
  },
  ########################
  methods: {
    changeBg () {
      this.style.backgroundColor = 'green'
      this.$emit('change-color', 'green')
    }
  },
  ########################
  props: {
    // innerHtml 文案
    title: {
      type: String,
      default: function () { return '暫未定義title' }
    },
    // 樣式
    styled: {
      type: Object,
      default: function () { return {} }
    }
  }
}

我們經常會遇到需要同步改變子元件以及父元件狀態的情況,如dialog的顯示和隱藏狀態的觸發,然而Vue並不建議我們直接修改props的值,此時我們可以藉助emitthis.listeners中由父元件$on繫結的方法,自然也可以配合watch使用,監聽父元件的值並同步修改子元件狀態

接受父元件公共狀態
export const GlobelButton = {
  template: `
  <div>
      <slot name="first"></slot>
        <button type="button" :style="style"  @click="changeBg">
          {{title}}
        </button>
        #############
        {{inject}}
        #############
      <slot name="end"></slot>
  </div>
  `,
  created () {
    const styled = this.styled || {}

    if (!styled) return

    if (styled instanceof Object || JSON.stringify(styled) !== '{}') {
      for (const key in styled) {
        this.style[key] = styled[key]
      }
    }
  },
  data () {
    return {
      style: {
        backgroundColor: '#b50136',
        fontSize: '12px',
        color: '#fff'
      }
    }
  },
  #################
  inject: ['inject'],
  #################
  methods: {
    changeBg () {
      this.style.backgroundColor = 'green'
      this.$emit('change-color', 'green')
    }
  },
  props: {
    // innerHtml 文案
    title: {
      type: String,
      default: function () { return '暫未定義title' }
    },
    // 樣式
    styled: {
      type: Object,
      default: function () { return {} }
    }
  }
}

對於某些情況下,一個父元件可能擁有多個子元件,此時父元件的功能狀態可以通過provide: { inject: ‘test provide’ }傳遞,子元件中inject接受到的資料可以直接用this訪問

靜態屬性的傳遞
export const GlobelButton = {
  template: `
  <div>
      <slot name="first"></slot>
        <button type="button" :style="style"  @click="changeBg">
          {{title}}
        </button>
        {{inject}}
      <slot name="end"></slot>
  </div>
  `,
  created () {
    const styled = this.styled || {}

    if (!styled) return

    if (styled instanceof Object || JSON.stringify(styled) !== '{}') {
      for (const key in styled) {
        this.style[key] = styled[key]
      }
    }
  },
  data () {
    return {
      style: {
        backgroundColor: '#b50136',
        fontSize: '12px',
        color: '#fff'
      },
      ##############
      attrs: this.$attrs
      ##############
    }
  },
  #################
  inheritAttrs: false
  #################
  inject: ['inject'],
  methods: {
    changeBg () {
      this.style.backgroundColor = 'green'
      this.$emit('change-color', 'green')
    }
  },
  props: {
    // innerHtml 文案
    title: {
      type: String,
      default: function () { return '暫未定義title' }
    },
    // 樣式
    styled: {
      type: Object,
      default: function () { return {} }
    }
  }
}

在開發過程中經常會出現父元件向孫子元件傳值,父元件向子元件傳遞多個靜態屬性,此時我們可以藉助$attrs來接受所有沒有在props中定義,但是父元件呼叫子元件確綁定了的值,同時為了使繫結值不出現在DOM渲染中,從而保證DOM樹的整潔,我們需要藉助:inheritAttrs: false

需要注意的是$attrsbeforeCreate中已經準備好了,並且不會進行響應式資料變化,所以傳遞的一定要是靜態屬性

相關推薦

Vue——元件封裝天龍

關鍵詞: data/$data 資料依賴 props/$props 父元件傳值通道 slot 分發 created Vue生命週期 $listeners 靜態

Typescript版本VUE+元件封裝+最簡單的策略模式,地址選擇

前言 去年做的公司專案,最近再從做升級2.0版本。因為需求是使用者需要填寫五級地址,從省到你家的自然村。 之前一個專案做過,因為在整個專案中只用到了一次,也沒去封裝。 現在使用者新增修改地址用得上,商家註冊,商家員工新增也要用上……那麼多場景我在不封裝要被打死…… 如果不想看文章的可以直接去 gayh

《惢客創業日記》2018.10.12(週五) 聲音主播背後的“天龍”(一)

  今天的主要任務是為《惢客創業日記》的後期音訊處理工作寫一個操作說明和製作一張操作流程表,主要目的是讓一個菜鳥也能輕鬆的通過GoldWave等音訊軟體來進行後期音訊處理工作。通過昨天和今天的努力,兩個檔案終於都做好了,圖文並茂的整整13頁。從9月份開始準備《惢客創業日記》,不管是文字版還是喜

eos原始碼賞析(二十):EOS智慧合約之push_transaction的天龍

很久沒談《天龍八部》了。 eosio整個系統中,transaction佔據著十分重要的位置。我們在區塊鏈上的任何有效操作,都代表著有transaction被執行了。在執行的過程中,push_transaction是不可以被忽略的。例如我們建立賬戶的時候,會通過p

eos原始碼賞析(二十一):EOS智慧合約之區塊簽名的天龍

在上篇文章中我們提到了,由使用者操作會產生各種事務,事務的鏈上執行是由push_transaction來完成的,我們簡單的劃分了下,具體可參考eos原始碼賞析(二十):EOS智慧合約之push_transaction的天龍八“步” 。我們知道,在區塊生產或者打包

Vue元件封裝 引數傳遞和事件傳遞

引數傳遞 子元件先定義好接收的引數和事件 <div > {{title}} <div class="row"> <Button icon="md-refresh" @click="refresh()" >重新整理&l

《惢客創業日記》2018.10.15(週一) 聲音主播背後的“天龍”(二)

  今天,抽時間補完了10月12日沒寫完的下半部分《聲音主播背後的“天龍八步”(二)》,在上半部分給大家分享了文案、聲音錄製、音量調節和降噪四個步驟,接下來再給大家分享後面的四個步驟。咱們先從第五個步驟聲音剪輯開始。   如果你聽過NG這個詞,就會明白,一部完整的作品在

SEO如何優化關鍵詞排名?這招天龍""一看就會

SEO如何優化關鍵詞排名?這個問題一直是困擾廣大SEO朋友的問題之一,大家知道優化有價值的關鍵詞到首頁後,會獲得可觀的流量和轉化,其實SEO優化技術說簡單也簡單,說難也難,難是因為搜尋引擎不斷更新演算法,簡單也是因為不管怎麼更新都萬變不離其宗,使用者體驗至上,想成為SEO天龍

vue元件封裝之Promise到的方式呼叫

vue元件封裝 需求:很多場景,如confirm或者彈出的輸入框,都需要後續做處理,之前自己簡單的傳入一個 回撥函式覺得程式碼不好維護,遂想到使用Promise物件封裝,呼叫之後返回一個Pro

vue元件封裝及父子元件傳值,事件處理

vue開發中,把有統一功能的部分提取出來,作為一個獨立的元件,在需要使用的時候引入,可以有效減少程式碼冗餘.難點在於如果封裝,使用,如何傳參,派發事件等,我會採取倒敘的方式進行說明.(本文總結於Vue2實戰解密一書)程式碼如下:封裝元件BookList.vue &lt;template&g

vue 元件封裝

把我們所需要的功能寫在一個元件裡面     比如 /*popout*/ 1:在components裡面建立資料夾popout 以及index.js和popout,vue 2:在index,js裡面去匯出popout.vue import Popout from "./p

vue元件封裝-radiogroup

先上圖CSS部分 樣式還可以自己調整哈.ui-radio{ width: 14px; height: 14px; border-radius: 50%; border: 1px solid #4693fe; display: inlin

vue 元件封裝 swiper輪播圖

第一步安裝:npm install vue-awesome-swiper --save 第二部在main.js裡引入: import Vue from 'vue' import VueAwesomeSwiper from 'vue-awesome-swiper' impo

vue元件開發之導航選單元件封裝

執行結果: 呼叫程式碼部分: <template> <div id="app"> <menu-bar :list="list" @click="menuClick"></menu-bar> <!--fir

vue封裝可複用的元件

本次封裝的元件以toast元件為例 以前使用移動端ui外掛時,通過一句程式碼比如 $.toast( ‘ 需要顯示的內容 ’ ),從而在頁面上展示這段文字,並在一定時間後消失。 現在我們也嘗試自己封裝toast元件。 準備工作:vue-cli腳手架工程 先看一下涉及到的檔案目錄截圖:

基於vue element 封裝上傳元件

 基於vue element封裝的上傳元件 使用方法: 1.首先引入該元件 2.註冊元件 3.頁面使用 4.回撥函式(如需其他回撥自行封裝 因為我暫時沒用到其他的  哈哈哈)   <template>

手把手教你封裝 Vue 元件並使用 NPM 釋出

Vue 開發外掛 我們可以先檢視Vue的外掛的開發規範 我們開發的之後期望的結果是支援 import、require 或者直接使用 script 標籤的形式引入,就像這樣: ps: 這裡注意一下包的名字字首是 unisoft ,元件的名字字首是 uni import UniSoftUI from 'uniso

封裝 Vue 元件並使用 NPM 釋出

Vue 開發外掛 我們可以先檢視Vue的外掛的 開發規範 我們開發的之後期望的結果是支援 import、require 或者直接使用 script 標籤的形式引入,就像這樣: ps: 這裡注意一下包的名字字首是 unisoft ,元件的名字字首是 uni import

vue封裝echarts折線圖元件

 先來張圖 要實現在父元件引用子元件圖表,父元件需要傳遞給圖表元件幾個資料, id: 圖表例項化需要一個唯一的id; time: x軸的顯示資料,引數名可以自己定義; opData: 用來配置series的系列列表,引數可以自己定義; unit: y軸單

vue_music:封裝scroll.vue元件

在專案中經常用到滾動,結合Better-scroll封裝了sroll.vue元件參考連結:https://ustbhuangyi.github.io...http://www.imooc.com/article/...**better-scroll 只處理容器(wrapper)的第一個子元素(content)