karol-f / vue-custom-element

Vue Custom Element - Web Components' Custom Elements for Vue.js
https://karol-f.github.io/vue-custom-element/
MIT License
1.97k stars 187 forks source link

Single file component with Props, Setting props #213

Closed stoivo closed 4 years ago

stoivo commented 4 years ago

Hi, Thanks for a very awesome package. I have look at the orifinal official package and it is not neadly as good. Thank you.

I have a Vue component I want to abstract out as a CustomElement for an example I have HelloApp

Single file component of `HelloApp.vue` ```vue ```

Than I import the vue component as a custom element

import Vue from 'vue/dist/vue.esm'

import vueCustomElement from 'vue-custom-element'
Vue.use(vueCustomElement);

import HelloApp from '../hello_awesome.vue'
Vue.customElement('hello-app', (new HelloApp()).$options);

Then in the DOM i put

<hello-app name="Simon"></hello-app>

All this work so far. At this moment I am having warnings

  1. To register the vue component I have to initilize one instance ov the vue Component and it would warn if I had any missing prop which was required. related line Vue.customElement('hello-app', (new HelloApp()).$options);
  2. When I change the prop in the html I get a warning from vue that the Prop should not be changed from the inside but only from the parent component.
    
    [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "name"

found in

---> at app/javascript/hello_awesome.vue

VueJS 14 warn loop reactiveSetter updateChildComponent prepatch patchVnode patch _update updateComponent get run flushSchedulerQueue nextTick flushCallbacks set vue-custom-element.esm.js:281 debugger eval code:1 ``` Line 281 is this.setAttribute... ```js function reactiveProps(element, props) { props.camelCase.forEach(function (name, index) { Object.defineProperty(element, name, { get: function get() { return this.__vue_custom_element__[name]; }, set: function set(value) { if (((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' || typeof value === 'function') && this.__vue_custom_element__) { var propName = props.camelCase[index]; this.__vue_custom_element__[propName] = value; } else { var type = props.types[props.camelCase[index]]; this.setAttribute(props.hyphenate[index], convertAttributeValue(value, type)); } } }); }); } ``` Do you have a suggustion on how to work resolve this two issues?
karol-f commented 4 years ago

Hi, I'm not into TS (yet) but looking at documentation (https://github.com/kaorun343/vue-property-decorator#Prop) and changing prop definition to:

  @Prop({
    type: String,
    default: undefined
  })
  readonly name: string | undefined;

seems to work fine.

https://codesandbox.io/s/vue-custom-element-render-function-with-on-doesnt-work-e8jt3?file=/src/App.vue

stoivo commented 4 years ago

When I change the attribute I get this warning message [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "name". I dont see it in the example app you shared and I wont know why.

karol-f commented 4 years ago

I've changed prop definition according to docs - last part

readonly name: string | undefined;

And it works.

stoivo commented 4 years ago

Any ideas how to get around initilizing a new instance when defining the custom element?

karol-f commented 4 years ago

I didn't test it but it seems that instead of

new App().$options

You can use

App.prototype.constructor.options