每次使用 Vue js 时,Webcomponents 都会重新初始化

Webcomponents is re-initializing every time while working with Vue js

我已经为我在多个项目中需要的通用输入框创建了一个 web 组件。 设计功能保持不变只是我必须在每个 projects.so 上使用切换主题 我决定继续 webcomponents.One 项目基于 Vue Js.In Vue js DOM 内容在每次更新时重新呈现以启用反应性。 vue 模板的重新渲染正在重新初始化我的自定义 web 组件,这将导致我使用 setters 分配给该组件的所有配置丢失。 我知道以下解决方案。但我想使用 setter 方法。

我在 jsfiddle 中创建了一个示例项目来显示我的问题。 每次我取消选中并选中我的组件的新实例时,都会创建该复选框。这导致失去我选择的主题。 (请检查他活跃的盒子数量) 对于这个特定示例,我希望显示蓝色主题。但它一直变成红色

JSFiddle direct Link

class InputBox extends HTMLElement {
    constructor() {
        super();
        window.activeBoxes ? window.activeBoxes++ : window.activeBoxes = 1;
        var shadow = this.attachShadow({
            mode: 'open'
        });
        var template = `
         <style>
           .blue#iElem {
             background: #00f !important;
             color: #fff !important;
            }
      .green#iElem {
             background: #0f0 !important;
             color: #f00 !important;
            }
            #iElem {
                background: #f00;
                padding: 13px;
                border-radius: 10px;
                color: yellow;
                border: 0;
                outline: 0;
                box-shadow: 0px 0px 14px -3px #000;
              
            }
          </style>
         <input id="iElem" autocomplete="off" autocorrect="off" spellcheck="false" type="text" />
        `;
        shadow.innerHTML = template;
        this._theme = 'red';
        
        this.changeTheme = function(){
         this.shadowRoot.querySelector('#iElem').className = '';
       this.shadowRoot.querySelector('#iElem').classList.add(this._theme);
        }
        
    }
    connectedCallback() {
     this.changeTheme();
    }
    set theme(val){
     this._theme = val;
      this.changeTheme();
  }
}
window.customElements.define('search-bar', InputBox);
<!DOCTYPE html>
<html>
  <head>
    <title>Wrapper Component</title>
    <script src="https://unpkg.com/vue"></script>
    <style>
      html,
      body {
        font: 13px/18px sans-serif;
      }
      select {
        min-width: 300px;
      }
      search-bar {
        top: 100px;
        position: absolute;
        left: 300px;
      }
      input {
        min-width: 20px;
        padding: 25px;
        top: 100px;
        position: absolute;
      }
    </style>
  </head>
  <body>
    <div id="el"></div>

    <!-- using string template here to work around HTML <option> placement restriction -->
    <script type="text/x-template" id="demo-template">
      <div>
       
       <div class='parent' contentEditable='true' v-if='visible'>
          <search-bar ref='iBox'></search-bar>
        </div>
        <input type='checkbox' v-model='visible'>
      </div>
    </script>

    <script type="text/x-template" id="select2-template">
      <select>
        <slot></slot>
      </select>
    </script>

    <script>
      var vm = new Vue({
        el: "#el",
        template: "#demo-template",
        data: {
          visible: true,
        },
        mounted(){
          let self = this
            setTimeout(()=>{
              self.$refs.iBox.theme = 'blue';
            } , 0)
        }        
      });
    </script>
  </body>
</html>

<div class='parent' contentEditable='true' v-if='visible'>
     <search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>

Vue 的 v-if 将从 DOM

add/remove 整个 DIV

所以 <search-bar> 也是 added/removed 在每个复选框点击时

如果您想要 <search-bar> 的状态,您必须将其保存在 外部 <search-bar> 组件的某个位置:

或者更改您的复选框代码以不使用 v-if 隐藏 <div> 与任何 CSS:

  • 显示:none
  • 可见性:隐藏
  • 不透明度:0
  • 移动到屏幕外位置
  • 身高:0
  • ...

and/or...

使用样式表管理多个屏幕元素

您可以使用 <style> 元素轻松 切换 样式:

<style id="SearchBox" onload="this.disabled=true">
 ... lots of CSS
 ... even more CSS
 ... and more CSS
</style>

onload 事件确保 <style> 应用于页面加载。

  • 激活所有 CSS 样式:
    (this.shadowRoot || document).getElementById("SearchBox").disabled = false

  • 删除所有 CSS 样式:
    (this.shadowRoot || document).getElementById("SearchBox").disabled = true

你确实需要 CSS Properties 才能与阴影DOM 元素结合使用。

与框架相比,我更喜欢原生。 <style v-if='visible'/> 将工作.. 通过粗暴地 removing/adding 样式表。