快乐的时光都是这么短暂,转眼间,web原生组件的知识点已经学完了,这个虽然暂时不一定有用,但是随着时间的积累,一步一个脚印的积累,你会有相应的收获,希望能变得更强,比如两年前我也会想有现成的东西不用,干嘛要自己写呢?但是你确定一直用上层的东西,你的收获有自己写快吗? 在开发的过程过能节约下来的时间,我们可以用这个时间拿来学习,这样随着时间的积累我们会变得更强,也会慢慢有更多的时间投入生活,进行正向循环

css问题

自定义元素然后是普通的HTML元素,也可以使用css设置样式

在我们没有设置shadow DOM的组件,进行全局样式设置

  1. <app-element></app-element>
  2. <style>
  3. /* CSS Global */
  4. app-element {
  5. display: inline-block;
  6. padding: 6px 20px;
  7. background: steelblue;
  8. color: white;
  9. }
  10. app-element span {
  11. font-weight: bold;
  12. vertical-align: super;
  13. font-size: small;
  14. color: gold;
  15. }
  16. </style>
  17. <script>
  18. customElements.define("app-element", class extends HTMLElement {
  19. connectedCallback() {
  20. this.innerHTML = `<div class="element">AppElement <span>New!</span></div>`;
  21. }
  22. });
  23. </script>
  • 无论文档是否具有Shadow DOM,都可以从文档的全局CSS从组件外部)对组件本身进行样式设置。
  • 只要没有Shadow DOM可以“保护”组件,就可以对组件中的元素进行全局样式设置

HTML 外部引入

  1. <app-element></app-element>
  2. <script>
  3. customElements.define("app-element", class extends HTMLElement {
  4. connectedCallback() {
  5. this.innerHTML = `
  6. <link rel="stylesheet" href="/components/AppElement.css">
  7. <style>
  8. @import "/components/AppElement.css";
  9. </style>
  10. <div class="element">
  11. AppElement <span>New!</span>
  12. </div>
  13. `;
  14. }
  15. });
  16. </script>

程序化动态的方法

  1. <app-element></app-element>
  2. <script>
  3. import css from "./AppElement.css";
  4. customElements.define("app-element", class extends HTMLElement {
  5. connectedCallback() {
  6. document.adoptedStyleSheets = [...document.adoptedStyleSheets, css];
  7. this.innerHTML = `
  8. <div class="element">
  9. AppElement <span>New!</span>
  10. </div>
  11. `;
  12. }
  13. });
  14. </script>
  1. this.shadowRoot.adoptedStyleSheets = [...document.adoptedStyleSheets, css];

我们通过import 加载css,在这种情况下,它是组件的相对路径,在加载css内容中并生成一个对象cssStyleSheet ,然后通过.adoptedStyleSheets 导入css

这种方法直接使用是错误的,需要引入插件css-loader,应该要借助webpack ,原生不能直接使用

import css from "./AppElement.css"

css自定义属性

  1. var(--color,red)
  2. // 第一个变量不存在,用第二个

全局设置,穿透到里面

  1. <app-element></app-element>
  2. <app-element></app-element>
  3. <app-element></app-element>
  4. <style>
  5. /* CSS Global */
  6. app-element:first-of-type {
  7. --color: orangered;
  8. }
  9. </style>
  10. <script>
  11. customElements.define("app-element", class extends HTMLElement {
  12. connectedCallback() {
  13. this.innerHTML = `
  14. <style>
  15. /* CSS Local */
  16. .element {
  17. display: inline-block;
  18. padding: 6px 20px;
  19. background: var(--color, steelblue);
  20. color: white;
  21. }
  22. span {
  23. font-weight: bold;
  24. vertical-align: super;
  25. font-size: small;
  26. color: gold;
  27. }
  28. </style>
  29. <div class="element">
  30. AppElement <span>New!</span>
  31. </div>
  32. `;
  33. }
  34. });
  35. </script>

css 作用域

css 伪类,仅在定义了shadow DOM 有效

伪类 描述
:host 它允许我们设置自定义元素(组件自己的容器)的样式。
:host(``css) 同上一个,但前提是它与中定义的选择器匹配css
:host-context(``css) 同上,但前提是您有与选择器匹配的父母css
  1. <app-element></app-element>
  2. <app-element disabled></app-element>
  3. <div class="box">
  4. <app-element></app-element>
  5. </div>
  6. <script>
  7. customElements.define("app-element", class extends HTMLElement {
  8. constructor() {
  9. super();
  10. this.attachShadow({ mode: "open" });
  11. }
  12. connectedCallback() {
  13. this.shadowRoot.innerHTML = `
  14. <style>
  15. :host {
  16. display: inline-block;
  17. padding: 6px 20px;
  18. background: steelblue;
  19. color: white;
  20. }
  21. :host([disabled]) {
  22. background: #aaa;
  23. }
  24. :host-context(.box) {
  25. background: red;
  26. }
  27. span {
  28. font-weight: bold;
  29. vertical-align: super;
  30. font-size: small;
  31. color: gold;
  32. }
  33. </style>
  34. <div class="element">
  35. AppElement <span>New!</span>
  36. </div>
  37. `;
  38. }
  39. });
  40. </script>

修改最外层的盒子的css

影子DOM操作事件

  1. <app-element></app-element>
  2. <script>
  3. customElements.define("app-element", class AppElement extends HTMLElement {
  4. constructor() {
  5. super();
  6. this.attachShadow({ mode: "open" });
  7. }
  8. sendMessage() {
  9. alert("Hello!");
  10. }
  11. connectedCallback() {
  12. this.shadowRoot.innerHTML = "<button>点我!</button>";
  13. this.button = this.shadowRoot.querySelector("button");
  14. this.button.addEventListener("click", () => this.sendMessage());
  15. }
  16. // 离开页面删除事件
  17. disconnectedCallback() {
  18. this.button.removeEventListener("click", () => this.sendMessage());
  19. }
  20. });
  21. </script>

第二种方法

不用addEventListener

  1. this.button.onclick=()=>this.sendMessage()
  2. // 离开页面删除事件
  3. disconnectedCallback() {
  4. this.button.onclick=null;
  5. }

第三种方法

神奇的handleEvent函数

  1. <app-element></app-element>
  2. <script>
  3. customElements.define("app-element", class extends HTMLElement {
  4. constructor() {
  5. super();
  6. this.attachShadow({ mode: "open" });
  7. }
  8. handleEvent(event) {
  9. if (event.type === "click"){
  10. console.log(3)
  11. }
  12. }
  13. connectedCallback() {
  14. this.shadowRoot.innerHTML = "<button> Press me!</button>";
  15. this.button = this.shadowRoot.querySelector("button");
  16. this.button.addEventListener("click", this);
  17. }
  18. disconnectedCallback() {
  19. this.button.removeEvenetListener("click", this);
  20. }
  21. });
  22. </script>

我们发现当我们简单的放置this 浏览器会奇特找到.handleEvent函数,存在就进行处理,这种方法我们可以通过检测event.type,我们可以通过这种方法进行集中处理

自定义事件

选择项 描述
detail 包含我们要传输的所有信息的对象。
bubbles 指示该事件是否应气泡在DOM“到表面”或没有。
composed 指示传播是否可以遍历Shadow DOM
cancelable 指示是否可以使用取消行为.preventDefault()

事件传递冒泡

  1. <div class="box1">
  2. <div class="box2"></div>
  3. </div>
  4. <script>
  5. let box2 = document.querySelector('.box2');
  6. let box1 = document.querySelector('.box1');
  7. box2.addEventListener('click',()=>{
  8. box2.dispatchEvent(
  9. new CustomEvent('messages', {
  10. detail: {
  11. message: 'hello'
  12. },
  13. bubbles:true,
  14. })
  15. )
  16. })
  17. box1.addEventListener('messages',(e)=>{
  18. console.log(333);
  19. console.log(e.detail);
  20. })
  21. </script>

bubbles=true 通过冒泡传递给父级,event.target 拿到dom元素,event.detail 拿到创建事件的数据

默认情况下

  1. <div class="box1">
  2. <div class="box2">
  3. <div class="box3"></div>
  4. </div>
  5. </div>
  6. <script>
  7. let box1 = document.querySelector('.box1');
  8. let box2 = document.querySelector('.box2');
  9. let box3 = document.querySelector('.box3');
  10. box3.addEventListener('click',()=>{
  11. console.log(1);
  12. box3.dispatchEvent(
  13. new CustomEvent('messages', {
  14. detail: {
  15. message: 'hello'
  16. },
  17. bubbles:true,
  18. })
  19. )
  20. })
  21. box2.addEventListener('click',()=>{
  22. console.log(2);
  23. })
  24. box1.addEventListener('click',()=>{
  25. console.log(3);
  26. })
  27. </script>

我们发现默认情况下冒泡是从里到外1,2,3

当我们在最外层添加

  1. box3.addEventListener("messages", (event) => {
  2. console.log(4);
  3. },{capture:true});

我们发现执行的顺序为1,4,2,3

跨组件的通信

组件1发送数据

  1. <first-element></first-element>
  2. customElements.define("first-element", class extends HTMLElement {
  3. constructor() {
  4. super();
  5. this.attachShadow({ mode: "open" });
  6. }
  7. handleEvent(event) {
  8. if (event.type === "click") {
  9. const MessageEvent = new CustomEvent("messages", {
  10. detail: {from: "Manz", message: ++this.i},
  11. bubbles: true,
  12. composed: true // 影子
  13. });
  14. this.dispatchEvent(MessageEvent);
  15. }
  16. }
  17. connectedCallback() {
  18. this.shadowRoot.innerHTML = `<button>点我</button>`;
  19. this.shadowRoot.querySelector("button").addEventListener("click", this);
  20. }
  21. });

接受传递来的数据

  1. customElements.define("second-element", class extends HTMLElement {
  2. constructor() {
  3. super();
  4. this.attachShadow({mode: "open"});
  5. }
  6. handleEvent(event) {
  7. if (event.type === "messages") {
  8. event.detail.from = "Robot";
  9. const data = event.detail;
  10. this.shadowRoot.innerHTML = `
  11. <div>
  12. From ${data.from}:
  13. <span style="color:red">${data.message}</span>
  14. </div>
  15. `;
  16. }
  17. }
  18. connectedCallback() {
  19. this.shadowRoot.innerHTML = `<div>No messages</button>`;
  20. document.addEventListener("messages", this);
  21. }
  22. });

这样想不想两个异步组件之间的通信

从原生web组件到框架组件源码(三)的更多相关文章

  1. Web前端三大框架_vue源码笔记

    一.VUE 1.1 MVVM VUE也是基于MVVM模式实现的.特点就是数据双向绑定 在MVVM模式中,分成三个部分: M 模型 model V 视图 view VM 视图-模型 view-model ...

  2. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

  3. robotlegs2.0框架实例源码带注释

    robotlegs2.0框架实例源码带注释 Robotlegs2的Starling扩展 有个老外写了robotleges2的starling扩展,地址是 https://github.com/brea ...

  4. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  5. JUC同步器框架AbstractQueuedSynchronizer源码图文分析

    JUC同步器框架AbstractQueuedSynchronizer源码图文分析 前提 Doug Lea大神在编写JUC(java.util.concurrent)包的时候引入了java.util.c ...

  6. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(2)-easyui构建前端页面框架[附源码]

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(2)-easyui构建前端页面框架[附源码] 开始,我们有了一系列的解决方案,我们将动手搭建新系统吧. 用 ...

  7. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  8. WEB前端开发学习:源码canvas 雪

    WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...

  9. 如何查看JDK以及JAVA框架的源码

    如何查看JDK以及JAVA框架的源码 设置步骤如下: 1.点 “window”-> "Preferences" -> "Java" -> &q ...

  10. 高性能网络I/O框架-netmap源码分析

    from:http://blog.chinaunix.net/uid-23629988-id-3594118.html 博主这篇文章写的很好 感觉很有借签意义 值得阅读 高性能网络I/O框架-netm ...

随机推荐

  1. python_购物车

    流程图  实现方式 #!/usr/bin/python3 __author__ = 'beimenchuixue' __blog__ = 'http://www.cnblogs.com/2bjiuji ...

  2. Python numpy总结(3)——常用函数用法

    1,np.ceil(x, y) 限制元素范围,进一法,即向上取整. x 表示输入的数据  y float类型 表示每个元素的上限. a = np.array([-1.7, -1.5, -0.2, 0. ...

  3. 【原创】xenomai内核解析--实时IPC概述

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 1.概述 2.Real-time IPC 2. ...

  4. java泛型之通配符?

    一.在说泛型通配符" ?" 之前先讲几个概念 1.里氏替换原则(Liskov Substitution Principle, LSP): 定义:所有引用基类(父类)的地方必须能透明 ...

  5. 烽火服务器IPMI远程装机

    连接控制台 一.通过vpn拨入进入内网,使用IE浏览器或者火狐等等,连接ilo地址.(需要安装java8.0,各个品牌的服务器需要的不一样) 二.启动虚拟连接控制台,进行控制主机 三.根据截图进行操作 ...

  6. 正睿十一A班模拟赛day1

    估分:25+0+60=85 实际:25+0+60=85 T1: 就只会25的暴力 分治,到一个区间[l,r],cnt[i]表示i这个颜色在区间内的出现次数,从两头同时扫描,扫描到第一个cnt[i]小于 ...

  7. STM32之旅5——IWDG

    STM32之旅5--IWDG stm32有两个看门狗,一个独立看门狗(IWDG).一个窗口看门狗(WWDG):独立看门狗是时钟源是内部的40kHz的低速时钟,即使主频出问题了,独立看门狗也不会受到影响 ...

  8. [WC 2011]最大Xor和路径

    题目大意: 给你一张n个点,m条边的无向图,每条边都有一个权值,求:1到n的路径权值和的最大值. 题解: 任意一条路径都能够由一条简单路径(任意一条),在接上若干个环构成(如果不与这条简单路径相连就走 ...

  9. 利用 Python 插入 Oracle 数据

    # coding=utf-8 ''''' Created on 2020-01-05 @author: Mr. Zheng ''' import json; import urllib2 import ...

  10. MeteoInfoLab脚本示例:FY-2C 云分类HDF数据

    脚本程序: #Add data file fn = 'D:/Temp/hdf/FY2C_CLC_MLT_NOM_20070730_1800.hdf' f = addfile(fn) #Get data ...