16-不得不学的Vue.js基础之自定义事件
前端 · 2020-07-22 ·
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自定义事件</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!--1.事件名:我们推荐你始终使用 kebab-case(短横线) 的事件名-->
<!--2.自定义组件的 v-model:一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的 event,但是像单选框、复选框等类型的输入控件可能会将 value 属性用于不同的目的。model 选项可以用来避免这样的冲突-->
<!--这里的 lovingVue 的值会传入这个名为 checked 的prop,当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的 property 将会被更新-->
<p>
<base-checkbox v-model="lovingVue"></base-checkbox> 选择
</p>
<!--3.将原生事件绑定到组件:在根元素上直接监听一个原生事件,这是可以通过 v-on 的 .native 修饰符-->
<!--3.1 首先定义个 base-button 组件,添加handleClick方法,当我们点击这个组件,并没有 输出对应的信息“base-button clicked!”-->
<!--这个时候.native 修饰符就提现出他的作用,我们加上此修饰符,此时点击按钮输出对应的信息“base-button clicked!”-->
<!--.native的作用:监听组件根元素的原生事件!除此之外,我们也可以通过 $emit 事件派发给父组件-->
<p>
<base-button v-on:click.native="handleClick"></base-button>
</p>
<p>
<base-button2 v-on:click="handleClick2"></base-button2>
</p>
<!--3.2 native修饰符:将原生事件绑定到组件的根元素上,但是有的时候根元素并没有原生事件。比如如下全局组件3.3,根元素实际上是 <label>,就不能使用如上重构,这是父级的 .native 监听器将静默失败。-->
<!--为了解决这个问题,Vue 提供了一个 $listeners property,它是一个对象,里面包含了作用在这个组件上的所有监听器。例如
{
focus:function (event){
/*...*/
}
input:function (event){
/*...*/
}
}
-->
<!--现在 <base-input> 组件是可以完全像一个普通的 <input> 元素一样使用了:所有跟他相同的attribute 和 监听器都可以工作,不必再使用.native 监听器。-->
<p>
<base-input label="price" placeholder="placeholder" v-model="price"></base-input>
</p>
<!--4. sync修饰符:语法糖,它会被扩展为一个自动更新父组件属性的 v-on 监听器,既子组件改变某个prop 的时候,来变更父组件的状态值进而变更子组件状态。-->
<!--
<comp v-bind:foo.sync="bar"></comp>
会被扩展为
<comp v-bind:foo="bar" v-on:update:foo="val => bar = val"></comp>
当子组件更新foo的值时,它就触发一个更新事件
this.$emit('update:foo',newValue)
-->
<p>
<base-toggle :show.sync='ifshow'></base-toggle>
<button @click="changeIfshow">toggle</button>
</p>
</div>
<script>
// 2.注册全局组件base-checkbox!
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
});
// 3.1注册全局组件base-button!
Vue.component('base-button',{
template:`
<button>Click Me</button>
`
});
// 3.2注册全局组件base-button2!
Vue.component('base-button2',{
template:`
<button v-on:click="click">Click Me2</button>
`,
methods:{
click(){
this.$emit('click',"I am form child!")
}
}
});
// 3.3注册全局组件base-input!
Vue.component('base-input',{
inheritAttrs: false,
props:['label','value'],
computed:{
inputListeners:function(){
var vm =this;
//`Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input:function(event){
vm.$emit('input',event.target.value)
},
focus:function(event) {
console.log('onFocus 事件')
}
}
)
}
},
template:`
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
</label>
`,
methods:{
click(){
this.$emit('click',"I am form child!")
}
}
});
// 4.注册全局组件base-toggle!
Vue.component('base-toggle',{
template:`
<div>
<p v-if="show">默认初始值是{{show}},所以是显示的</p>
<button @click.stop="closeDiv">关闭</button>
</div>
`,
props:['show'],
methods:{
closeDiv(){
this.$emit('update:show',false);
}
}
});
var vm = new Vue({
el: "#app",
data:{
lovingVue: true,
price:0,
ifshow:true
},
methods:{
handleClick(){
console.log("base-button clicked!");
},
handleClick2(val){
console.log(val);
},
changeIfshow(){
this.ifshow = !this.ifshow;
}
}
});
</script>
</body>
</html>
以下是测试数据: