2.6之前的用法 (template)
1静态插槽
子组件声明
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
父组件声明
<base-layout>
<template slot="header">
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template slot="footer">
<p>Here's some contact info</p>
</template>
</base-layout>
或者
<h1 slot="header">Here might be a page title</h1>
2作用域插槽
子组件声明
//customname 任意明明
<span>
<slot name ="header" :customname="mydata">
{{ user.lastName }}
</slot>
</span>
父组件声明
// usename 为任意命名,其中 ‘customname’ 为前面子组件声明的key
<mycomponent>
<template slot="header" slot-scope="usename">
<div>{{usename.customname}}</div>
</template>
</mycomponent>
2.6之后的用法 (template)
1静态插槽
子组件声明
同上 不变化
父组件声明
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
2作用域插槽
子组件声明
同上 不变化
父组件声明
v-slot 也是需要写在template上
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
只有一种情况 是独占插槽的时候可以写在组件上
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
ps:额外补充下slot 和children区别
jsx写法
3.0之前
1静态插槽
子组件声明
export default defineComponent({
name: "Test",
render() {
return (
<>
<span>I'm Child</span>
{ this.$slots.default }
{ this.$slots.header }
</>
)
}
})
父组件声明
上面是父组件的 作用域传值 会传递到子组件的 slot和$scopedSlots
2动态插槽
子组件声明
export default defineComponent({
name: "Test",
setup() {
return {
value: {
name: 'xzw'
}
}
},
render() {
return (
<>
<span>I'm Child</span>
{ this.$scopedSlots.content?.(this.value) }
</>
)
}
})
父组件声明
<child
scopedSlots={{
default: props => {
return (
<div style="line-height: 30px;">
{props.info.title}
</div>
);
},
other: props => {
return (
<div style="line-height: 30px;">
{props.info.title}
</div>
);
}
}}
/>
3.0
1静态插槽
子组件声明
export default defineComponent({
name: "Test",
render() {
return (
<>
<span>I'm Child</span>
{ this.$slots.default?.() }
{ this.$slots.header?.() }
</>
)
}
})
或者 ,当 `enableObjectSlots` 不是 `false` 时,您可以使用对象插槽
const App = {
setup() {
return () => (
<>
<A>
{{
default: () => <div>A</div>,
bar: () => <span>B</span>,
}}
</A>
<B>{() => "foo"}</B>
</>
);
},
};
父组件声明
import { defineComponent } from 'vue'
import TestComponent from './TestComponent'
export default defineComponent({
name: "Test",
components: {
TestComponent
},
render() {
return (
<TestComponent v-slots={{
default: () => (
<div>这是默认插槽</div>
),
header: () => (
<div>这是header插槽</div>
)
}}>
</TestComponent>
)
}
})
2动态插槽
子组件声明
同上
父组件声明
同上
pps 关于 scopedSlots 在3.0中统一
v3-migration.vuejs.org/zh/breaking…
案例分析
这个组件是对el-form的二次封装,
我们先约定三个名称
eltable 为 el-table组件(孙组件)
TargetTable 为 对eltable封装,也就是图中组件 (子组件)
homeTable 为 使用TargetTable的组件 (父组件)
30行的v-slot="scope" (相当于 scoped-slot="scope")表示动态作用域,给eltable传递模板,接受el-table返回的数据 "scope"
33行 表示接受外层组件 也就是 homeTable组件传递过来模板,并像外层组件 传递参数 scope
所以这个的作用 相当于 对原来接受slot的组件二次封装时,并能透传外层组件slot
其他文章: myblogbo.com/article/28.…
备份
指令
1. v-html ==> `domPropsInnerHTML={xxxxx}`
2. v-on:click / @click ==> `on-click` = `{this.xxx()}` 无效则使用 `{() => this.xxx()}`
3. v-if ==> `xxxx ? 为true的内容 : 为false的内容` (三目运算符)
v-show ==> 在jsx中还是直接用 `v-show`
4. 指令修饰符,以`trim`为例: v-model_trim={this.userName}
5. v-for:
<p v-for="(item, index) in content" :key="index" type="success">
{{item.name}}
</el-tag>
{
this.content.map((item, index) => {
return (
<p key={index} type="success">
{item.name}
</p>
)
})
}
6. v-bind:xxx='value' ==> xxx={this.value}
动态绑定属性值
模板写法:
<router-link :to="{path: '/user-center', query: { id: this.userInfo.id }}">
个人中心
</router-link>
JSX写法:
<router-link
to={{
path: '/user-center',
query: { id: this.userInfo.id }
}}
>
个人中心
</router-link>
绑定style与class
绑定动态class:
<div class={['left-info', item.createUserId === item.userId ? 'is-landlord' : '']}></div>
动态绑定style:
写法一:
<div class="thumbnail-wrapper" style={{ width: this.width + 'px' }}></div>
写法二:
<div class="zoom-wrapper" style={'width:' + this.width + 'px;height:' + this.width + 'px'}></div>
.sync 修饰符写法
模板写法:
<MyComponent :visible.sync="showDialog" />
JSX写法:
<MyComponent visible={ this.showDialog} {...{on: {'update:visible': (val) => { this.showDialog= val }}}} />
vue事件、事件修饰符与JSX原生事件
@submit.native.prevent ==> `nativeOnSubmit={event => event.preventDefault()}`
@change ==> `on-change={() => this.formatNumber()}`
@keyup.native ==> `nativeOnKeyup={() => {this.formatNumber()}}`
@mousewheel.native.prevent ==> `nativeOnMousewheel={event => event.preventDefault()}`
@keyup.native.enter="fetch()" ==> `nativeOn-keyup={e => e.keyCode === 13 && this.fetch()}`
绑定原生属性
使用 attrs 绑定原生属性
<input
type="text"
class="num-input"
disabled
value={props.row.quantity}
attrs={{ onkeypress: 'return(/[\d]/.test(String.fromCharCode(event.keyCode)))' }}
on-input={
(event) => {
this.customizeQuantity(props.$index, props.row.id, props.row.inventory, event);
}
}
/>
template 写法:
<input
type="text"
class="num-input"
disabled
:value="scope.row.quantity"
onkeypress="return(/[\d]/.test(String.fromCharCode(event.keyCode)))"
@input="this.customizeQuantity(props.$index, props.row.id, props.row.inventory, event)"
/>
绑定原生JavaScript事件
oninput="this.type = 'password'" ==> `nativeOnInput={(e) => {e.target.type = 'password'}}`
onkeypress ==> `nativeOnKeypress={event => (/[\d]/.test(String.fromCharCode(event.keyCode)))}`
作用域插槽,以el-table为例
模板写法:
<el-table-column>
<template scope-slot="props">
<el-button
type="primary"
size="mini"
click="openDialog('edit',props.row)"
>
编辑
</el-button>
</template>
</el-table-column>
JSX写法:
<el-table-column
key={index}
label={item.name}
width={item.width}
{
...{
scopedSlots: {
default: props => {
return (
<el-button
type="primary"
size="mini"
on-click={this.openDialog.bind(this,'edit',props.row)}
>
编辑
</el-button>
)
}
}
}
}
/>