vue 组件封装-逻辑与展示分离

vue 组件封装-逻辑与展示分离

在组件封装中,逻辑与展示的分离是一种常见的开发模式,它将组件的功能和样式分隔开来,使代码更具可读性、可维护性和可重用性,在统计与报表类场景中最为常见,往往是以不同主题或不同需求进行不同的展示,业务逻辑的代码一样展示效果不一样。以下是三种种常见的实现方式:

1. 继承

使用 extends 继承组件,这种方式的缺点就是 父组件的template和子组件template模板不能共存,只能选其一,如果要使用父级模板就子组件就不能要template,如果子组件要使用template模板,父组件的模板是继承不过来的,所以这种方式适用于只是页面不一样的的场景,让子组件去重写模板。

创建逻辑组件

javascript 复制代码
<template>
  <div class="fill-width fill-height flex1">
    <slot v-bind="thatData"></slot>
  </div>
</template>

<script>
export default {
    name:'rulesRegulaBase',
    data(){
        return {
            tableData: []
        }
    },
    computed:{
        thatData(){
            return this._data
        }
    },
    methods: {
        getPage() {
            const formSelectData = {
                simpleCondition: "",
                pageSize: 5,
                pageNumber: 1,
                sort: "createtime",
                order: "desc",
                sortS: "createtime",
                orderS: "desc"
            }
            this.$store.dispatch('specificationlistHelp',formSelectData).then(res => {
                this.tableData = res.data || []
            })
        },
        readMore(){
            const routeUrl = this.$router.resolve({ path: '/help/2' }).href;
            window.open(routeUrl, '_blank');
        },
        init(){
            this.getPage()
        }
    },
    mounted(){
        this.init()
    }
}
</script>

创建展示组件

javascript 复制代码
<template>
    <div class="flex1 height-200 hotContainer d-flex flex-col">
        <div class="hotTitle">
            <span>
                <svg-icon
                    class="primary--text text-fz-20 mr-1"
                    style="font-size: 25px !important"
                    text="notify"
                />
                <span class="titleText">&nbsp;&nbsp;规章制度</span>
            </span>
        </div>
        <div class="flex1 pa-2  overflow-auto">
            <ul class="minConentList">
                <li v-for="(item,index) in tableData" :key="index">
                    <div class="text-overflow-hidden">{{ item.title }}</div>
                </li>
            </ul>
        </div>
        <div class="height-40 con_bottom" @click="readMore()">查看全部&gt;&gt;</div>
    </div>
</template>

<script>
import rulesRegulaBase from '../../base/rulesRegulaBase'
export default {
    name:'rulesRegula',
    extends: rulesRegulaBase
}
</script>

2. 作用域插槽

使用 作用域插槽 插槽这种方式比较灵活,即可以在父组件复杂的逻辑,将需要不同展示的部分通过插槽的方式传入即可。

创建逻辑组件

Javascript 复制代码
<template>
  <div class="fill-width fill-height">
    <notice ref="noticeRef"/>
    <slot v-bind="thatData"></slot>
  </div>
</template>

<script>
import { getNoticeList } from '@/api/common/notice'
import notice from "@Work/notice"
export default {
    components: {
        notice
    },
    data(){
        return {
            noticeList: []
        }
    },
    computed:{
        thatData(){
            return this._data
        }
    },
    methods: {
        getTop10NoticeList(){
            getNoticeList().then(res => {
                this.noticeList = res.data || []
            })
        },
        readMore(){
            this.$refs.noticeRef.showDialog()
        },
        init(){
            this.getTop10NoticeList()
        }
    },
    mounted(){
        this.init()
    },

}
</script>

<style>

</style>

创建展示组件

Javascript 复制代码
<template>
    <notifiMessageBase ref="notifiMessageBaseRef">
        <template #default="{noticeList}">
            <div class="flex1 height-200 hotContainer d-flex flex-col minwidth-0">
                <div class="hotTitle">
                    <span>
                        <svg-icon
                            class="primary--text text-fz-20 mr-1"
                            style="font-size: 25px !important"
                            text="book"
                        />
                        <span class="titleText">&nbsp;&nbsp;通知消息</span>
                    </span>
                </div>
                <div class="flex1 pa-2 overflow-auto">
                    <ul class="minConentList">
                        <li v-for="(item,index) in noticeList" :key="index">
                            <div class="text-overflow-hidden">{{ item.title }}</div>
                        </li>
                    </ul>
                </div>
                <div class="height-40 con_bottom" @click="notifiMessageBaseRefObj.readMore()">查看全部>></div>
            </div>
        </template>
    </notifiMessageBase>
</template>

<script>
import notifiMessageBase from '../../base/notifiMessageBase'
export default {
    name:'notifiMessage',
    components: {
        notifiMessageBase
    },
    computed: {
        notifiMessageBaseRefObj(){
            return this.$refs.notifiMessageBaseRef
        }
    }
}
</script>

3. mixin混入

创建mixin.js

javascript 复制代码
<script>
export default {
    name:'rulesRegulaBase',
    data(){
        return {
            tableData: []
        }
    },
    computed:{
        thatData(){
            return this._data
        }
    },
    methods: {
        getPage() {
            const formSelectData = {
                simpleCondition: "",
                pageSize: 5,
                pageNumber: 1,
                sort: "createtime",
                order: "desc",
                sortS: "createtime",
                orderS: "desc"
            }
            this.$store.dispatch('specificationlistHelp',formSelectData).then(res => {
                this.tableData = res.data || []
            })
        },
        readMore(){
            const routeUrl = this.$router.resolve({ path: '/help/2' }).href;
            window.open(routeUrl, '_blank');
        },
        init(){
            this.getPage()
        }
    },
    mounted(){
        this.init()
    }
}
</script>

创建逻辑组件

javascript 复制代码
<template>
    <div class="flex1 height-200 hotContainer d-flex flex-col">
        <div class="hotTitle">
            <span>
                <svg-icon
                    class="primary--text text-fz-20 mr-1"
                    style="font-size: 25px !important"
                    text="notify"
                />
                <span class="titleText">&nbsp;&nbsp;规章制度</span>
            </span>
        </div>
        <div class="flex1 pa-2  overflow-auto">
            <ul class="minConentList">
                <li v-for="(item,index) in tableData" :key="index">
                    <div class="text-overflow-hidden">{{ item.title }}</div>
                </li>
            </ul>
        </div>
        <div class="height-40 con_bottom" @click="readMore()">查看全部&gt;&gt;</div>
    </div>
</template>

<script>
import rulesRegulaBase from '../../base/rulesRegulaBase'
export default {
    name:'rulesRegula',
    mixins: [rulesRegulaBase]
}
</script>

使用 v-if (不推荐)

这种方式简单,逻辑与展示都写在了同一个组件里了

language 复制代码
<template>
    <div class="flex1 height-200 hotContainer d-flex flex-col">
        <divclass="flex1 pa-2  overflow-auto" v-if="templateone">
           
        </div>
        <div class="flex1 pa-2  overflow-auto" v-if="templatetow">
            
        </div>
    </div>
</template>

<script>
export default {
    name:'rulesRegula',
    data(){
        return {
              templateType: 'templateone' 
        }
    }
}

每种方式都有各自的使用场景,选用一种适合自己业务的即可。

相关推荐
志尊宝1 小时前
Vue3 零基础每日笔记(088·完结):从零到一——一个完整 Vue3 项目的成长复盘
前端·javascript·vue.js·笔记·ecmascript·#vue.js
桔筐1 小时前
Vue中DOM的data-*自定义属性(dataset)与Vue data响应式变量区别详解
前端·javascript·vue.js
用户1733598075372 小时前
纯前端 PDF 按书签拆分避坑指南:拆分后章节对不上?
前端·javascript·vue.js
雪芽蓝域zzs3 小时前
Webstorm打开uniapp uvue文件报红处理方案
vue.js
撸串-研究生4 小时前
面向景区的综合服务管理平台设计——以稻城亚丁景区为例【附源码】
java·开发语言·vue.js·前后端分离·稻城亚丁景区
志尊宝16 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
m0_587383001 天前
无人自助拼豆系统落地开发实战指南 核心逻辑实现与部署经验分享
前端·javascript·vue.js·人工智能·经验分享·需求分析
.Hypocritical.1 天前
SpringBoot+Vue 前后端分离项目部署到云服务器
服务器·vue.js·spring boot
溪语流沙1 天前
【Web全栈进阶】Vue3起步:组件、模板语法、响应式数据
前端·javascript·vue.js·css3
志尊宝1 天前
Vue3 零基础每日笔记(081):富文本编辑器集成 wangEditor 5——封装
前端·javascript·vue.js·笔记·信息可视化·echarts