• 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

  • 相关阅读:
    燃尽的一个不便之处修改
    jquery给元素添加样式表的方法
    http协议
    春节读书
    file_get_contents(): php_network_getaddresses: getaddrinfo failed: Name or service not known
    jQuery on(),live(),trigger()
    jquery ui中的dialog,官网上经典的例子
    问题:循环元素,被选中元素个数,全选
    3.5星|《小学问》:年轻人思维与婚恋常见误区解析
    正念疗法入门介绍,作者是日籍美国正念疗法医生:3星|《高效休息法》
  • 原文地址:https://www.cnblogs.com/dreamsqin/p/12002063.html
Copyright © 2020-2023  润新知