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' 
        }
    }
}

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

相关推荐
c***V3233 小时前
Vue优化
前端·javascript·vue.js
zy happy7 小时前
若依 vue3 报错:找不到模块“@/api/xxxx/xxxxx”或其相应的类型声明。。Vue 3 can not find mod
前端·javascript·vue.js
Q***l6879 小时前
Vue增强现实案例
前端·vue.js·ar
b***74889 小时前
Vue开源
前端·javascript·vue.js
前端小白۞11 小时前
vue2 md文件预览和下载
前端·javascript·vue.js
u***u68511 小时前
Vue云原生
前端·vue.js·云原生
OpenTiny社区12 小时前
TinyEngine 低代码实时协作揭秘:原理 +实操,看完直接用!
前端·vue.js·低代码
喵个咪12 小时前
go-kratos-admin 技术栈深度解析:为什么选 Golang+Vue3 这套组合?
vue.js·go
5***790012 小时前
Vue项目性能优化
前端·javascript·vue.js
抱琴_13 小时前
【Vue3】大屏性能优化黑科技:Vue 3 中实现请求合并,让你的大屏飞起来!
前端·vue.js