[英]How to update a slot in Vue.JS
我在下面簡化了Vue組件。
這是模板
<template>
<slot></slot>
</template>
插槽可能包含HTML,這就是為什么我決定使用插槽而不是我會簡單綁定到的道具的原因。 我想保持這種方式。
我有一種從服務器獲取新HTML的方法。 我想使用這個新的HTML來更新廣告位。 我不確定插槽是否具有反應性以及如何實現此目的。
我可以使用this.$slots.default[0]
查看默認插槽,但是我不知道如何使用字符串HTML內容更新默認插槽。 簡單地將字符串分配給元素顯然是不正確的,因為.innerHtml
不是可用的函數,因此對.innerHtml
不起作用,而對.text
不起作用。 我假定即使插槽對象上存在文本元素,但元素屬性仍然優先。
根據評論中的建議,我已經嘗試過將其與計算機屬性一起使用。
<span v-html="messageContent"><slot></slot></span>
但是現在的問題是,它覆蓋了傳遞給我的廣告位。
如何在Vue.JS中使用新的HTML反應式更新廣告位?
我認為您的問題源於對<slot>
在VueJS中固有工作方式的誤解。 插槽用於將內容從使用中的父組件交織到子組件中。 將其視為等同於v-bind:prop
的HTML。 在組件上使用v-bind:prop
時,實際上是在將數據傳遞到子組件中。 這與插槽相同。
如果沒有最終的具體示例或代碼,此答案充其量只是猜測。 我假設您的父組件本身就是VueJS應用程序,子組件就是保存<slot>
元素的組件。
<!-- Parent template -->
<div id="app">
<custom-component>
<!-- content here -->
</custom-component>
</div>
<!-- Custom component template -->
<template>
<slot></slot>
</template>
在這種情況下,應用程序具有默認的基本狀態,在該狀態下,它將靜態HTML傳遞給子組件:
<!-- Parent template -->
<div id="app">
<custom-component>
<!-- Markup to be interweaved into custom component -->
<p>Lorem ipsum dolor sit amet.</p>
</custom-component>
</div>
<!-- Custom component template -->
<template>
<slot></slot>
</template>
然后,在觸發事件時,您想用新的傳入標記替換該基態標記。 這可以通過將傳入的HTML存儲在data
屬性中,並簡單地使用v-html
有條件地呈現它來完成。 假設我們要將傳入的標記存儲在應用程序的vm.$data.customHTML
:
data: {
customHTML: null
}
然后您的模板將如下所示:
<!-- Parent template -->
<div id="app">
<custom-component>
<div v-if="customHTML" v-html="customHTML"></div>
<div v-else>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</custom-component>
</div>
<!-- Custom component template -->
<template>
<slot></slot>
</template>
請注意,與您嘗試的代碼相比,不同之處在於:
<slot>
元素中 請參閱下面的概念驗證:
var customComponent = Vue.component('custom-component', { template: '#custom-component-template' }); new Vue({ el: '#app', data: { customHTML: null }, components: { customComponent: customComponent }, methods: { updateSlot: function() { this.customHTML = '<p>Foo bar baz</p>'; } } });
.custom-component { background-color: yellow; border: 1px solid #000; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <div id="app"> <h1>I am the app</h1> <button type="button" @click="updateSlot">Click me to update slot content</button> <custom-component> <div v-if="customHTML" v-html="customHTML"> </div> <div v-else> <p>Lorem ipsum dolor sit amet.</p> </div> </custom-component> </div> <!-- custom-component template --> <script type="text/template" id="custom-component-template"> <div class="custom-component"> <h2>I am a custom component</h2> <!-- slot receives markup set in <custom-component> --> <slot></slot> </div> </script>
以下是我的解決方案,盡管我不喜歡這種觀點(將html直接加載到當前組件級別的插槽中),因為它違反了插槽的規則。 而且我認為您應該喜歡這種方式( <component><template v-html="yourHtml"></template></component>
),這樣會更好,因為Slot將專注於Vue設計的工作。
關鍵是this.$slots.default
必須是一個VNode,因此我使用extend()
和$mount()
來獲取_vnode。
Vue.config.productionTip = false Vue.component('child', { template: '<div><slot></slot><a style="color:green">Child</a></div>', mounted: function(){ setTimeout(()=>{ let slotBuilder = Vue.extend({ // use your html instead template: '<div><a style="color:red">slot in child</a></div>', }) let slotInstance = new slotBuilder() this.$slots.default = slotInstance.$mount()._vnode this.$forceUpdate() }, 2000) } }) new Vue({ el: '#app', data() { return { test: '' } } })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script> <div id="app"> <child><h1>Test</h1></child> </div>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.