Hola, quiero envolver el contenido de un componente con alguna etiqueta html específica, digamos un button para este ejemplo.
Tengo una función que devuelve dinámicamente un valor que uso como accesorio, en función de eso, quiero envolver el contenido de un componente.
Sé que podría haberlo logrado de esta manera también <button><compA/></button> no resuelve mi problema porque necesito cambiarlo en 100 lugares.
Mi resultado esperado:
<button><div>press me i'm button</div></button><div>don't wrap me with button leave me as it is</div> Nota: :wrappwithbutton="" tiene true para el primer uso y false para el segundo uso
const localComponent = { name:'first-comp', template:`<div> {{text}}</div>`, props:['wrappwithbutton','text'], } const app = new Vue({ el:'#app', name:'app', components:{'first-comp':localComponent}, }); <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <first-comp :wrappwithbutton="true" text="press me i'm button"></first-comp> <br/> <hr/> <br/> <first-comp :wrappwithbutton="false" text="don't wrap me with button leave me as it is"></first-comp> </div>Este es un ejemplo perfecto para las funciones de renderizado. En lugar de usar una plantilla, puede usar una función de renderizado para renderizar la plantilla por usted. Leer más sobre las funciones de renderizado
const localComponent = { name:'first-comp', props:['wrappwithbutton', 'text'], methods: { btnClick() { if (this.wrappwithbutton) console.log('button') } }, render(h) { return h(this.wrappwithbutton ? 'button' : 'div', [ h('div', this.text) ]) } } const app = new Vue({ el:'#app', name:'app', components:{'first-comp':localComponent}, }); Vue.config.productionTip = false Vue.config.devtools = false Incluso puede ir un paso más allá y hacer que su componente localComponent sea más dinámico con el padre pasando un accesorio con la etiqueta que debe representarse:
const localComponent = { name:'first-comp', props:['tag', 'text'], methods: { btnClick() { if (this.wrappwithbutton) console.log('button') } }, render(h) { return h(this.tag, [ h('div', this.text) ]) } } Si desea tener un solo div y no dos divs , puede hacerlo:
render(h) { if (this.tag === 'div') { return ('div', this.text); } return h(this.tag ? 'button' : 'div', [ h('div', this.text) ]) }Esta es mi idea, pero creo que la plantilla debería tener una forma más concisa de escribir
const localComponent = { name: "first-comp", template: ` <template v-if="wrappwithbutton"> <button> <div> {{text}}</div> </button> </template> <template v-else> <div> {{text}}</div> </template> `, props: ["wrappwithbutton", "text"] }; const app = new Vue({ el: "#app", name: "app", components: { "first-comp": localComponent } });Puede intentar centrarse en la funcionalidad en lugar de las etiquetas:
const localComponent = { name:'first-comp', template:`<div :class="wrappwithbutton && 'btn'" @click="btnClick" > {{text}} </div>`, props:['wrappwithbutton','text'], methods: { btnClick() { if (this.wrappwithbutton) console.log('button') } } } const app = new Vue({ el:'#app', name:'app', components:{'first-comp':localComponent}, }); Vue.config.productionTip = false Vue.config.devtools = false .btn { border: 1px solid violet; cursor: pointer; } <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <first-comp :wrappwithbutton="true" text="press me i'm button"></first-comp> <br/> <hr/> <br/> <first-comp :wrappwithbutton="false" text="don't wrap me with button leave me as it is"></first-comp> </div>