Coder Social home page Coder Social logo

ShadowDom Support about css-render HOT 7 CLOSED

07akioni avatar 07akioni commented on May 4, 2024
ShadowDom Support

from css-render.

Comments (7)

07akioni avatar 07akioni commented on May 4, 2024 1

Current vue has some limitations. I can't access shadowRoot easily from the component. I think we may raise a feature request for vue. Then we can use the following method to reuse generated style.

https://jsbin.com/mafiyidave/3/edit?html,console,output

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <script src="https://unpkg.com/vue"></script>
  <script>
    const style = '.foo { color: red; }'
    let styleUrl = ''
    let styleGenerated = false
    
    const _El = Vue.defineCustomElement({
      setup () {
        const self = Vue.getCurrentInstance()
        Vue.onBeforeMount(() => {
          const linkEl = document.createElement('link')
          linkEl.rel = 'stylesheet'
          if (!styleGenerated) {
            console.log('generate style')
            styleUrl = URL.createObjectURL(new Blob([style]))
            linkEl.href = styleUrl
            styleGenerated = true
          } else {
            console.log('reuse style style')
            linkEl.href = styleUrl
          }
          self.shadowRoot.appendChild(linkEl)
        })
      },
      render () {
        return Vue.h('div', { class: 'foo' }, 'custom element')
      }
    })
    // Hack into Vue
    class El extends _El {
      constructor(...args) {
        super(...args)
        this.VueElement = Object.getPrototypeOf(Object.getPrototypeOf(this))
      }
      connectedCallback() {
        this.VueElement.connectedCallback.apply(this)
      }
      _createVNode() {
        const vnode = this.VueElement._createVNode.apply(this)
        if (!this._instance) {
          const ce = vnode.ce
          vnode.ce = instance => {
            instance.shadowRoot = this.shadowRoot
            return ce(instance)
          }
        } 
        return vnode
      }
    }
    customElements.define('custom-el', El)
  </script>
  <custom-el></custom-el>
  <custom-el></custom-el>
  <custom-el></custom-el>
</body>
</html>

from css-render.

07akioni avatar 07akioni commented on May 4, 2024

I think we may provide a style mount hook in css-render. (props: { id: string, style: string }) => void. Then user can mount the style following their intention.

However I'm not very sure how it's going to be like exactly since I'm not familiar with shadow dom (for example why is the style, how many times it's mounted, how to check if some style is already mounted).

The key points are:

  1. Make sure style applied
  2. Do not generate style multiple times if it's already mounted (by id)

from css-render.

NiewView avatar NiewView commented on May 4, 2024

The shadow dom is mounted once, when the custom element is initiated.
The shadow dom is more or a less a additional document within an HTML-Element, by this it isolates all the styles in both directions (outside styles are not applied in the shadow dom and the other way around.) This also means one webpage can have x shadow-doms.

Because of this and your second point I don't think it is enough to provide a style mount hook. Then css-render would have no way to check, if styles are already mounted. Except the plan would be, to just always call the hook and leave it to the logic within it, to check if the styles are already mounted.

from css-render.

07akioni avatar 07akioni commented on May 4, 2024

The shadow dom is mounted once, when the custom element is initiated. The shadow dom is more or a less a additional document within an HTML-Element, by this it isolates all the styles in both directions (outside styles are not applied in the shadow dom and the other way around.) This also means one webpage can have x shadow-doms.

Because of this and your second point I don't think it is enough to provide a style mount hook. Then css-render would have no way to check, if styles are already mounted. Except the plan would be, to just always call the hook and leave it to the logic within it, to check if the styles are already mounted.

I wonder if style created in a component instance can be reused in another component instance?

For example:

<custom-button />
<custom-button />

Can these 2 buttons share same style (with only 1 time style generation)

from css-render.

NiewView avatar NiewView commented on May 4, 2024

I'm not sure, if I understand you correctly.
When I build a vue app as custom element the stlyes will only be applied within the custom element, so it would look something like this

<custom-button>
  # shadow-root
    <styles>/* styles from css-render */</styles>
    <button></button>
  #end shadow-root
</custom-button>
<custom-button>
  # shadow-root
    <styles>/* styles from css-render */</styles>
    <button></button>
  #end shadow-root
</custom-button>

It is ensured, that the implementation for both custom-button is the same, because you can only register a custom-element once. But the styles need to be added within each shadow-dom separate.

If you were only talking about the generation part within css-render, I think it could be theoretically possible to share the logic.
But I don't think it is a good idea, because by default the components don't know from each other and they also should be separated. There is even a shadow-dom mode, which explicitly prohibits any js mutation within a DOM from externally.

If you attach a shadow root to a custom element with mode: closed set, you won't be able to access the shadow DOM from the outside — myCustomElem.shadowRoot returns null. link

That's why I would recommend generating the styles for each element individually and not breaking the border between them.

from css-render.

07akioni avatar 07akioni commented on May 4, 2024

At least there's not much JS runtime expense. If possible I think it's better to benchmark normal way & style reuse way.

from css-render.

07akioni avatar 07akioni commented on May 4, 2024

ref vuejs/core#6113

from css-render.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.