不只 Vue3 , 尤大在 github 还更新了这个

共 4432字,需浏览 9分钟

 ·

2020-09-23 10:31


  • 作者:陈大鱼头
  • github:KRISACHAN

前言

近期前端最火的话题莫过于 Vue v3.0.0 release 的发布了。

不过除了 Vue 3 之外,鱼头在尤大的 github 上还发现了悄咪咪上线的DEMO - vue-lit 。

下载下来之后发现还挺有意思的,所以就来跟大家一起分享下。

正文

项目 README.md 里有这么一句话:

Proof of concept mini custom elements framework powered by @vue/reactivity and lit-html.

由  @vue/reactivity 和 lit-html 提供支持的概念性迷你 custom elements (自定义标签)框架。

下载下来之后发现这是尤大一个实验性的玩具DEMO(当然后续会发展得如何,那就看尤大了)。

项目目录如下:


在浏览器打开 example.html ,我们能看到:


然后 DEMO 代码如下(由于代码太长,本文仅展示部分代码):

<my-component>my-component>
<script type="module">
  import {
    defineComponent,
    reactive,
    html,
    onMounted,
    onUpdated,
    onUnmounted
  } from './index.js'

  defineComponent('my-component', () => {
    const state = reactive({
      text'hello',
      showtrue
    })
    const toggle = () => {
      state.show = !state.show
    }
    const onInput = e => {
      state.text = e.target.value
    }

    return () => html`
      <button @click=
${toggle}>toggle childbutton>
      <p>
      
${state.text} <input value=${state.text} @input=${onInput}>
      p>

      ${state.show ? html`<my-child msg=${state.text}>my-child>` : ``}
    `

  })
script>

看到这里就明白了,这是一个让 Web Components 支持类 Vue 语法的小工具。

我们再来看看源码(由于代码太长,本文仅展示除了生命周期以外的核心代码):

import { render } from 'https://unpkg.com/lit-html?module'
import {
  shallowReactive,
  effect
from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'

let currentInstance

import { render } from 'https://unpkg.com/lit-html?module'
import {
  shallowReactive,
  effect
from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'

export function defineComponent(name, propDefs, factory{
  if (typeof propDefs === 'function') {
    factory = propDefs
    propDefs = []
  }

  customElements.define(
    name,
    class extends HTMLElement {
      static get observedAttributes() {
        return propDefs
      }
      constructor() {
        super()
        const props = (this._props = shallowReactive({}))
        currentInstance = this
        const template = factory.call(this, props)
        currentInstance = null
        const root = this.attachShadow({ mode'closed' })
        effect(() => {
          render(template(), root)
        })
      }
    }
  )
}

export * from 'https://unpkg.com/lit-html?module'
export * from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'

这里我们来介绍下这个DEMO所涉及到的五个概念

@vue/reactivity

这是 Vue3 里比较重要的一个模块,它是 Composition API 的核心,用于实现数据响应。

shallowReactive

shallowReactive()  是 Composition API 之一,用于响应数据的第一层,类似于浅拷贝。

调用方式如下:

import {
    shallowReactive,
    isReactive
from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
const props = shallowReactive({ n1 })
console.log(isReactive(props.n)) // false
console.log(isReactive(props)) // true

如上所示,props 才是一个 reactive 对象,而 props.n 不是

effect

effect() 则是一个观察者,调用方法如下:

import {
    effect,
    reactive
from 'https://unpkg.com/@vue/reactivity/dist/reactivity.esm-browser.js'
let dummy
const counter = reactive({ num0 })
effect(() => (dummy = counter.num))
console.log(dummy === 0// true
counter.num = 7
console.log(dummy === 7// true

lit-html

距 官网 介绍,它是一个高效,富有表现力,可扩展性的 HTML 模板。它支持创建跟更新 DOM,也兼容所有的浏览器。

使用方式如下:

import {
    html,
    render
from 'https://unpkg.com/lit-html?module'
let sayHello = (name) => html`<h1>Hello ${name}h1>`
render(sayHello('World'), document.body)
render(sayHello('Everyone'), document.body)

这个时候页面就会渲染出一个

Hello Everyone

,效果如下:


还挺好用,不过网上对其褒贬不一,有兴趣的可以去搜索引擎搜一搜,本文不作展开。

Web Components

至于 Web Components 应该是老生常谈的技术了,简单来说就是原生的组件化技术,简单的例子如下:

<h1><context-span>examplecontext-span>h1>
<script src="./wc.js">script>
// wc.js
class ContextSpan extends HTMLElement {
    constructor() {
      super();

      const style = document.createElement('style');
      const span = document.createElement('span');
      span.textContent = this.textContent;

      const shadowRoot = this.attachShadow({mode'open'});
      shadowRoot.appendChild(style);
      shadowRoot.appendChild(span);

      style.textContent = `
        span:hover { text-decoration: underline; }
        :host-context(h1) { font-style: italic; }
        :host-context(h1):after { content: " - 我是一个H1" }
        :host { background: rgba(0,0,0,0.1); padding: 2px 5px; }
      `
;
    }
}
customElements.define('context-span', ContextSpan);

效果如下:


vue-lit

我们回到 vue-lit 来,vue-lit 有可能只是尤大一时兴起的玩具,但是也有可能是 vue 结合 原生组件的第一步。

VueReact 此类前端框架出来不久之后,Web Components 就应运而生,虽然直到如今地位还不能跟这些前端框架相比,但是 Web Components 始终是浏览器的一大发展,极有可能就取代众多前端框架成为新的开发模式,毕竟当年 JQuery 大火之后,浏览器也出了许许多多模拟它 API 的原生函数。

所以看到这个工具,鱼头也是非常激动,虽然不确定后续会如何发展,但是对于在 Web Components 里使用 Vue 的这种模式,还是非常期待的。

后记

如果你喜欢探讨技术,或者对本文有任何的意见或建议,非常欢迎加鱼头微信好友一起探讨,当然,鱼头也非常希望能跟你一起聊生活,聊爱好,谈天说地。鱼头的微信号是:krisChans95 也可以扫码关注公众号,订阅更多精彩内容。

浏览 45
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报