参见https://jsfiddle.net/d017am59/1/
我有一个复选框控制box
元素是否应该显示黑色文本。
<div id="app">
<label><input type='checkbox' v-model='showBlack' />Show black</label>
<box>Hello</box>
<box>World</box>
<box>Hi</box>
<box>Bye</box>
</div>
Vue.component('box', {
template: `
<div v-bind:style='styleObject'>
{{text}}
<slot></slot>
</div>`,
data: function() {
return {
text: vueApp.showBlack?'black text: ':'white text: ',
styleObject:{
color: vueApp.showBlack?'black':'white',
'background-color':vueApp.showBlack?'white':'black',
}
}
}
});
const vueApp= new Vue({
el: '#app',
data: {
showBlack: true,
},
});
box
是一个复杂的组件,但我只在这里给出相关的道具。举例来说,如果复选框被选中,则颜色为黑色,背景为白色;如果未选中该复选框,则颜色与背景颜色相反。
我的代码不工作,因为Vue抛出一个错误"Cannot access 'vueApp' before initialization."
我的box
元素如何收听复选框?
我不太喜欢使用全局mixin,因为全局mixin会注入到所有组件,而我只想注入到box
。
我不喜欢给box添加一个prop,并将showBlack
传递给所有box
实例的prop。我的业务需求是所有的框都必须服从复选框,如果我必须写:
<box v-bind:showBlack="showBlack">Hello</box>
<box v-bind:showBlack="showBlack">Wolrd</box>
<box v-bind:showBlack="showBlack">Hi</box>
<box v-bind:showBlack="showBlack">Bye</box>
我可以用Vue 2或Vue 3。
一个快速的解决方案是使用this.$root
访问根实例(实例化Vue
的那个实例)的数据。另外,请注意<box>
中的绑定应该是computed
props,这样它们就可以响应根目录showBlack
中的更改:
Vue.component('box', {
template: `
<div v-bind:style='styleObject'>
{{ text }}
<slot></slot>
</div>`,
computed: {
text() {
return this.$root.showBlack ? 'black text: ' : 'white text: '
},
styleObject() {
return {
color: this.$root.showBlack ? 'black' : 'white',
'background-color': this.$root.showBlack ? 'white' : 'black',
}
}
}
})
演示HTML:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div><label><input type='checkbox' v-model='showBlack' />Show black</label></div>
<box :black="showBlack">Hello</box>
</div>
JS:
Vue.component('box', {
template: `
<div v-bind:style='styleObject'>
<slot></slot>
</div>
`,
props: ['black'],
data: function() {
return {}
},
computed: {
styleObject() {
return {
color: this.black ? 'black' : 'white',
'background-color': this.black ? 'white' : 'black',
}
}
}
});
const vueApp= new Vue({
el: '#app',
data: {
showBlack: true,
},
});