Vue & Bootstrap 連繫進修筆記(二)

本文重要形貌鄙人在進修Vue和Bootstrap中碰到的關於插槽的題目及處置懲罰方案

插槽明白

vue官網和許多熱情朋儕又許多關於默許插槽,簽字插槽,插槽作用域相干的詮釋,我就不反覆搬過來佔用篇幅了,這裏簡樸的談談我個人的膚見。

  • 插槽就是預留位置
    插槽實在就是定義組件時預留的一些位置,將運用組件時組件內分外的一些標籤寫入到對應的預留位置就是插槽的作用了。
  • 插槽適用於不牢固內容的組件
    恰是由於沒法預感組件內部一切可以的標籤或內容,所以痛快留一個空白,全權交給運用者,想填啥就用啥。
  • 簽字插槽適用於具有一定構造且有多處不牢固內容的組件
    此時在定義組件時實在就是預留了多個空白位置且離別定名(假如只要一個固然也可以採納簽字插槽,但一定不如默許插槽,只會徒增設置本錢)。然後在運用時將內容分紅多塊離別定名成預留空白位置的名字。

組件明白

為何要定義組件?
答:定義組件是一種封裝的情勢,運用最簡樸的標籤及屬性設置表達一大段比較豐富的構造結果及一些數據和事宜。

Bootstrap組件-Collapse(Accordion example)

官網HTML代碼

<div id="accordion">
  <div class="card">
    <div class="card-header" id="headingOne">
      <h5 class="mb-0">
        <button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
          Collapsible Group Item #1
        </button>
      </h5>
    </div>

    <div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordion">
      <div class="card-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingTwo">
      <h5 class="mb-0">
        <button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
          Collapsible Group Item #2
        </button>
      </h5>
    </div>
    <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordion">
      <div class="card-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingThree">
      <h5 class="mb-0">
        <button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
          Collapsible Group Item #3
        </button>
      </h5>
    </div>
    <div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordion">
      <div class="card-body">
        Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
      </div>
    </div>
  </div>
</div>
  • 該示例代碼比較長
  • 構造是很有規律的,很輕易發明幾個配合的構造:card, card-header, card-body…
  • 案牘是詳細的展現信息,也是我們願望組件可以設置的

最精簡的組件設置

<widget-collapse>
    <div header="Collapsible Group Item #1">
        Anim pariatur ...
    </div>
    <div header="Collapsible Group Item #2">
        Anim pariatur ...
    </div>
    <div header="Collapsible Group Item #3">
        Anim pariatur ...
    </div>
</widget-collapse>
  • header平常文本就夠用了,所以直接設置在標籤屬性上
  • content, 如’Anim pariatur …’我們料想其多是其他的一個或多個組件以至大段html(會有標籤),此時放到屬性內就不適宜了,設置起來超等貧苦

組件封裝

  • 獵取header簡樸。遍歷$children從其attrs對象中可以讀取到,放到data中的一個數組裡,採納v-for指令即可很輕易襯着出來
  • 獵取content不輕易。$children都是假造DOM,反向變成html的API沒找到;再者就算找到了,同header一樣遍歷襯着出來,也只是當做字符串襯着出來,加上v-html指令,規範的HTML標籤卻是確切襯着出來了,可已定義的組件標籤未能準確剖析襯着(不知道vue有無響應的API要領處置懲罰)。
  • 插槽<slot></slot>恰好可以處置懲罰內容中的標籤剖析題目,但它會將一切的內容(上例中3個div)都剖析到一同沒法拆分
  • 簽字插槽<slot name="..."></slot>可以處置懲罰內容沒法拆分的題目。那我們就把內容中的每一個都標一個name, name取值要滿足內容個數不定的前提,所以最好採納和序號有關的,恰好可以在v-for指令中匹配到。
  • 題目處置懲罰!

組件定義

Vue.component('widget-collapse', {
    template: `<div>
        <div class="card" v-for="(item, index) in vitems">
            <div class="card-header">
                <h5 class="mb-0">
                    <button class="btn btn-link" data-toggle="collapse">{{item.header}}</button>
                </h5>
            </div>

            <div :class="['collapse']">
                <div class="card-body">
                    <slot :name="index"></slot>
                </div>
            </div>
        </div>
    </div>`,
    data() {
        let children = this.$slots, items = [];
        for (let i in children) {
            let node = children[i][0];
            if (node.tag) {
                items[i] = ({
                    header: VTool.attr(node, 'header') || ('Item ' + items.length),
                })
            }
        }
        return {
            vitems: items
        }
    }
})

組件運用

<widget-collapse>
    <div header="Collapsible Group Item #1" slot="0">
        Anim pariatur ...
    </div>
    <div header="Collapsible Group Item #2" slot="1">
        Anim pariatur ...
    </div>
    <div header="Collapsible Group Item #3" slot="2">
        Anim pariatur ...
    </div>
</widget-collapse>

組件優化

運用時每一個節點都寫一個slot太累墜,輕易寫錯,刪除某個節點或調解節點遞次后變動貧苦,可否順序動態幫助增添該slot屬性?
答:未找到對應API,但對照默許與簽字插槽的$slots數據對象發明key離別為default和簽字name

動態增添$slots屬性值

Vue.component('widget-collapse', {
    template: `<div>
            <div class="card" v-for="(item, index) in vitems">
                <div class="card-header">
                    <h5 class="mb-0">
                        <button class="btn btn-link" data-toggle="collapse">{{item.header}}</button>
                    </h5>
                </div>

                <div :class="['collapse']">
                    <div class="card-body">
                        <slot :name="item.id"></slot>
                    </div>
                </div>
            </div>
        </div>`,
    data() {
        let children = this.$slots.default, items = [];
        for (let i = 0, len = children.length; i < len; i++) {
            let node = children[i];
            if (node.tag) {
                let id = VTool.random();
                this.$slots[id] = node;
                items.push({
                    id: id,
                    header: VTool.attr(node, 'header') || ('Item ' + items.length),
                })
            }
        }
        return {
            vitems: items
        }
    }
})

刪除運用時的插槽定名

<widget-collapse>
    <div header="Collapsible Group Item #1">
        Anim pariatur ...
    </div>
    <div header="Collapsible Group Item #2">
        Anim pariatur ...
    </div>
    <div header="Collapsible Group Item #3">
        Anim pariatur ...
    </div>
</widget-collapse>

同步更新

  • 以上設置基礎初始化是沒有任何題目了,但在vue對象更新時會變動$slots對象
    (經跟蹤代碼查找到updateChildComponent要領內涵更新基層組件時執行了vm.$slots = resolveSlots(renderChildren, parentVnode.context);掩蓋了之前縮處置懲罰過的$slots,且會在vm._render要領中從新襯着,且在此之前沒有宣布任何事宜,那就暴力掩蓋重寫了)
Vue.component('widget-collapse', {
    ...
    created() {
        let _render = this._render;
        this._render = function() {
            let $slots = this.$slots;
            for (let name in $slots) {
                if (name !== 'default') {
                    return _render.apply(this, arguments);
                }
            }
            // 此時一定是從新new的$slots, 重寫對應關聯
            let children = this.$slots.default, items = [];
            for (let i = 0, len = children.length; i < len; i++) {
                let node = children[i];
                if (node.tag) {
                    let id = VTool.random();
                    this.$slots[id] = node;
                    items.push({
                        id: id,
                        header: VTool.attr(node, 'header') || ('Item ' + items.length),
                    })
                }
            }
            this.vitems = items;
            return _render.apply(this, arguments);
        }
    },
    ...
})

本文關於vue插槽的處置懲罰方法略顯暴力,但確實處置懲罰了我碰到的題目,列位大拿有更好的履歷還請不吝賜教,拜謝!

    原文作者:石俠
    原文地址: https://segmentfault.com/a/1190000015351130
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞