我正在编写一个简单的工具提示组件。工具提示的内容使用vue插槽定义。我希望插槽的内容能够发出工具提示的结束信号,就像工具提示可以从自己的模板中关闭一样。
以下是示例代码:
Vue.component('vtip', {
created: function() {
this.$on('closeDialog', function(a,b,c) {
console.log('[closeDialog in vtip]', a,b,c,this);
this.closeDialog(); // idfk
});
},
props: ['button_text'],
template: '#vtip_template',
methods: {
closeDialog: function(event) {
var $dialog = $(this.$refs.dialog);
$dialog.fadeToggle('fast');
},
toggleDialog: function(event) {
var $button = $(this.$refs.button);
var $dialog = $(this.$refs.dialog);
var button_left = $button.position().left;
var button_top = $button.position().top;
var extras = 2;
var arrow_size = 10;
var new_pos = {left:button_left+'px',top:button_top+$button.height()+arrow_size+extras+'px'};
$dialog.css(new_pos);
$dialog.fadeToggle('fast');
},
}
});
var v_app;
$(document).ready(function () {
v_app = new Vue({
el: '#v_app',
});
});

body {
background:#eee;
padding:1em;
font-family:Verdana;
font-size:11pt;
}
.dialog {
background:#222;
color:#eee;
border:2px solid white;
display:none;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius:4px;
position:absolute;
}
.dialog .item-body .item-body {
padding:1em 1em;
}
.dialog .item-body {
min-width:10em;
padding:0.5em 1em;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script id="vtip_template" type="x-template">
<span style="position:relative;">
<button @click="toggleDialog" v-text="button_text" ref="button"></button>
<div ref="dialog" class="dialog">
<div class='item-body'>
<a @click="closeDialog" style="float:right;color:white;padding:1em;" href="#">x</a>
<!-- i hate slots -->
<slot>...</slot>
</div>
</div>
</span>
</script>
<DIV id="v_app">
1. Click Hey.<br>
2. How do I make the "Yes!" button close the component like the "x" link does?<br>
<vtip button_text="hey">
<!-- how do i make it so this slot child can close the parent component -->
Are you sure?
<button>Yes!</button> <!-- @click="closeDialog" does not work (and should not) -->
</vtip>
</DIV>
&#13;
答案 0 :(得分:2)
您可以向ref
组件标记添加vtip
属性,然后通过closeDialog
对象引用组件的$refs
方法:
<vtip button_text="hey" ref="tip">
Are you sure?
<button @click="$refs.tip.closeDialog()">Yes!</button>
</vtip>
Vue.component('vtip', {
created: function() {
this.$on('closeDialog', function(a,b,c) {
console.log('[closeDialog in vtip]', a,b,c,this);
this.closeDialog(); // idfk
});
},
props: ['button_text'],
template: '#vtip_template',
methods: {
closeDialog: function(event) {
var $dialog = $(this.$refs.dialog);
$dialog.fadeToggle('fast');
},
toggleDialog: function(event) {
var $button = $(this.$refs.button);
var $dialog = $(this.$refs.dialog);
var button_left = $button.position().left;
var button_top = $button.position().top;
var extras = 2;
var arrow_size = 10;
var new_pos = {left:button_left+'px',top:button_top+$button.height()+arrow_size+extras+'px'};
$dialog.css(new_pos);
$dialog.fadeToggle('fast');
},
}
});
var v_app;
$(document).ready(function () {
v_app = new Vue({
el: '#v_app',
});
});
&#13;
body {
background:#eee;
padding:1em;
font-family:Verdana;
font-size:11pt;
}
.dialog {
background:#222;
color:#eee;
border:2px solid white;
display:none;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius:4px;
position:absolute;
}
.dialog .item-body .item-body {
padding:1em 1em;
}
.dialog .item-body {
min-width:10em;
padding:0.5em 1em;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script id="vtip_template" type="x-template">
<span style="position:relative;">
<button @click="toggleDialog" v-text="button_text" ref="button"></button>
<div ref="dialog" class="dialog">
<div class='item-body'>
<a @click="closeDialog" style="float:right;color:white;padding:1em;" href="#">x</a>
<!-- i hate slots -->
<slot>...</slot>
</div>
</div>
</span>
</script>
<DIV id="v_app">
1. Click Hey.<br>
2. How do I make the "Yes!" button close the component like the "x" link does?<br>
<vtip button_text="hey" ref="tip">
<!-- how do i make it so this slot child can close the parent component -->
Are you sure?
<button @click="$refs.tip.closeDialog()">Yes!</button> <!-- @click="closeDialog" does not work (and should not) -->
</vtip>
</DIV>
&#13;
或者,您也可以使用scoped slot,将closeDialog
方法作为props
中的点击处理程序属性传递。
在插槽定义中,绑定clickHandler
属性:
<slot :clickHandler="closeDialog">...</slot>
然后,在您的父组件中,您可以通过范围clickHandler
访问props
,如下所示:
<vtip button_text="hey">
<template scope="props">
Are you sure?
<button @click="props.clickHandler">Yes!</button>
</template>
</vtip>
Vue.component('vtip', {
created: function() {
this.$on('closeDialog', function(a,b,c) {
console.log('[closeDialog in vtip]', a,b,c,this);
this.closeDialog(); // idfk
});
},
props: ['button_text'],
template: '#vtip_template',
methods: {
closeDialog: function(event) {
var $dialog = $(this.$refs.dialog);
$dialog.fadeToggle('fast');
},
toggleDialog: function(event) {
var $button = $(this.$refs.button);
var $dialog = $(this.$refs.dialog);
var button_left = $button.position().left;
var button_top = $button.position().top;
var extras = 2;
var arrow_size = 10;
var new_pos = {left:button_left+'px',top:button_top+$button.height()+arrow_size+extras+'px'};
$dialog.css(new_pos);
$dialog.fadeToggle('fast');
},
}
});
var v_app;
$(document).ready(function () {
v_app = new Vue({
el: '#v_app',
});
});
&#13;
body {
background:#eee;
padding:1em;
font-family:Verdana;
font-size:11pt;
}
.dialog {
background:#222;
color:#eee;
border:2px solid white;
display:none;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius:4px;
position:absolute;
}
.dialog .item-body .item-body {
padding:1em 1em;
}
.dialog .item-body {
min-width:10em;
padding:0.5em 1em;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script id="vtip_template" type="x-template">
<span style="position:relative;">
<button @click="toggleDialog" v-text="button_text" ref="button"></button>
<div ref="dialog" class="dialog">
<div class='item-body'>
<a @click="closeDialog" style="float:right;color:white;padding:1em;" href="#">x</a>
<!-- i hate slots -->
<slot :clickHandler="closeDialog">...</slot>
</div>
</div>
</span>
</script>
<DIV id="v_app">
1. Click Hey.<br>
2. How do I make the "Yes!" button close the component like the "x" link does?<br>
<vtip button_text="hey">
<template scope="props">
Are you sure?
<button @click="props.clickHandler">Yes!</button>
</template>
</vtip>
</DIV>
&#13;