马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
目次
一、弁言
二、默认插槽
2.1. 默认插槽根本语法
2.2. 完备代码
2.2.1. main.js
2.2.2. App.vue
2.2.3. MyDialog.vue
2.3. 运行效果
三、插槽后备内容(默认值)
3.1. 插槽后备内容根本语法
3.2. 完备代码
3.2.1. main.js
3.2.2. App.vue
3.2.3. MyDialog.vue
3.3. 运行效果
四、具名插槽
4.1. 具名插槽语法
4.2. 完备代码
4.2.1. main.js
4.2.2. App.vue
4.2.3. MyDialog.vue
五、作用域插槽
5.1. 作用域插槽语法
5.2. 完备代码
5.2.1. main.js
5.2.2. App.vue
5.2.3. MyTable.vue
一、弁言
如下图所示的两个对话框,除了内部的提示语信息内容有一些差异外,其他部分完全类似。这种环境下我们可以将对话框类似公用的部分抽取封装成一个组件,内部的会变更的提示语信息(组件的内容)通过插槽举行定制化传入参数,从而实现组件的复用。
插槽作用:让组件内部的一些布局支持自界说。
二、默认插槽
2.1. 默认插槽根本语法
1. 组件内须要定制的布局部分,改用<slot></slot>占位
2. 使用组件时, <MyDialog></MyDialog>标签内部, 传入布局更换slot
2.2. 完备代码
2.2.1. main.js
- import Vue from 'vue'
- import App from './App.vue'
- Vue.config.productionTip = false
- new Vue({
- render: h => h(App),
- }).$mount('#app')
复制代码 2.2.2. App.vue
- <template>
- <div>
- <!-- 2. 在使用组件时,组件标签内填入内容 -->
- <MyDialog>
- <div>你确认要删除么</div>
- </MyDialog>
- <MyDialog>
- <p>你确认要退出么</p>
- </MyDialog>
- </div>
- </template>
- <script>
- import MyDialog from './components/MyDialog.vue'
- export default {
- data () {
- return {
- }
- },
- components: {
- MyDialog
- }
- }
- </script>
- <style>
- body {
- background-color: #b3b3b3;
- }
- </style>
复制代码 2.2.3. MyDialog.vue
- <template>
- <div class="dialog">
- <div class="dialog-header">
- <h3>友情提示</h3>
- <span class="close">✖️</span>
- </div>
- <div class="dialog-content">
- <!-- 1. 在需要定制的位置,使用slot占位 -->
- <slot></slot>
- </div>
- <div class="dialog-footer">
- <button>取消</button>
- <button>确认</button>
- </div>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- }
- }
- }
- </script>
- <style scoped>
- * {
- margin: 0;
- padding: 0;
- }
- .dialog {
- width: 470px;
- height: 230px;
- padding: 0 25px;
- background-color: #ffffff;
- margin: 40px auto;
- border-radius: 5px;
- }
- .dialog-header {
- height: 70px;
- line-height: 70px;
- font-size: 20px;
- border-bottom: 1px solid #ccc;
- position: relative;
- }
- .dialog-header .close {
- position: absolute;
- right: 0px;
- top: 0px;
- cursor: pointer;
- }
- .dialog-content {
- height: 80px;
- font-size: 18px;
- padding: 15px 0;
- }
- .dialog-footer {
- display: flex;
- justify-content: flex-end;
- }
- .dialog-footer button {
- width: 65px;
- height: 35px;
- background-color: #ffffff;
- border: 1px solid #e1e3e9;
- cursor: pointer;
- outline: none;
- margin-left: 10px;
- border-radius: 3px;
- }
- .dialog-footer button:last-child {
- background-color: #007acc;
- color: #fff;
- }
- </style>
复制代码 2.3. 运行效果
三、插槽后备内容(默认值)
3.1. 插槽后备内容根本语法
我们通过插槽实现内容的定制,同时插槽还支持设定默认的内容,即插槽后备内容。我们在封装组件时,可以为预留的`<slot>` 插槽提供后备内容(默认内容)。
外部使用组件时,不传东西,则slot会体现后备内容
外部使用组件时,传东西了,则slot团领会被换掉
3.2. 完备代码
3.2.1. main.js
- import Vue from 'vue'
- import App from './App.vue'
- Vue.config.productionTip = false
- new Vue({
- render: h => h(App),
- }).$mount('#app')
复制代码 3.2.2. App.vue
- <template>
- <div>
- <MyDialog>
- </MyDialog>
- <MyDialog>
- <p>你确认要退出么</p>
- </MyDialog>
- </div>
- </template>
- <script>
- import MyDialog from './components/MyDialog.vue'
- export default {
- data () {
- return {
- }
- },
- components: {
- MyDialog
- }
- }
- </script>
- <style>
- body {
- background-color: #b3b3b3;
- }
- </style>
复制代码 3.2.3. MyDialog.vue
- <template>
- <div class="dialog">
- <div class="dialog-header">
- <h3>友情提示</h3>
- <span class="close">✖️</span>
- </div>
- <div class="dialog-content">
- <!-- 插槽默认显示的内容 -->
- <slot>插槽默认显示的内容</slot>
- </div>
- <div class="dialog-footer">
- <button>取消</button>
- <button>确认</button>
- </div>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- }
- }
- }
- </script>
- <style scoped>
- * {
- margin: 0;
- padding: 0;
- }
- .dialog {
- width: 470px;
- height: 230px;
- padding: 0 25px;
- background-color: #ffffff;
- margin: 40px auto;
- border-radius: 5px;
- }
- .dialog-header {
- height: 70px;
- line-height: 70px;
- font-size: 20px;
- border-bottom: 1px solid #ccc;
- position: relative;
- }
- .dialog-header .close {
- position: absolute;
- right: 0px;
- top: 0px;
- cursor: pointer;
- }
- .dialog-content {
- height: 80px;
- font-size: 18px;
- padding: 15px 0;
- }
- .dialog-footer {
- display: flex;
- justify-content: flex-end;
- }
- .dialog-footer button {
- width: 65px;
- height: 35px;
- background-color: #ffffff;
- border: 1px solid #e1e3e9;
- cursor: pointer;
- outline: none;
- margin-left: 10px;
- border-radius: 3px;
- }
- .dialog-footer button:last-child {
- background-color: #007acc;
- color: #fff;
- }
- </style>
复制代码 3.3. 运行效果
四、具名插槽
前面我们讲的默认插槽,它只支持组件内只有一处内容差异须要自界说的环境。但我们在现实开发过程中常常会遇到组件中有多处内容差异须要自界说,这时我们可以使用具名插槽来实现。
下面的提示框我们可以看到除了提示语差异外,提示框的标题也差异: 4.1. 具名插槽语法
1. 多个slot使用name属性区分名字
2. template共同v-slot:名字来分发对应标签
4.2. 完备代码
4.2.1. main.js
- import Vue from 'vue'
- import App from './App.vue'
- Vue.config.productionTip = false
- new Vue({
- render: h => h(App),
- }).$mount('#app')
复制代码 4.2.2. App.vue
- <template>
- <div>
- <MyDialog>
- <!-- 需要通过template标签包裹需要分发的结构,包成一个整体 -->
- <template v-slot:head>
- <div>我是大标题</div>
- </template>
-
- <template v-slot:content>
- <div>我是内容</div>
- </template>
- <template #footer>
- <button>取消</button>
- <button>确认</button>
- </template>
- </MyDialog>
- </div>
- </template>
- <script>
- import MyDialog from './components/MyDialog.vue'
- export default {
- data () {
- return {
- }
- },
- components: {
- MyDialog
- }
- }
- </script>
- <style>
- body {
- background-color: #b3b3b3;
- }
- </style>
复制代码 4.2.3. MyDialog.vue
- <template>
- <div class="dialog">
- <div class="dialog-header">
- <!-- 一旦插槽起了名字,就是具名插槽,只支持定向分发 -->
- <slot name="head"></slot>
- </div>
- <div class="dialog-content">
- <slot name="content"></slot>
- </div>
- <div class="dialog-footer">
- <slot name="footer"></slot>
- </div>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- }
- }
- }
- </script>
- <style scoped>
- * {
- margin: 0;
- padding: 0;
- }
- .dialog {
- width: 470px;
- height: 230px;
- padding: 0 25px;
- background-color: #ffffff;
- margin: 40px auto;
- border-radius: 5px;
- }
- .dialog-header {
- height: 70px;
- line-height: 70px;
- font-size: 20px;
- border-bottom: 1px solid #ccc;
- position: relative;
- }
- .dialog-header .close {
- position: absolute;
- right: 0px;
- top: 0px;
- cursor: pointer;
- }
- .dialog-content {
- height: 80px;
- font-size: 18px;
- padding: 15px 0;
- }
- .dialog-footer {
- display: flex;
- justify-content: flex-end;
- }
- .dialog-footer button {
- width: 65px;
- height: 35px;
- background-color: #ffffff;
- border: 1px solid #e1e3e9;
- cursor: pointer;
- outline: none;
- margin-left: 10px;
- border-radius: 3px;
- }
- .dialog-footer button:last-child {
- background-color: #007acc;
- color: #fff;
- }
- </style>
复制代码 五、作用域插槽
我们在企业级项目开发过程中,常常会遇到PC端管理背景中有些列表的列头和列题在差异的条件下会动态的变更,以外的开发实现上大概会使用判定条件语句来实现,假如动态变更的种类条件许多的环境下,代码就会相当复杂和冗余。别的尚有列表中最右侧列,有些满是查察按钮,有些满是删除按钮。在Vue中,这些需求通过作用域插槽实现起来就非常简便。
使用具名插槽结相助用域插槽实现动态表格:
使用默认插槽结相助用域插槽实现动态使用按钮:
留意:作用域插槽并不是插槽的一个种类,插槽只有默认插槽和具名插槽两种。作用域插槽它是插槽的一种传参语法。
作用域插槽的意思是在界说 slot 插槽的时间, 我们还可以传值。给插槽上可以绑定命据,未来使用组件时可以用。
如下的场景需求:封装表格组件
5.1. 作用域插槽语法
1. 给 slot 标签, 以添加属性的方式传值
2. 全部添加的属性, 都会被网络到一个对象中
3. 在父组件的template中, 通过 ` #插槽名= "obj" ` 吸取子组件中插槽的传值,默认插槽名为default
5.2. 完备代码
5.2.1. main.js
- import Vue from 'vue'
- import App from './App.vue'
- Vue.config.productionTip = false
- new Vue({
- render: h => h(App),
- }).$mount('#app')
复制代码 5.2.2. App.vue
- <template>
- <div>
- <MyTable :data="list">
- <!-- 3. 通过template #插槽名="变量名" 接收 MyTable插槽的传参,传过来的参数是个如下形式的obj -->
- <!-- {
- row: { id: 2, name: '孙红雷', age: 19 },
- msg: '测试文本'
- } -->
- <template #default="obj">
- <button @click="del(obj.row.id)">
- 删除
- </button>
- </template>
- </MyTable>
-
- <MyTable :data="list2">
- <!-- { row } 为直接从obj从解构出来的对象 -->
- <template #default="{ row }">
- <button @click="show(row)">查看</button>
- </template>
- </MyTable>
- </div>
- </template>
- <script>
- import MyTable from './components/MyTable.vue'
- export default {
- data () {
- return {
- list: [
- { id: 1, name: '李沁', age: 18 },
- { id: 2, name: '虞书欣', age: 19 },
- { id: 3, name: '新垣结衣', age: 17 },
- ],
- list2: [
- { id: 1, name: '胡歌', age: 18 },
- { id: 2, name: '朱一龙', age: 19 },
- { id: 3, name: '刘烨', age: 17 },
- ]
- }
- },
- methods: {
- del (id) {
- this.list = this.list.filter(item => item.id !== id)
- },
- show (row) {
- // console.log(row);
- alert(`姓名:${row.name}; 年纪:${row.age}`)
- }
- },
- components: {
- MyTable
- }
- }
- </script>
复制代码 5.2.3. MyTable.vue
- <template>
- <table class="my-table">
- <thead>
- <tr>
- <th>序号</th>
- <th>演员</th>
- <th>年纪</th>
- <th>操作</th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="(item, index) in data" :key="item.id">
- <td>{{ index + 1 }}</td>
- <td>{{ item.name }}</td>
- <td>{{ item.age }}</td>
- <td>
- <!-- 1. 给slot标签,添加多个属性的方式传值 -->
- <slot :row="item" msg="测试文本"></slot>
- <!-- 2. 将所有的属性,添加到一个对象中 -->
- <!--
- {
- row: { id: 2, name: '孙大明', age: 19 },
- msg: '测试文本'
- }
- -->
- </td>
- </tr>
- </tbody>
- </table>
- </template>
- <script>
- export default {
- props: {
- data: Array
- }
- }
- </script>
- <style scoped>
- .my-table {
- width: 450px;
- text-align: center;
- border: 1px solid #ccc;
- font-size: 24px;
- margin: 30px auto;
- }
- .my-table thead {
- background-color: #1f74ff;
- color: #fff;
- }
- .my-table thead th {
- font-weight: normal;
- }
- .my-table thead tr {
- line-height: 40px;
- }
- .my-table th,
- .my-table td {
- border-bottom: 1px solid #ccc;
- border-right: 1px solid #ccc;
- }
- .my-table td:last-child {
- border-right: none;
- }
- .my-table tr:last-child td {
- border-bottom: none;
- }
- .my-table button {
- width: 65px;
- height: 35px;
- font-size: 18px;
- border: 1px solid #ccc;
- outline: none;
- border-radius: 3px;
- cursor: pointer;
- background-color: #ffffff;
- margin-left: 5px;
- }
- </style>
复制代码
|