Vue3官网-高级指南(十五)Vue 与 Web Components

文章目录

  • Vue3官网-高级指南(十五)Vue 与 Web Components
    • 1. Vue 与 Web Components
      • 在 Vue 中使用自定义元素
        • 跳过组件的解析
        • 传递 DOM Property
      • 使用 Vue 构建自定义元素
        • defineCustomElement
        • 将 SFC 作为自定义元素
        • Vue 自定义元素库的提示
      • 对比 Web Components 与 Vue 组件

总结:

  • 补充

    • Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。

    • truthy(真值):在 JavaScript 中,truthy(真值)指的是在布尔值上下文中,转换后的值为真的值。所有值都是真值,除非它们被定义为 假值(即除 false0""nullundefinedNaN 以外皆为真值)。括号内都是假值falsy。

    • .prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

    • ==Event.preventDefault方法取消浏览器对当前事件的默认行为。==比如点击链接后,浏览器默认会跳转到另一个页面,使用这个方法以后,就不会跳转了;再比如,按一下空格键,页面向下滚动一段距离,使用这个方法以后也不会滚动了。该方法生效的前提是,事件对象的cancelable属性为true,如果为false,调用该方法没有任何效果。

    • vue:用组件(app.component)构建一个模板(template),并反复使用模板

    • 父组件、子组件

      • const app = Vue.createApp({components: {'component-a': ComponentA,'component-b': ComponentB}
        })
        
      • 上面代码中app为父组件,ComponentA和ComponentB为子组件

      • context.emit

        • 父组件通过 :data="data" 传递数据
        • 父组件通过 @fun="fun" 传递方法
        • 子组件通过 props 接收父组件传递的值
        • 子组件通过 $emit 调用父组件的方法并传递数据
    • Vue中美元$符号的意思

      • 除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。
      • vue中$refs的作用?
        • 当我们需要获取一个dom元素进行操作的时候 可以利用原生js的getElementByXxx 而在vue中可以设置refs来获取这个dom元素
    • 第三方网站

      • greensock API(GSAP):是一套用于所有主流浏览器中制作高性能html5动画的工具。他们有一个很棒的 ease visualizer,帮助你建立精心制作的画架。

        • GSAP的全名是==GreenSock Animation Platform,这个名字是有些怪异(官网还在各种安利你加入它的Club),但它的确是一个从flash时代一直发展到今天的专业动画库。==参照CSDN:https://blog.csdn.net/weixin_39939012/article/details/80833073
      • animate.css :集成第三方 CSS 动画库
      • CSS Triggers :来查看哪些属性会在动画时触发重绘。这个网站是用来告诉开发者不同内核浏览器对css属性修改的重绘/回流情况,开发者知道了这些细节可以提高页面性能。
    • JavaScript钩子

      • 添加 :css="false",也会让 Vue 会跳过 CSS 的检测,除了性能略高之外,这可以避免过渡过程中 CSS 规则的影响。
    • 解构(Destructuring)

      • ES6允许按照一定模式从数组和对象中提取值,然后对变量进行复制,这被称为解构(Destructuring)
    • API参考

      • https://v3.cn.vuejs.org/api/refs-api.html#ref
    • 自定义指令

      • 注意,在 Vue 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
    • 渲染函数

      • Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。
  • Web Components

    • 简介

      • 一组 Web 原生 API 的总称,允许开发人员创建可重用的自定义组件。

1. Vue 与 Web Components

Web Components 是一组 Web 原生 API 的总称,允许开发人员创建可重用的自定义组件。

我们认为 Vue 和 Web Components 大体上是互补的技术。Vue 能很好地解析和创建自定义元素。不论是在将自定义元素整合到已有的 Vue 应用中,还是使用 Vue 构建和分发自定义元素,你都能获得很好的支持。

在 Vue 中使用自定义元素

Vue 在 Custom Elements Everywhere 测试中获得了 100% 的完美分数。Vue 应用程序中解析出的自定义元素大体上和原生 HTML 元素相同,但需要牢记以下几点:

跳过组件的解析

默认情况下,Vue 会优先尝试将一个非原生的 HTML 标签解析为一个注册的 Vue 组件,如果失败则会将其渲染为自定义元素。这种行为会导致在开发模式下的 Vue 发出“failed to resolve component”的警告。如果你希望 Vue 能将某些确切的元素作为自定义元素处理并跳过组件解析,请指定 compilerOptions.isCustomElement 选项。

如果你正在构建步骤中使用 Vue,则此选项需要通过构建配置传递,因为这是一个编译时选项。

Example In-Browser Config

// Only works if using in-browser compilation.
// If using build tools, see config examples below.
app.config.compilerOptions.isCustomElement = tag => tag.includes('-')

Vite 配置示例

// vite.config.js
import vue from '@vitejs/plugin-vue'export default {plugins: [vue({template: {compilerOptions: {// 将所有包含短横线的标签作为自定义元素处理isCustomElement: tag => tag.includes('-')}}})]
}

Vue CLI 配置示例

// vue.config.js
module.exports = {chainWebpack: config => {config.module.rule('vue').use('vue-loader').tap(options => ({...options,compilerOptions: {// 将所有以 ion- 开头的标签作为自定义元素处理isCustomElement: tag => tag.startsWith('ion-')}}))}
}

传递 DOM Property

由于 DOM attribute 只能是字符串,因此我们得将复杂数据作为 DOM property 传递给自定义元素。在自定义元素上配置 prop 时,Vue 3 会自动使用 in 操作符检查是否存在 DOM-property,如果此键存在则会优先将值配置为一个 DOM property。也就是说大多数情况下,如果自定义元素遵守推荐的最佳实践,则无需考虑这一点。

但是,在极少数情况下,数据必须作为 DOM property 传递,但自定义元素没有正确定义/反映 property (导致 in 检查失败)。此时,可以使用 .prop 修饰符强制将一个 v-bind 绑定设置为一个 DOM property:

<my-element :user.prop="{ name: 'jack' }"></my-element><!-- 等效的简写 -->
<my-element .user="{ name: 'jack' }"></my-element>

使用 Vue 构建自定义元素

自定义元素的一大好处就是它们可以与任何框架一起使用,甚至可以在没有框架的情况下使用。当你需要向可能使用不同前端技术栈的终端用户分发组件时,或者希望向最终应用程序隐藏其所用组件的实现细节时,使用自定义元素非常适合。

defineCustomElement

Vue 支持使用 defineCustomElement 方法创建自定义元素,并且使用与 Vue 组件完全一致的 API。该方法接受与 defineComponent 相同的参数,但是会返回一个扩展自 HTMLElement 的自定义元素构造函数:

<my-vue-element></my-vue-element>

1

import { defineCustomElement } from 'vue'const MyVueElement = defineCustomElement({// 在此提供正常的 Vue 组件选项props: {},emits: {},template: `...`,// defineCustomElement 独有特性: CSS 会被注入到隐式根 (shadow root) 中styles: [`/* inlined css */`]
})// 注册自定义元素
// 注册完成后,此页面上的所有的 `<my-vue-element>` 标签会被更新
customElements.define('my-vue-element', MyVueElement)// 你也可以编程式地实例化这个元素:
// (只能在注册后完成此操作)
document.body.appendChild(new MyVueElement({// initial props (optional)})
)

生命周期

  • 当元素的 connectedCallback 被首次调用时,Vue 自定义元素会在其隐式根部挂载一个内部的 Vue 组件实例。
  • 当元素的 disconnectedCallback 被调用时,Vue 会在很短的时间后检查此元素是否已被移出页面。
    • 如果元素仍在文档中,说明是移动,组件实例将被保留;
    • 如果元素已被移出文档,说明是移除,组件实例将被卸载。

Props

  • 所有使用 props 选项声明的 prop 都将在自定义元素上定义为 property。Vue 将在合适的时候自动处理 attribute / property 之间的映射。

    • Attribute 总是映射为相应的 property。
    • 基础类型 (stringbooleannumber) 的 property 会被映射为 attribute。
  • Vue 也会自动将声明为 BooleanNumber 类型的 attribute prop (始终为字符串)转换为所需的类型。例如给出以下 prop 声明:

    props: {selected: Boolean,index: Number
    }
    

    以及自定义元素用法:

    <my-element selected index="1"></my-element>
    

    在组件中,selected 会被转换为 true (boolean),index 会被转换为 1 (number)。

事件

在自定义元素中,通过 this.$emit 或在 setup 中的 emit 发出的事件会被调度为原生 CustomEvents。附加的事件参数 (payload) 会作为数组暴露在 CustomEvent 对象的 details property 上。

插槽

在组件内部,可以像往常一样使用 <slot/> 渲染插槽。但是在解析最终生成的元素时,它只接受原生插槽语法:

  • 不支持作用域插槽。

  • 传递命名插槽时,请使用 slot attribute 而非 v-slot 指令:

    <my-element><div slot="named">hello</div>
    </my-element>
    

Provide / Inject

Provide / Inject API 和组合式 API 中的 Provide / Inject 在 Vue 定义的自定义元素之间可以正常工作。但是请注意这仅适用于自定义元素之间,即 Vue 定义的自定义元素将无法注入非自定义元素的 Vue 组件提供的属性。

将 SFC 作为自定义元素

defineCustomElement 也适用于 Vue 单文件组件 (SFC)。但是,在默认工具链配置下,生产构建时 SFC 内部的 <style> 会被提取并合并到单独的 CSS 文件中。当使用 SFC 作为自定义元素时,通常需要将 <style> 标签注入自定义元素的隐式根。

官方 SFC 工具支持以“自定义元素模式”(需要 @vitejs/plugin-vue@^1.4.0vue-loader@^16.5.0 )导入 SFC。以自定义元素模式加载的 SFC 将其 <style> 标签作为 CSS 字符串内联,并在组件的 styles 选项中暴露出来,然后会被 defineCustomElement 获取并在实例化时注入隐式根。

要选用此模式,只需使用 .ce.vue 作为文件拓展名即可:

import { defineCustomElement } from 'vue'
import Example from './Example.ce.vue'console.log(Example.styles) // ["/* 内联的 css */"]// 转换为自定义元素构造器
const ExampleElement = defineCustomElement(Example)// 注册
customElements.define('my-example', ExampleElement)

如果你希望指定应在自定义元素模式下导入的文件(例如将 所有 SFC 视为自定义元素),你可以将 customElement 选项传递给相应的构建插件:

  • @vitejs/plugin-vue
  • vue-loader

Vue 自定义元素库的提示

如果使用 Vue 构建自定义元素,则此元素将依赖于 Vue 的运行时。这会导致一个 16kb 左右的基础大小开销 (具体取决于使用了多少特性)。这意味着如果你准备发布单个自定义元素,使用 Vue 可能不是最佳方案——你可能想要使用纯 JavaScript,petite-vue,或是其他专注于轻量化运行时的框架。但是,如果你要发布具有复杂逻辑的自定义元素集合,那么这点基础大小就会显得合理了,因为 Vue 可以使用非常精简的代码耦合每个组件。你准备发布的元素越多,开销权衡就越好。

如果自定义元素会在同样使用 Vue 的项目中使用,你可以选择从构建的包中外部化 Vue,这样元素就会使用与宿主应用程序相同的 Vue 副本。

我们推荐你提供一个导出独立元素的构造函数,这样你的用户就可以灵活地按需导入它们并使用他们所需的标签名注册自定义元素。你还可以导出一个能自动注册所有元素的函数以便于使用。这是一个 Vue 自定义元素库示例的入口点:

import { defineCustomElement } from 'vue'
import Foo from './MyFoo.ce.vue'
import Bar from './MyBar.ce.vue'const MyFoo = defineCustomElement(Foo)
const MyBar = defineCustomElement(Bar)// 导出独立的元素
export { MyFoo, MyBar }export function register() {customElements.define('my-foo', MyFoo)customElements.define('my-bar', MyBar)
}

如果你有许多组件,你还可以利用构建工具提供的功能,例如 Vite 的 glob 导入或是 webpack 的 require.context

对比 Web Components 与 Vue 组件

一些开发人员认为应该避免使用框架专有的组件模型,并且仅使用自定义元素以便应用程序“面向未来”。我们将在此处尝试解释为什么我们认为这种看法过于简单化了问题。

自定义元素和 Vue 组件之间确实存在一定程度的功能重叠:它们都允许我们定义具有数据传递、事件发出和生命周期管理功能的可重用组件。然而,Web Components API 是相对低级和简单的。为了构建一个实际可用的应用程序,我们需要很多平台没有涵盖的附加功能:

  • 一个声明式的、高效的模板系统;
  • 一个有助于跨组件逻辑提取和重用的响应式状态管理系统;
  • 一个能在服务器端渲染组件并在客户端集成的高效方法(SSR),这对于 SEO 和 Web 关键指标 (例如 LCP) 来说很重要。原生自定义元素 SSR 通常涉及在 Node.js 中模拟 DOM,然后序列化被改变的 DOM,而 Vue SSR 会尽可能编译为字符串连接,后者的效率更高。

作为一个考虑周到的系统,Vue 的组件模型在设计时就考虑到了这些需求。

如果你拥有一支称职的工程团队,或许可以基于原生自定义元素构建出近似效果的产品——但这也意味着你需要承担对内部框架的长期维护负担,同时失去了像 Vue 这样拥有生态系统和社区贡献的成熟的框架。

也有使用自定义元素作为其组件模型基础构建的框架,但它们都不可避免地要针对上面列出的问题引入自己的专有解决方案。使用这些框架需要学习或是购买他们对这些问题的技术决策——尽管他们可能会打广告宣传——这依旧无法使你免除后顾之忧。

我们还找到了一些自定义元素无法胜任的应用场景:

  • 激进的插槽定值会阻碍组件的整合。Vue 的作用域插槽提供了非常强大的组件整合机制,这是原生插槽所没有的,因为原生插槽的激进特性。激进特性插槽同样意味着接收组件无法控制何时或是否需要渲染一段插槽内容。
  • 目前,发布带有隐式 DOM scoped CSS 的自定义元素需要将 CSS 嵌入到 JavaScript 中,以便它们可以在运行时注入到隐式根中。在 SSR 场景中,它们还会导致重复定义样式。该领域有一些平台特性正在开发中——但截至目前,它们尚未得到普遍支持,并且仍有生产环境性能/ SSR 问题需要解决。而与此同时,Vue SFC 已经提供了 CSS 作用域机制,支持将样式提取到纯 CSS 文件中。

Vue 将始终与 Web 平台中的最新标准保持同步,如果平台提供的任何内容能使我们的工作更轻松,我们将很乐意利用它。但是,我们的目标是提供运行良好且开箱即用的解决方案。这意味着我们必须以批判的心态整合新的平台功能——这会涉及到在遵循现有标准的前提下弥补标准的不足。

Vue3官网-高级指南(十五)Vue 与 Web Components相关推荐

  1. Vue3官网-高级指南(十七)响应式计算`computed`和侦听`watchEffect`(onTrack、onTrigger、onInvalidate、副作用的刷新时机、`watch` 、pre)

    Vue3官网-高级指南(十七)响应式计算computed和侦听watchEffect(onTrack.onTrigger.onInvalidate.副作用的刷新时机.watch .pre).渲染机制和 ...

  2. Vue3官网-可复用组合式API(十四)实例 property(\$slots,\$attrs)、渲染函数render(虚拟节点VNode,h() 参数,使用JavaScript代替模板功能),插件

    Vue3官网-可复用&组合式API(十四)实例 property($slots,$attrs).渲染函数render(虚拟节点VNode,h() 参数,使用JavaScript代替模板功能), ...

  3. Threejs 官网 - 入门指南(Getting Started)

    Threejs 官网 - 入门指南(Getting Started) 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一 ...

  4. 网页设计作业 仿苏宁易购商城网站设计——仿苏宁易购官网商城(1页) HTML+CSS+JavaScript web网页大作业

    HTML5期末大作业:仿苏宁易购商城网站设计--仿苏宁易购官网商城(1页) HTML+CSS+JavaScript web网页大作业 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电 ...

  5. HTML5期末大作业:网页设计——小米商城官网首页(1页) HTML+CSS+JavaScript web期末作业设计网页_清新淡雅个人网页大学生网页设计作业成品

    HTML5期末大作业:网页设计--小米商城官网首页(1页) HTML+CSS+JavaScript web期末作业设计网页_清新淡雅个人网页大学生网页设计作业成品 常见网页设计作业题材有 个人. 美食 ...

  6. HTML5期末大作业:仿苏宁易购商城网站设计——仿苏宁易购官网商城(1页) HTML+CSS+JavaScript web网页大作业

    HTML5期末大作业:仿苏宁易购商城网站设计--仿苏宁易购官网商城(1页) HTML+CSS+JavaScript web网页大作业 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电 ...

  7. HTML5期末大作业:游戏官网网站设计——神之刃游戏官网网页(6页) HTML+CSS+JavaScript web网页设计与开发

    HTML5期末大作业:游戏官网网站设计--神之刃游戏官网网页(6页) HTML+CSS+JavaScript web网页设计与开发 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电商 ...

  8. html大作业网页代码——神之刃游戏官网网页(6页) HTML+CSS+JavaScript web网页设计与开发

    HTML5期末大作业:游戏官网网站设计--神之刃游戏官网网页(6页) HTML+CSS+JavaScript web网页设计与开发 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电商 ...

  9. 第三百二十五节,web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签...

    第三百二十五节,web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签 标签选择器对象 HtmlXPathSelector()创建标签选择器对象,参数接收response回调的html对象 ...

最新文章

  1. 安装Ruby和Rails运行环境
  2. Android中的自定义view和自定义属性TypedArray的使用
  3. LAMP集群项目四 安装apache、php及其插件
  4. WebSocket入门
  5. 抖音访问太频繁-设备注册分析
  6. MAVEN 傻瓜式快速教程
  7. smtplib 抄送邮件_用Python收发电子邮件
  8. 一种数据结构的封装模式
  9. 高等微積分(高木貞治) 1.4節 例2
  10. AWS CSAA -- 04 AWS Object Storage and CDN - S3 Glacier and CloudFront(二)
  11. 力控组态软件与mysql_力控组态软件实时数据库的原理
  12. [译] APT分析报告:07.拉撒路(Lazarus)使用的两款恶意软件分析
  13. 基于拉格朗日差值算法的BMP图像缩放
  14. android5.0 root工具,ROOT大师:Android 5.0 ROOT并没那么难
  15. 完美解决Win10 X64非原装版系统打不开CHM文件
  16. (纯原创)分解质因数
  17. python数据分析六个环节_安利6个珍藏的Python数据分析神器
  18. #微信公众平台开发(一)
  19. 数据分析 第三讲 matplotlib常用统计图
  20. 计算机90学时培训小结,90学时培训总结

热门文章

  1. android studio导入arr文件
  2. 当前年的日历存储到数据库,用于判断某一天是假期还是工作日
  3. 【Linux系统】第9节 linux系统中用户分类以及用户与组属性的修改示例
  4. 回忆过去,畅想未来--2016下
  5. 程序员快速成长的核心原则
  6. 【最新版】宝塔面板7.9.3企业版 开心破解版一键脚本
  7. Unity - Timeline 之 Muting tracks(屏蔽轨道)
  8. 复旦大学《数学分析》教学大纲,读后有感
  9. linux服务器下搭建svn服务器仓库
  10. IP地址为140.123.0.0的地址是B类地址,若要切割为10个子网,而且都要连接上Internet,请问子网掩码应设为