文档章节

vue单页面引入CDN链接

o
 osc_zoa3moe9
发布于 2019/12/07 16:05
字数 1366
阅读 13
收藏 0

精选30+云产品,助力企业轻松上云!>>>

不想在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'
      }
    })
  ]
)

<br/> ## 渲染函数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

o
粉丝 1
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
vue项目首屏加载优化实战

问题 单页面应用的一个问题就是首页加载东西过多,加载时间过长。特别在移动端,单页面应用的首屏加载优化更是绕不开的话题。下面我会写出我在项目中做的一些优化,希望大家能够相互讨论,共...

osc_ertc0ko2
2019/04/22
6
0
vue项目首屏加载优化实战

问题 单页面应用的一个问题就是首页加载东西过多,加载时间过长。特别在移动端,单页面应用的首屏加载优化更是绕不开的话题。下面我会写出我在项目中做的一些优化,希望大家能够相互讨论,共...

漫思
04/27
0
0
如何搭建一个vue-cli4+webpack移动端框架?本文详解

简介 这是基于 vue-cli4 实现的移动端框架,其中包含项目常用的配置,组件封装及webpack优化方法,可供快速开发使用。 技术栈:vue-cli4 + webpack4 + vant + axios + less + postcss-px2re...

程序员的人生A
06/12
0
0
搭建一个vue-cli4+webpack移动端框架(开箱即用)

简介 这是基于 vue-cli4 实现的移动端框架,其中包含项目常用的配置,组件封装及webpack优化方法,可供快速开发使用。 技术栈:vue-cli4 + webpack4 + vant + axios + less + postcss-px2re...

lzg9527
05/10
0
0
vue加载优化策略

  vue.js是一个比较流行的前端框架,与react.js、angular.js相比来说,vue.js入手曲线更加流畅,不管掌握多少都可以快速上手。但是单页面应用也都有其弊病,有时候首屏加载慢的让人捏舌。今...

osc_lit0zkpv
2019/03/19
4
0

没有更多内容

加载失败,请刷新页面

加载更多

python每日经典算法题5(基础题)+1(中难题)

  现在,越来越多的公司面试以及考验面试对算法要求都提高了一个层次,从现在,我讲每日抽出时间进行5+1算法题讲解,5是指基础题,1是指1道中等偏难。希望能够让大家熟练掌握python的语法结...

osc_9we1w99u
9分钟前
0
0
vue中通过路由跳转的三种方式

router-view 实现路由内容的地方,引入组件时写到需要引入的地方 需要注意的是,使用vue-router控制路由则必须router-view作为容器。 通过路由跳转的三种方式 1、router-link 【实现跳转最简...

dragon_tech
9分钟前
14
0
秃顶顶少年团-冲刺总结

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1/homewor......

osc_ed2py9ot
11分钟前
0
0
往事不堪回首

开局一张图,内容全靠编 从12年大学毕业到如今,兜兜转转,依然在码工,码农,码代码的路上徘徊着,从最初的用asp.net写站点,写内部的CRM,内部管理系统,内部的XXX,很难想象内部的系统居然...

osc_nvkeo9cj
12分钟前
10
0
一款很好用的前端公、农历转换插件

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, ......

osc_qo89by3k
13分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部