vue單頁面引入CDN鏈接


不想在index.html文件中全局引入CDN資源,那么如何在Vue單文件組件中引入?下面來瞅瞅~

虛擬DOM創建

Vue 通過創建一個虛擬 DOM 來追蹤自己要改變的真實 DOM

  • 什么是虛擬DOM?
return createElement('h1', this.blogTitle)

createElement實際返回的是createNodeDescription而非實際上的DOM元素,因為它所包含的信息會告訴Vue頁面上需要渲染什么樣的節點,包括及其子節點的描述信息。這樣的節點稱為“虛擬節點 (virtual node)”,也常簡寫為“VNode”。“虛擬 DOM”是整個 VNode 樹(由 Vue 組件樹建立起來)的稱呼。

  • createElement函數參數

createElement函數中可以使用模板中的功能,它接收的參數有:

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // 一個 HTML 標簽名、組件選項對象,或者
  // resolve 了上述任何一種的一個 async 函數。必填項。
  'div',

  // {Object}
  // 一個與模板中屬性對應的數據對象。可選。
  {
      // 與 `v-bind:class` 的 API 相同,
      // 接受一個字符串、對象或字符串和對象組成的數組
      'class': {
        foo: true,
        bar: false
      },
      // 與 `v-bind:style` 的 API 相同,
      // 接受一個字符串、對象,或對象組成的數組
      style: {
        color: 'red',
        fontSize: '14px'
      },
      // 普通的 HTML 特性
      attrs: {
        id: 'foo'
      },
      // 組件 prop
      props: {
        myProp: 'bar'
      },
      // DOM 屬性
      domProps: {
        innerHTML: 'baz'
      },
      // 事件監聽器在 `on` 屬性內,
      // 但不再支持如 `v-on:keyup.enter` 這樣的修飾器。
      // 需要在處理函數中手動檢查 keyCode。
      on: {
        click: this.clickHandler
      },
      // 僅用於組件,用於監聽原生事件,而不是組件內部使用
      // `vm.$emit` 觸發的事件。
      nativeOn: {
        click: this.nativeClickHandler
      },
      // 自定義指令。注意,你無法對 `binding` 中的 `oldValue`
      // 賦值,因為 Vue 已經自動為你進行了同步。
      directives: [
        {
          name: 'my-custom-directive',
          value: '2',
          expression: '1 + 1',
          arg: 'foo',
          modifiers: {
            bar: true
          }
        }
      ],
      // 作用域插槽的格式為
      // { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: props => createElement('span', props.text)
      },
      // 如果組件是其它組件的子組件,需為插槽指定名稱
      slot: 'name-of-slot',
      // 其它特殊頂層屬性
      key: 'myKey',
      ref: 'myRef',
      // 如果你在渲染函數中給多個元素都應用了相同的 ref 名,
      // 那么 `$refs.myRef` 會變成一個數組。
      refInFor: true
},

  // {String | Array}
  // 子級虛擬節點 (VNodes),由 `createElement()` 構建而成,
  // 也可以使用字符串來生成“文本虛擬節點”。可選。
  [
    '先寫一些文字',
    createElement('h1', '一則頭條'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

渲染函數render

Vue 推薦在絕大多數情況下使用模板來創建HTML,然而在一些場景中,你需要發揮 JavaScript 最大的編程能力,這時可以用渲染函數,它比模板更接近編譯器。

  • 類型

(createElement: () => VNode) => VNode

渲染函數接收一個createElement方法作為第一個參數來創建VNode;如果組件是一個函數組件,渲染函數還會接收一個額外的 context 參數,為沒有實例的函數組件提供上下文信息。

例子:假設我們要生成一些帶錨點的標題

<h1>
  <a name="hello-world" href="#hello-world">
    Hello world!
  </a>
</h1>
  • 模板實現
<anchored-heading :level="1">Hello world!</anchored-heading>

<script type="text/x-template" id="anchored-heading-template">
  <h1 v-if="level === 1">
    <slot></slot>
  </h1>
  <h2 v-else-if="level === 2">
    <slot></slot>
  </h2>
  <h3 v-else-if="level === 3">
    <slot></slot>
  </h3>
  <h4 v-else-if="level === 4">
    <slot></slot>
  </h4>
  <h5 v-else-if="level === 5">
    <slot></slot>
  </h5>
  <h6 v-else-if="level === 6">
    <slot></slot>
  </h6>
</script>
Vue.component('anchored-heading', {
  template: '#anchored-heading-template',
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

這里用模板並不是最好的選擇:不但代碼冗長,而且在每一個級別的標題中重復書寫了<slot></slot>,在要插入錨點元素時還要再次重復。

  • render實現
<anchored-heading :level="1">Hello world!</anchored-heading>
Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // 標簽名稱
      this.$slots.default // 子節點數組
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

這樣代碼就精簡很多,需要注意的是向組件中傳遞不帶v-slot指令的子節點時,比如anchored-heading中的 Hello world!,這些子節點被存儲在組件實例中的$slots.default中。

Vue單頁面引入CDN鏈接

在了解了render函數createElement函數的基礎上,想要實現Vue單頁面引入CDN鏈接就簡單很多了。

  • 首先采用createElement創建不同資源類型(以js、css為例)的VNode
// js CDN
createElement('script', {
    attrs: {
        type: 'text/javascript',
        src: this.cdn
    }
})
// css CDN
createElement('link', {
    attrs: {
        rel: 'stylesheet',
        type: 'text/css',
        href: this.cdn
    }
})
  • 然后基於上述VNode,采用render創建函數式組件remote-jsremote-css
components: {
    'remote-js': {
        render(createElement) {
            return createElement('script', {
                attrs: {
                    type: 'text/javascript',
                    src: this.cdn
                }
            })
        },
        props: {
            cdn:  {
                type: String,
                required: true
            }
        }
    },
    'remote-css': {
        render(createElement) {
            return createElement('link', {
                attrs: {
                    rel: 'stylesheet',
                    type: 'text/css',
                    href: this.cdn
                }
            })
        },
        props: {
            cdn:  {
                type: String,
                required: true
            }
        }
    }
}
  • Vue單頁面引入
<template>
    <div class="my-page">
        <remote-js cdn="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></remote-js>
        <remote-css cdn="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css"></remote-css>
    </div>
</template>
  • 彩蛋(=。=)

如果你覺得render函數寫起來很費勁的話,就可以利用Bable插件,在Vue 中使用 JSX ,讓我們可以無限接近於模板語法。上述代碼就變成下面這樣了,好像是順眼了一丟丟吧:

components: {
    'remote-js': {
        render(h) {
            return (
                <script type= 'text/javascript' src={this.cdn}></script>
            )
        },
        props: {
            cdn:  {
                type: String,
                required: true
            }
        }
    },
    'remote-css': {
        render(h) {
            return (
                <link rel='stylesheet' type='text/css' href={this.cdn} />
            )
        },
        props: {
            cdn:  {
                type: String,
                required: true
            }
        }
    }
}

Ps:將 h 作為 createElement 的別名是 Vue 生態系統中的一個通用慣例,實際上也是 JSX 所要求的。

最終效果就是只有訪問當前頁(my-page)時,CDN資源才會加載,不會像以前放在index.htmlmain.js中那樣全局加載。

參考資料

1、render:https://cn.vuejs.org/v2/guide/render-function.html
2、createElement:https://cn.vuejs.org/v2/guide/render-function.html#createElement-%E5%8F%82%E6%95%B0
3、如何在VUE單頁面引入CSS、JS(CDN鏈接):https://blog.csdn.net/kielin/article/details/86649074


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM