** Declare : Without permission , Do not reprint .** Web Components It's been a long time , So you may have heard of , I even learned , I understand very well . But it doesn't matter , You can go over it again , Learn from the past . ## Browser native ability more and more strong . ### js Once upon a time `JQuery`, It's a must learn skill for front-end beginners , It is a necessary library for front-end projects . Its strength lies in its simplification `dom operation `( Powerful selector ) and `ajax`( asynchronous ) operation . Now native api `querySelector()`、`querySelectorAll()`、`classList` The emergence of etc. has been greatly weakened dom operation , `fetch`、 Based on `promise` Of `axios` Has completely replaced `ajax`, Even better ,`async-await` It's really easy to use . [You-Dont-Need-jQuery](https://github.com/nefe/You-Dont-Need-jQuery/blob/master/README.zh-CN.md#css--style) ### css css Preprocessor ( Such as `scss`、`less`) It's project engineering css The best choice for . Its strength is support ** Variables **、** The style is regular and nest like **、** Function **. Now css Variables are already supported `(--var)` 了 , Patterns, rules, nests are also planned , Function `calc()` It's also very powerful , And support `attr()` Use , And `css-module` Modularity . [ No precompiling ,CSS It's time to write the nest directly ](https://github.com/75team/w3c/blob/master/articles/20180712_anjia_%E4%B8%8D%E7%94%A8%E9%A2%84%E7%BC%96%E8%AF%91%EF%BC%8CCSS%E7%9B%B4%E6%8E%A5%E5%86%99%E5%B5%8C%E5%A5%97%E7%9A%84%E6%97%A5%E5%AD%90%E5%B0%B1%E8%A6%81%E5%88%B0%E4%BA%86.md) [w3c The style is regular and nest like css-nesting-module](https://drafts.csswg.org/css-nesting/) It used to be cool and complicated css Style and animation , Must be aided by css Preprocessor variables 、 Function or js Talent , Now use (`css-doodle`)[https://css-doodle.com/] Technology , It's cooler to achieve 、 More dazzling . [css-doodle sample reels ](https://codepen.io/yuanchuan/collections/popular/) ### web components Componentization `Web Components` You can build reusable components , One day in the future, abandon what we call frameworks and libraries , Use native directly API Or use based on Web Components Standard framework and Library Development , Do you think it's possible ? I think it's possible . #### vue-lit [vue-lit](https://github.com/yyx990803/vue-lit), Described below : > Proof of concept mini custom elements framework powered by @vue/reactivity and lit-html. The description uses custom elements, And the browser console elements Of DOM The structure also contains shadow-root. and custom element and shadow DOM yes web components An important part of . See below for details demo, Explain : Examples of this document , Can be directly complicated to a html Of documents body in , Then turn on the preview directly in the browser . ```html
```
[ Original code interpretation ](https://github.com/yyx990803/vue-lit/blob/master/index.js) ```js // lit-html Templates , Provide html Templates ( Simple js Expression and event binding )、render Rendering capabilities import { render } from 'https://unpkg.com/lit-html?module' // reactivity yes vue3.0 At the heart of ,shallowReactive Shallow response ,effect It can be understood as watch, Provide attribute response and partial lifecycle processing import { shallowReactive, effect } from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js' let currentInstance export function defineComponent(name, propDefs, factory) { if (typeof propDefs === 'function') { factory = propDefs propDefs = [] } // Custom elements custom element, Native API customElements.define( name, class extends HTMLElement { // Set the properties you want to listen to static get observedAttributes() { return propDefs } constructor() { super() // Attribute access vue In response to const props = (this._props = shallowReactive({})) currentInstance = this // lit-html Of html Generated templates const template = factory.call(this, props) currentInstance = null // bm onBeforeMount this._bm && this._bm.forEach((cb) => cb()) // shadowRoot,closed You can't go directly through js Get the defined customElement operation shadowRoot const root = this.attachShadow({ mode: 'closed' }) let isMounted = false effect(() => { if (isMounted) { // _bu, onBeforeUpdate this._bu && this._bu.forEach((cb) => cb()) } // Will template Mount the content to shadowRoot On render(template(), root) if (isMounted) { // _u,onUpdated this._u && this._u.forEach((cb) => cb()) } else { isMounted = true } }) } // Mount to for the first time dom Call back later ,onMounted connectedCallback() { this._m && this._m.forEach((cb) => cb()) } // Uninstall , onUnmounted disconnectedCallback() { this._um && this._um.forEach((cb) => cb()) } // Attribute listening attributeChangedCallback(name, oldValue, newValue) { this._props[name] = newValue } } ) } function createLifecycleMethod(name) { return (cb) => { if (currentInstance) { ;(currentInstance[name] || (currentInstance[name] = [])).push(cb) } } } export const onBeforeMount = createLifecycleMethod('_bm') export const onMounted = createLifecycleMethod('_m') export const onBeforeUpdate = createLifecycleMethod('_bu') export const onUpdated = createLifecycleMethod('_u') export const onUnmounted = createLifecycleMethod('_um') export * from 'https://unpkg.com/lit-html?module' export * from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js' ``` [shallowReactive Source code ](https://github.com/vuejs/vue-next/blob/master/packages/reactivity/src/reactive.ts), Function annotations have made it clear ,only the root level properties are reactive. The object only responds to the root attribute , In other words , Shallow response , It's similar to a shallow copy . ```js /** * Return a shallowly-reactive copy of the original object, where only the root * level properties are reactive. It also does not auto-unwrap refs (even at the * root level). */ export function shallowReactive
(target: T): T { return createReactiveObject( target, false, shallowReactiveHandlers, shallowCollectionHandlers ) } ``` [effect Source code ](https://github.com/vuejs/vue-next/blob/master/packages/reactivity/src/effect.ts), You can see roughly that there is dep Rely on , And oldValue、newValue Deal with . Through analysis ,vue-lit It's supposed to be vue3.0 And web components An attempt to do . use `lit-html` The reason is that the support template support is simple js Expression and event binding ( Native template At present, only slot slot ) #### css-doodle Actually , What I mentioned earlier css-doodle It's also a web component. It's a browser native support . Example :[ Art background ](https://codepen.io/yuanchuan/pen/YRvMwK). ```
:doodle { @grid: 1x300 / 100vw 40vmin; overflow: hidden; background: linear-gradient(rgba(63, 81, 181, .11), #673AB7); } align-self: flex-end; --h: @r(10, 80, .1); @random(.1) { --h: @r(85, 102, .1) } @size: 1px calc(var(--h) * 1%); background: linear-gradient(transparent, rgba(255, 255, 255, .4), transparent); background-size: .5px 100%; transform-origin: center 100%; transform: translate(@r(-2vmin, 2vmin, .01), 10%) rotate(@r(-2deg, 2deg, .01)); :after { content: ''; position: absolute; top: 0; @size: calc(2px * var(--h)); transform: translateY(-50%) scale(.14); background: radial-gradient(@p(#ff03929e, #673ab752, #fffa) @r(40%), transparent 50%) 50% 50% / @r(100%) @lr() no-repeat; }
``` dom Structure :
#### input、select And so on html Elements input、select It's also web component. But it's built-in , Default can't see shadowRoot Structure , Need to open browser console settings , Tick `Show user agent shadow DOM`, In the console `elements` We can see its structure in . Set
dom Structure
## web components Componentization by 3 Part of it . - **Custom elements( Custom elements )**: A set of JavaScript API, Allows you to define custom elements And their behavior , You can then use them as needed in your user interface . - **Shadow DOM( shadow DOM)**: A set of JavaScript API, Used to encapsulate “ shadow ”DOM Trees are attached to elements ( With the master file DOM Present separately ) And control its associated functions . In this way , You can keep the functionality of the element private , So they can be scripted and stylized , And don't worry about conflict with the rest of the file . - **HTML templates(HTML Templates )**: `
` and `
` Element allows you to write markup templates that are not displayed in the rendering page . Then they can be reused many times as the basis for a custom element structure . ### Custom elements Users can use `customElements.define` Customize html Elements . ``` customElements.define(elementName, class[, extendElement]); ``` - elementName: The name cannot be a single word , You have to use ** Short horizontal line ** Separate . - class: A class used to define the behavior of an element , Including the life cycle . - extendElement: Optional arguments , One contains `extends` Property configuration object , Specifies which built-in HTML Elements By definition , There are two kinds of custom element: - Autonomous custom elements: Independent elements , Don't inherit built-in HTML Elements . and html Elements are used as well , for example `
` - Customized built-in elements: Inherit the built-in HTML Elements . Write the built-in first html Element notes , Through **is** Properties specify custom element Name , for example `
` And the life cycle : - connectedCallback: When custom element First inserted file DOM When , Being called . - disconnectedCallback: When custom element From the file DOM When deleted from the , Being called . - adoptedCallback: When custom element When moved to a new file , Being called . - attributeChangedCallback: When custom element increase 、 Delete 、 When modifying its own properties , Being called . Example : Independent elements . ```html
``` Example : Inherited elements ```html
``` more , Please refer to :[Custom elements](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_custom_elements) ### Shadow DOM Web components The important function of is encapsulation —— The tag structure can be 、 Style and behavior are hidden , And isolated from other code on the page , Make sure the different parts don't mix together , Make your code cleaner 、 Neat .Shadow DOM The interface is the key , It can take a hidden 、 Independent DOM Attach to an element . Which element to attach to , And definitions custom element When it comes to , If it's an independent element , Attach to document body On ; If it's an inherited element , It is attached to the inherited element .
It can be as common as the operation DOM The same thing , utilize API operation Shoadow DOM. ```js let shadow = elementRef.attachShadow({mode: 'open'}); let shadow = elementRef.attachShadow({mode: 'closed'}); ``` `open` It means that you can use the JavaScript Method to get Shadow DOM, Such as 'document.querySelector('custom-info').shadowRoot'. conversely , Can't get . more , Please refer to :[Shadow DOM](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM) ### HTML templates template and slot Elements can create very flexible shadow DOM Templates , To fill custom element. For repeated use html Structure , It can simplify things , It's very meaningful . Example ```html
template info
default text
``` more , Please refer to :[HTML templates and slots](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_templates_and_slots) ## web components Example [web component todolist](https://wc-todo.firebaseapp.com/native/)
[ Other libraries todolist parade ](https://wc-todo.firebaseapp.com/)
Look at the picture , The result is self-evident . ## Summary Browser native capabilities are becoming very powerful .web component It's worth a hug . Although template It's not perfect ( Expressions are not supported ), But it's just a black spot on the whiteboard . Refer to : 1. [ Especially large 3 It was sent on GitHub Upper vue-lit What is it ?](https://github.com/axuebin/articles/issues/41) 2. [Web Components](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components) 3. [web-components-todo](https://github.com/shprink/web-component