vue实现简易流程图

这是最终实现的效果

vue实现简易流程图_第1张图片

总体的思路是,定义一个变量,通过循环该变量来渲染流程图。然后将该流程图文件封装成一个组件,父组件只需要按照要求格式定义好变量结构和值,然后传值给子组件。
父组件传值变量结构如下所示:

process: [
    {
        num: 1, // 区块个数
        list: [
            {
                class_name: 'blue', // 区块背景及文字颜色
                label: '应用名称', // 区块名称
                width: '8%', // 区块宽度
                clear: 'before' // 是否清楚伪类 伪类类型:before/after
            }
        ]
    },
    {
        num: 1,
        list: [
            {
                class_name: 'blue',
                label: '1.服务器、域名',
                width: '8%',
                clear: 'before',
                id: 'point-server',
            }
        ]
    }
]

如上process为要定义的变量,该变量为对象类型,每一个值为对应图1的一行,一行多个值的话,需要在list增加多个数据。
process变量结构含义:

process: [
	{
		num: // 代表当前区块数量,及一行要展示小方块的数量
		list: [
			{ // 定义区块内容
				class_name: // 代表区块的样式-可选,目前可选值:blue\grey,
				label: //区块名称
				width: // 区块宽度-可选,
				clear: // 是否清除当前组件伪类,区块上下线条为伪类实现,清除对应伪类,该线条就不展示了-可选,目前可选值:before\after
				id: // 点击区块跳转到页面相应位置,id为该锚点的ID-可选
 			}
		]
	}
]

具体实现的代码如下所示:

<template>
    <div class="process">
        <div class="process_box">
            <el-row
                v-for="(row, index) in process"
                :key="index" class="process_list"
                :ref="(row.num != 1 ? 'ref_' + getRandom()  : null)"
            >
                <div
                    v-if="(row.num != 1)"
                    :class="[(row.num != 1 ? 'row_line' : ''), row.unset_border]"
                >
                div>
                <div
                    v-for="(item, key) in row.list"
                    :key="key" :style="{width: item.width}"
                    :class="[
                        item.class_name,
                        'box_li',
                        (item.clear == 'before' ? 'clear_before' : (item.clear == 'after' ? 'clear_after' : ''))
                        ]"
                >
                    {{item.label}}
                div>
            el-row>
        div>
    div>
template>

<script>
    export default {
        name: "Process",
        data() {
            return {
                process: [
                    {
                        num: 1, // 区块个数
                        list: [
                            {
                                class_name: 'blue', // 区块背景及文字颜色
                                label: '应用名称', // 区块名称
                                width: '8%', // 区块宽度
                                clear: 'before' // 是否清楚伪类 伪类类型:before/after
                            }
                        ]
                    },
                    {
                        num: 1,
                        list: [
                            {
                                class_name: 'blue',
                                label: '1.服务器、域名',
                                width: '8%',
                                clear: 'before',
                                id: 'point-server',
                            }
                        ]
                    },
                    {
                        num: 1,
                        list: [
                            {
                                class_name: 'blue',
                                label: '2.图片存储',
                                width: '8%',
                                clear: 'before',
                                id: 'point-file'
                            }
                        ]
                    },
                    {
                        num: 2,
                        unset_border: 'unset_bottom',
                        list: [
                            {
                                class_name: 'blue',
                                label: '3.提供包名',
                                width: '8%',
                                id: 'point-package'
                            },
                            {
                                class_name: 'blue',
                                label: '4.制作Logo',
                                width: '8%',
                                id: 'point-logo'
                            }
                        ]
                    },
                    {
                        num: 7,
                        list: [
                            {
                                class_name: 'blue',
                                label: '5.苹果开发者账号',
                                width: '8%',
                                id: 'point-ios'
                            },
                            {
                                class_name: 'blue',
                                label: '6.谷歌登录、支付',
                                width: '8%',
                                id: 'point-google'
                            },
                            {
                                class_name: 'blue',
                                label: '7.Fb登录、支付',
                                width: '8%',
                                id: 'point-facebook'
                            },
                            {
                                class_name: 'blue',
                                label: '8.腾讯企业邮箱',
                                width: '8%',
                                id: 'point-email'
                            },
                            {
                                class_name: 'blue',
                                label: '9.推送',
                                width: '8%',
                                id: 'point-push'
                            },
                            {
                                class_name: 'blue',
                                label: '10.启动图',
                                width: '8%',
                                id: 'point-start-photo'
                            },
                            {
                                class_name: 'blue',
                                label: '11.苹果税务信息',
                                width: '8%',
                                id: 'point-tax'
                            },
                        ]
                    },
                    {
                        num: 1,
                        list: [
                            {
                                class_name: 'blue',
                                label: 'APP资料已补齐',
                                width: '8%',
                                clear: 'after'
                            }
                        ]
                    },
                    {
                        num: 1,
                        list: [
                            {
                                class_name: 'blue',
                                label: '测试',
                                width: '8%',
                                clear: 'after'
                            }
                        ]
                    },
                    {
                        num: 1,
                        list: [
                            {
                                class_name: 'blue',
                                label: '上线',
                                width: '8%',
                                clear: 'after',
                            }
                        ]
                    }
                ]
            }
        },
        mounted() {
            let _this = this;
            this.$nextTick(() => {
                for (let ref in _this.$refs) {
                    if (_this.$refs[ref][0].$el.children == undefined) {
                        continue;
                    }
                    let _children = _this.$refs[ref][0].$el.children;
                    let widthArr  = [];
                    let leftArr   = [];
                    let lineObj;
                    let width;
                    let left;
                    for (let child in _children) {
                        if (typeof _children[child] != 'object') {
                            continue;
                        }
                        if (_children[child].className.indexOf('row_line') != -1) {
                            lineObj = _children[child];
                            continue;
                        }
                        widthArr.push(_children[child].clientWidth);
                        leftArr.push(_children[child].offsetLeft);
                    }
                    let firstWidth = widthArr.shift();
                    let endWidth   = widthArr.pop();
                    let firstLeft  = leftArr.shift();
                    let endLeft    = leftArr.pop();
                    width = (lineObj.clientWidth -((firstWidth + endWidth) / 2 + (lineObj.clientWidth - endLeft - endWidth) + firstLeft)) / lineObj.clientWidth;
                    left  = (firstLeft + firstWidth / 2 + 1) / lineObj.clientWidth;
                    lineObj.style.width = width * 100 + '%';
                    lineObj.style.left  = left * 100 + '%';
                }
            });
        },
        methods: {
            getRandom() { // 随机生成6位数,保持ref的唯一性
                let number = parseInt(Math.random() * 1000000);
                return number;
            },
            jumpId(id) {
                this.$emit('jump', id)
            }
        }
    }
script>

<style scoped>
    .process {
        background-color: #ffffff;
        box-shadow: 1px 1px 5px #F4F5F9;
        padding: 30px;
        margin: 30px;
    }
    .process_box {
        width: 100%;
        height: auto;
    }
    .process_list {
        width: 100%;
        display: flex;
        justify-content: space-between;
    }
    .box_li {
        height: 30px;
        line-height: 30px;
        font-size: 12px;
        border-radius: 3px;
        color: #999999;
        border: 1px solid #999999;
        cursor: pointer;
        text-align: center;
        text-decoration: none;
        position: relative;
        margin: 30px 0;
    }
    .row_line {
        width: 100%;
        height: 90px;
        position: absolute;
        border-top: 1px solid #b5b5b5;
        border-bottom: 1px solid #b5b5b5;
    }
    .unset_bottom {
        border-bottom: 0 !important;
    }
    .clear_before {
        margin-top: 0 !important;
    }
    .clear_before:before {
        content: '';
        height: 0 !important;
        background-color: unset !important;
    }
    .clear_after {
        margin-bottom: 0 !important;
    }
    .clear_after:after {
        content: '';
        height: 0 !important;
        background-color: unset !important;
    }
    .box_li:after {
        content: '';
        display: block;
        height: 30px;
        width: 0.1px;
        position: absolute;
        bottom: -31px;
        background-color: #b5b5b5;
        left: 50%;
        transform: translateX(-50%);
        -webkit-transform: translateX(-50%);
    }
    .box_li:before {
        content: '';
        display: block;
        height: 30px;
        width: 0.1px;
        position: absolute;
        top: -31px;
        background-color: #b5b5b5;
        left: 50%;
        transform: translateX(-50%);
        -webkit-transform: translateX(-50%);
    }
    .blue {
        color: #fff!important;
        background-color: #00a3ff !important;
        border: 1px solid #00a3ff!important;
    }
    .grey {
        background-color: #f2f2f2 !important;
        border: 1px solid #f2f2f2 !important;
    }
style>

你可能感兴趣的:(Vue,前端,vue)