在使用Vue js时,Webcomponents每次都要重新初始化。

问题描述 投票:0回答:1

我已经为一个通用输入框创建了一个webcomponent,我需要在多个项目中使用,设计功能保持不变,只是我必须在每个项目中使用切换主题,所以我决定继续使用webcomponents,其中一个项目是基于Vue Js的,在Vue js中,DOM内容在每次更新时都会重新渲染以实现反应性。在Vue js中,当每次更新时,DOM内容都会被重新渲染,以实现反应性,Vue模板的重新渲染会重新初始化我的自定义webcomponent,这将导致失去所有我使用setter分配给组件的配置。

  • 将数据作为属性传递
  • 基于事件的配置传递。
  • 使用Vue-directives。
  • 使用v-show代替v-if

    -- 以上三种解决方案并不真正符合我所要创建的东西,我已经在jsfiddle中创建了一个示例项目来显示我的问题。

我已经在jsfiddle中创建了一个示例项目来显示我的问题。每次我取消选中和选中复选框时,我的组件都会创建新的实例,这导致我选择的主题丢失。(请检查他的活动框计数)对于这个特殊的例子,我希望蓝色的主题被显示。

JSFiddle直接链接

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>
javascript vue.js vue-component web-component custom-element
1个回答
1
投票
<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中删除整个DIV。

所以 <search-bar> 每次点击复选框时,也会添加或删除。

如果你想要一个国家的 <search-bar> 你必须把它保存在某个地方 外面<search-bar> 组件。

或更改您的复选框代码,不使用 v-if 不过 隐蔽<div> 用任何CSS。

  • display: none
  • 可见度:隐藏
  • 不透明度: 0
  • 移动到屏幕外的位置
  • 高度: 0
  • ...

或...

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

您可以轻松地 拨动 风格化 <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属性 以使其与shadowDOM元素结合使用。

我更喜欢原生的而不是框架。<style v-if='visible'/> 将工作......通过粗暴地删除添加样式表。


相关的SO答案。WCMAIN WCPROPS


© www.soinside.com 2019 - 2024. All rights reserved.