Open vaakian opened 4 years ago
插槽slot,父组件访问slot传过来的值。
子组件使用slot创建插槽,使用name添加具名插槽。
创建一个组件,有两个插槽:name-box
和sex-box
,name-box
绑定了一个data
属性,称之为插槽 prop
。
MyDiv.vue
<template functional>
<div>
someThing in the component.
<slot :data="{name: 'xwj', age: 21}" name="name-box">name-default</slot>
<slot name="sex-box">sex-default</slot>
</div>
</template>
父组件使用<template v-slot:slot-name="propsName"></template>
调用,并访问插槽props
<template>
<div>
<MyDiv>
<template v-slot:name-box="slotProps"> // 此处slotProps可以使用es6解构语法
name: {{ slotProps.data.name }}, age: {{ slotProps.data.age }}
</template>
</MyDiv>
</div>
</template>
跟 v-on
和 v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容(v-slot:)
替换为字符 #
。例如v-slot:header
可以被重写为 #header
<template>
<div>
<MyDiv>
<template #name-box="slotProps"> // 此处slotProps可以使用es6解构语法
name: {{ slotProps.data.name }}, age: {{ slotProps.data.age }}
</template>
</MyDiv>
</div>
</template>
动态组件,根据组件名自动切换。
非常适用于导航栏切换。
使用v-bind:is
或者简写:is
使用动态组件
<component v-bind:is="currentTabComponent"></component>
// currentTabComponent是一个字符串,代表组件名
每次切换组件,组件都会被重新render,如果需要缓存起来的话,需要使用vue提供的<keep-alive>
元素将组件包裹起来。
//失活的组件将会被缓存
<keep-alive>
<component v-bind:is="currentTabComponent">
// 这里可以往组件的slot里插入数据
</component>
</keep-alive>
使用_vm.$onice()
$listners和$attrs透传,用于创建高阶组件。 所有的@/v-on对于子组件,都通过$listeners获得。 所有的:/v-bind对于子组件,都通过$attrs获得。
首先,$listeners是什么?
假设有父组件Parent和子组件Child
// Parent
<template>
...
<child v-on:event-one="methodOne" v-on:event-two="methodTwo" />
...
</template>
那么你在使用Child时,传入的所有v-on事件都可以在$listeners对象中找到。
// Child
created () {
console.log(this.$listeners) // { 'event-one': f(), 'event-two': f() }
}
应用场景,子组件内的子组件触发事件。
// Parent
<template>
...
<child v-on:event-one="methodOne" v-on:event-two="methodTwo" />
...
</template>
// Child1
<template>
... // 一些其他组件
<Child2 v-bind="$listeners" />
...
</template>
// Child2
created() {
this.$emit("method-one", ...args); // 可触发Parent绑定的事件。
}
$attrs:组件获得的所有属性。
// Parent
<template>
...
<MyInput v-bind:value="value" type="text" maxlength="20" />
...
</template>
// MyInput
<template>
...
<input v-bind="$attrs" /> // 可获得 value="value" type="text" maxlength="20"等参数
...
</template>
综合应用,v-model透传。
我们知道,v-model等价于
<input :value="name" @input="name = $event.target.value">
//<input v-bind:value="name" v-on:input="name = $event.target.value">
这里有v-bind($attrs)和v-on($listeners)所以要实现v-model透传,只需要将这两个参数透传下去即可。
// Parent
<template>
...
<MyInput v-model="value" type="text" maxlength="20" />
...
</template>
// MyInput
<template>
...
<input v-bind="$attrs" v-bind="$listenters" /> // 错,只允许一次v-bind
<input v-bind="{...$attrs, ...$listenters}" /> // 合并对象
...
</template>
总结:v-on/@绑定的事件,子组件使用$listeners获得;v-bind/:绑定的属性,子组件使用$attrs获得。使用v-bind="$attrs/$listenrs" 全部赋予另外的组件。
父组件使用v-bind:attr.sync
,子组件使用$emit("update:attr", value)
,达到子组件修改父组件绑定的属性值,attr不允许驼峰命名。使用-作为分隔符。
// Parent
<template>
<MyInput type="text" :value.sync="title" />
// attr不一定是value,可随意指定。但只是input->title单向绑定了,需要在子组件内手动绑定v-bind:value="$attrs.title"(不写props的话)
</template>
export default {
data() {
return {
title: "hello"
};
}
};
// MyInput
<template>
<input v-bind="$attrs" @input="event => $emit("update:value", event.target.value)" />
</template>
复选框的双向绑定,自动填入
hobbies
数组中。父组件使用
@hook:mounted
调用子组件生命周期钩子事件,本质上是子组件生命周期执行时,会进行this.$emit('hook:mounted', ...args)
,也就是Vue提供的子组件调用父组件$emit方法。父组件通过props与子组件通信,子组件通过$emit向父组件发送原生事件通信。
Parent -- props --> Child
Child -- $emit --> Parent
Parent.vue
2021-9-15尝试,该方法在vue3中已经不适用,取而代之的是:
@vnode-mounted
在vue3中使用,挂载子组件生命周期方法对应如下:
....
使用
functional
声明纯函数组件,没有生命周期、data、methods等等,只单纯渲染,性能更优。 同样的,和非纯函数组件一样,我们可以props
访问父组件传递的参数。 2021-09-15 更新,发现functional已经no longer supported了。自定义组件直接使用
@click
绑定点击事件是行不通的,需要使用.native
修饰符,Vue内部最终会自动处理,子组件被点击后,触发一个$emit('click')
事件从而执行父组件绑定的click
事件。