Vue 2.x + Element后台模板开发教程(三)后台首页模板设计

源码下载地址:http://www.80cxy.com/Blog/ResourceView?arId=202012091714193847b2Euxl

最近在学习vue.js开发,想做个简单的管理系统,研究了很长时间,看了很多慕课网的视频教程,教程地址:https://www.imooc.com/new/course/list?c=vuejs,看完教程开始试着做项目,做到后台首页被几个问题困扰了很久。

1、后台模板,模板功能怎么实现,之前都是嵌套iframe,现在怎么处理呢?研究了两天,发现这里的控制使用子路由实现,vue在路由跳转时,跳转到子路由会保留父路由的页面内容。

2、从网上下载了很多代码,都没跑起来,左侧菜单都是动态的,都得配置接口程序。

3、vue后台模板路由也需要根据接口返回权限动态实现,如果访问地址路由里面没有跳转到404页面。

本文实现的后台模板只是静态页面,动态路由、动态菜单会随着学习逐步完善。

先看看效果图:

Vue 2.x + Element后台模板开发教程(三)后台首页模板设计

实现思路:先创建一个主模板文件,home.vue,然后顶部是一个组件header.vue,底部是一个组件footer.vue,左侧菜单栏是一个组件Sidebar.vue,还有个tags.vue组件用于管理打开页面,中间内容部分是一个<router-view></router-view>用于展示具体跳转的页面,新增完目录如下:

Vue 2.x + Element后台模板开发教程(三)后台首页模板设计

home页面代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

<template>

    <div class="wrapper">

        <v-head></v-head>

        <v-sidebar></v-sidebar>

        <div class="content-box":class="{'content-collapse':collapse}">

            <div class="content_wrapper">

                <v-tags></v-tags>

                <div class="content"style="flex:1;">

                    <div class="content_inner">

                        <transition name="move"mode="out-in">

                            <keep-alive :include="tagsList">

                                <router-view></router-view>

                            </keep-alive>

                        </transition>

                    </div>

                </div>

                <v-footer></v-footer>

            </div>

        </div>

    </div>

</template>

 

<style lang="scss"scoped>

    .content_wrapper {

        display: flex;

        flex-direction: column;

        height: 100%;

 

        .content_inner {

            //    background: #fff;

            height: 100%;

        }

    }

</style>

 

<script>

    importvHead from './Header.vue';

    importvSidebar from './Sidebar.vue';

    importvTags from './Tags.vue';

    importvFooter from './Footer.vue';

    importbus from './bus';

    export default{

        data() {

            return{

                tagsList: [],

                collapse: false

            }

        },

        components: {

            vHead,

            vSidebar,

            vTags,

            vFooter

        },

        created() {

            bus.$on('collapse', msg => {

                this.collapse = msg;

            })

 

            // 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。

            bus.$on('tags', msg => {

                let arr = [];

                for(let i = 0, len = msg.length; i < len; i++) {

                    msg[i].name && arr.push(msg[i].name);

                }

                this.tagsList = arr;

            })

        }

    }

</script>

1

2

3

4

5

6

7

8

9

10

11

12

    importvHead from './Header.vue';

    importvSidebar from './Sidebar.vue';

    importvTags from './Tags.vue';

    importvFooter from './Footer.vue';

    importbus from './bus';

 

components: {

            vHead,

            vSidebar,

            vTags,

            vFooter

        },

以上代码引用各个子组件。

Header.vue代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

<template>

    <div class="header">

        <!-- 折叠按钮 -->

        <div class="collapse-btn"@click="collapseChage">

            <i class="el-icon-menu"></i>

        </div>

        <div class="logo">孔子人才网后台管理系统</div>

        <div class="header-right">

            <div class="header-user-con">

                <!-- <marquee onMouseOver="this.start()"style="font-size:18px;padding-bottom:4px;width:100px;"scrollamount="1">{{getlev}}</marquee> -->

                <div style="font-size:18px;padding-bottom:4px;width:60px;">admin</div>

                <!-- 全屏显示 -->

                <div class="btn-fullscreen"@click="handleFullScreen">

                    <el-tooltip effect="dark":content="fullscreen?`取消全屏`:`全屏`"placement="bottom">

                        <i class="el-icon-rank"></i>

                    </el-tooltip>

                </div>

                <!-- 消息中心 -->

                <div class="btn-bell">

                    <el-tooltip effect="dark":content="message?`有${message}条未读消息`:`消息中心`"placement="bottom">

                        <router-link to="/tabs">

                            <i class="el-icon-bell"></i>

                        </router-link>

                    </el-tooltip>

                    <span class="btn-bell-badge"v-if="message"></span>

                </div>

                <!-- 用户头像 -->

                <div class="user-avator"><img src="../../assets/Images/img.jpg"></div>

                <!-- 用户名下拉菜单 -->

                <el-dropdown class="user-name"trigger="click"@command="handleCommand">

                    <span class="el-dropdown-link">

                        用户名<i class="el-icon-caret-bottom"></i>

                    </span>

                     

                    <el-dropdown-menu slot="dropdown">

                         

                        <a  href="https://github.com/merciqiao"target="_blank">

                            <el-dropdown-item>关于作者</el-dropdown-item>

                        </a>

                        <a href="https://github.com/merciqiao/merciqiao-vue"target="_blank">

                            <el-dropdown-item>项目仓库</el-dropdown-item>

                        </a>

                        <a href="/zanzhu"target="_blank">

                            <el-dropdown-item style="color:orange;">赞助作者</el-dropdown-item>

                        </a>

                        <el-dropdown-item divided  command="changeZh">切换中文</el-dropdown-item>

                        <el-dropdown-item command="changeEn">切换英文</el-dropdown-item>

                        <el-dropdown-item divided  command="loginout">退出登录</el-dropdown-item>

                    </el-dropdown-menu>

                </el-dropdown>

            </div>

        </div>

    </div>

</template>

<script>

    importbus from './bus';

    export default{

        data() {

            return{

                collapse: false,

                fullscreen: false,

                name: 'merciqiao',

                lev:'青铜级',

                message: 2

            }

        },

        computed:{

            username(){

                let username = this.$common.getSessionStorage('username');

                returnusername ? username : this.name;

            },

            getlev(){

         

                let levList = this.$common.getSessionStorage('lev',true);

                let lev='';

                if(levList){

                    for(var i=0;i<levList.length;i++){

                        lev+=levList[i].roleName;

                    }

                }

                

                returnlev ? lev : this.lev;

            }

        },

        methods:{

            // 用户名下拉菜单选择事件

            handleCommand(command) {

                if(command == 'loginout'){

                    this.$common.removeSessionStorage('token');

                    this.$router.push('/login');

                }

                elseif(command == 'changeZh'){

                    this.$i18n.locale = 'zh_CN';

                }

                elseif(command == 'changeEn'){

                    this.$i18n.locale = 'en_US';

                }

            },

            // 侧边栏折叠

            collapseChage(){

                this.collapse = !this.collapse;

                bus.$emit('collapse', this.collapse);

            },

            // 全屏事件

            handleFullScreen(){

                let element = document.documentElement;

                if(this.fullscreen) {

                    if(document.exitFullscreen) {

                        document.exitFullscreen();

                    } elseif(document.webkitCancelFullScreen) {

                        document.webkitCancelFullScreen();

                    } elseif(document.mozCancelFullScreen) {

                        document.mozCancelFullScreen();

                    } elseif(document.msExitFullscreen) {

                        document.msExitFullscreen();

                    }

                } else{

                    if(element.requestFullscreen) {

                        element.requestFullscreen();

                    } elseif(element.webkitRequestFullScreen) {

                        element.webkitRequestFullScreen();

                    } elseif(element.mozRequestFullScreen) {

                        element.mozRequestFullScreen();

                    } elseif(element.msRequestFullscreen) {

                        // IE11

                        element.msRequestFullscreen();

                    }

                }

                this.fullscreen = !this.fullscreen;

            }

        },

        mounted(){

            if(document.body.clientWidth < 1366){

                this.collapseChage();

            }

        }

    }

</script>

<style scoped>

    .header {

        position: relative;

        box-sizing: border-box;

        width: 100%;

        height: 70px;

        font-size: 22px;

        color: #fff;

        background-color: #07c4a8;

    }

    .collapse-btn{

        float: left;

        padding: 021px;

        cursor: pointer;

        line-height: 70px;

    }

    .header .logo{

        float: left;

        width:250px;

        line-height: 70px;

    }

    .header-right{

        float: right;

        padding-right: 50px;

    }

    .header-user-con{

        display: flex;

        height: 70px;

        align-items: center;

    }

    .btn-fullscreen{

        transform: rotate(45deg);

        margin-right: 5px;

        font-size: 24px;

    }

    .btn-bell, .btn-fullscreen{

        position: relative;

        width: 30px;

        height: 30px;

        text-align: center;

        border-radius: 15px;

        cursor: pointer;

    }

    .btn-bell-badge{

        position: absolute;

        right: 0;

        top: -2px;

        width: 8px;

        height: 8px;

        border-radius: 4px;

        background: #f56c6c;

        color: #fff;

    }

    .btn-bell .el-icon-bell{

        color: #fff;

    }

    .user-name{

        margin-left: 10px;

    }

    .user-avator{

        margin-left: 20px;

    }

    .user-avator img{

        display: block;

        width:40px;

        height:40px;

        border-radius: 50%;

    }

    .el-dropdown-link{

        color: #fff;

        cursor: pointer;

    }

    .el-dropdown-menu__item{

        text-align: center;

    }

</style>

footer.vue组件代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

<template>

  <footer>

      <div class="footer_content">

          <!-- 京ICP备18050367号-1qq群:73110051(无广告)

          {{$t("footer.title")}}-->

      </div>

       

  </footer>

</template>

<style lang="scss">

    footer{

        border-top:1px solid #ddd;

        flex: 00auto;

        .footer_content{

            width: 340px;

            margin: 0auto;

            text-align: center;

            line-height: 60px;

            height: 60px;

            color:#606266;

            .qq{

                font-size: 9px;

            }

        }

    }

</style>

Siderbar.vue组件代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

<template>

    <div class="sidebar">

        <el-menu class="sidebar-el-menu":default-active="onRoutes":collapse="collapse"background-color="#324157"

            text-color="#bfcbd9"active-text-color="#20a0ff"unique-opened router>

            <el-submenu index="1">

                <template slot="title">

                    <i class="el-icon-location"></i>

                    <span>导航一</span>

                </template>

                <el-menu-item-group>

                    <template slot="title">分组一</template>

                    <el-menu-item index="1-1">选项1</el-menu-item>

                    <el-menu-item index="1-2">选项2</el-menu-item>

                </el-menu-item-group>

                <el-menu-item-group title="分组2">

                    <el-menu-item index="1-3">选项3</el-menu-item>

                </el-menu-item-group>

                <el-submenu index="1-4">

                    <template slot="title">选项4</template>

                    <el-menu-item index="1-4-1">选项1</el-menu-item>

                </el-submenu>

            </el-submenu>

            <el-menu-item index="2">

                <i class="el-icon-menu"></i>

                <span slot="title">导航二</span>

            </el-menu-item>

            <el-menu-item index="3"disabled>

                <i class="el-icon-document"></i>

                <span slot="title">导航三</span>

            </el-menu-item>

            <el-menu-item index="4">

                <i class="el-icon-setting"></i>

                <span slot="title">导航四</span>

            </el-menu-item>

        </el-menu>

        <!--<el-menu class="sidebar-el-menu":default-active="onRoutes":collapse="collapse"background-color="#324157"

            text-color="#bfcbd9"active-text-color="#20a0ff"unique-opened router>

            <template v-for="(item,i) in menuList">

                <template v-if="item.subs&&item.subs.length">

                    <el-submenu :index="item.index":key="i">

                        <template slot="title">

                            <i :class="item.icon"></i><span slot="title">{{ item.title }}</span>

                        </template>

                        <el-menu-item v-for="(subItem,i) in item.subs":key="i":index="subItem.index">

                            {{ subItem.title }}

                        </el-menu-item>

                    </el-submenu>

                </template>

            </template>

        </el-menu>-->

    </div>

</template>

 

<script>

    importbus from './bus';

    import{

        mapGetters

    } from 'vuex'

    export default{

        data() {

            return{

                collapse: false,

                items: [{

                        icon: 'el-icon-setting',

                        index: 'index',

                        title: '系统首页',

                    },

                    {

                        icon: 'el-icon-tickets',

                        index: 'table',

                        title: '基础模块',

                        subs: [{

                                index: 'searchinput',

                                title: '查询输入页'

                            },

                            {

                                index: 'tabpage',

                                title: '标签选项卡'

                            },

                            {

                                index: 'tablepage',

                                title: '综合表格页'

                            },

                            {

                                index: 'formpage',

                                title: '表单页'

                            },

                            {

                                index: 'treepage',

                                title: '树组件页'

                            }

                        ]

                    },

                    {

                        icon: 'el-icon-setting',

                        index: '3',

                        title: '系统管理',

                        subs: [{

                                index: 'organizationTree',

                                title: '机构管理'

                            },

                            {

                                index: 'sysUser',

                                title: '用户管理'

                            },

                            {

                                index: 'sysRole',

                                title: '角色管理'

                            },

                            {

                                index: 'sysAcl',

                                title: '角色资源授权'

                            },

                            {

                                index: 'sysResource',

                                title: '资源管理'

                            },

                            {

                                index: 'sysMenu',

                                title: '菜单管理'

                            }

 

 

                        ]

                    },

                    // {

                    //     icon: 'el-icon-message',

                    //     index: 'tabs',

                    //     title: 'tab选项卡'

                    // },

                    // {

                    //     icon: 'el-icon-date',

                    //     index: '3',

                    //     title: '表单相关',

                    //     subs: [

                    //         {

                    //             index: 'form',

                    //             title: '基本表单'

                    //         },

                    //         {

                    //             index: 'editor',

                    //             title: '富文本编辑器'

                    //         },

                    //         {

                    //             index: 'markdown',

                    //             title: 'markdown编辑器'

                    //         },

                    //         {

                    //             index: 'upload',

                    //             title: '文件上传'

                    //         }

                    //     ]

                    // },

                    // {

                    //     icon: 'el-icon-star-on',

                    //     index: 'charts',

                    //     title: 'schart图表'

                    // },

                    // {

                    //     icon: 'el-icon-rank',

                    //     index: 'drag',

                    //     title: '拖拽列表'

                    // },

                    // {

                    //     icon: 'el-icon-warning',

                    //     index: 'permission',

                    //     title: '权限测试'

                    // },

                    {

                        icon: 'el-icon-error',

                        index: '404',

                        title: '404页面'

                    }

                ]

            }

        },

        computed: mapGetters({

            menuList: 'getMenuList',

            onRoutes() {

                returnthis.$route.path.replace('/', '');

            }

        }),

        created() {

            // 通过 Event Bus 进行组件间通信,来折叠侧边栏

            bus.$on('collapse', msg => {

                this.collapse = msg;

            })

        }

    }

</script>

 

<style scoped>

    .sidebar {

        display: block;

        position: absolute;

        left: 0;

        top: 70px;

        bottom: 0;

        overflow-y: scroll;

    }

 

    .sidebar::-webkit-scrollbar {

        width: 0;

    }

 

    .sidebar-el-menu:not(.el-menu--collapse) {

        width: 250px;

    }

 

    .sidebar>ul {

        height: 100%;

    }

</style>

Tags.vue组件代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

<template>

    <div class="tags"v-if="showTags">

        <ul>

            <li class="tags-li"v-for="(item,index) in tagsList":class="{'active': isActive(item.path)}":key="index">

                <router-link :to="item.path"class="tags-li-title">

                    {{item.title}}

                </router-link>

                 

                <span v-show="item.title!='系统首页'"class="tags-li-icon"@click="closeTags(index)"><i class="el-icon-close"></i></span>

            </li>

        </ul>

        <div class="tags-close-box">

            <el-dropdown @command="handleTags">

                <el-button size="small"type="primary">

                    标签选项<i class="el-icon-arrow-down el-icon--right"></i>

                </el-button>

                <el-dropdown-menu size="medium"slot="dropdown">

                    <el-dropdown-item command="other">关闭其他</el-dropdown-item>

                    <el-dropdown-item command="all">关闭所有</el-dropdown-item>

                </el-dropdown-menu>

            </el-dropdown>

        </div>

         

    </div>

</template>

 

<script>

    importbus from './bus';

    export default{

        data() {

            return{

                tagsList: []

            }

        },

        methods: {

            isActive(path) {

                returnpath === this.$route.fullPath;

            },

            // 关闭单个标签

            closeTags(index) {

                constdelItem = this.tagsList.splice(index, 1)[0];

                constitem = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];

                if(item) {

                    delItem.path === this.$route.fullPath && this.$router.push(item.path);

                }else{

                    this.$router.push('/');

                }

            },

            // 关闭全部标签

            closeAll(){

                this.tagsList = [{

                    name: "index",

                    path: "/index",

                    title: "系统首页"

                }];

                this.$router.push('/');

            },

            // 关闭其他标签

            closeOther(){

                constcurItem = this.tagsList.filter(item => {

                    returnitem.path === this.$route.fullPath;

                })

                this.tagsList = curItem;

            },

            // 设置标签

            setTags(route){

                constisExist = this.tagsList.some(item => {

                    returnitem.path === route.fullPath;

                })

                !isExist && this.tagsList.push({

                    title: route.meta.title,

                    path: route.fullPath,

                    // name: route.matched[1].components.default.name

                    name: route.name

                })

                bus.$emit('tags', this.tagsList);

            },

            handleTags(command){

                command === 'other'? this.closeOther() : this.closeAll();

            }

        },

        computed: {

            showTags() {

                returnthis.tagsList.length > 0;

            }

        },

        watch:{

            $route(newValue, oldValue){

                this.setTags(newValue);

            }

        },

        created(){

            this.setTags(this.$route);

        }

    }

 

</script>

 

 

<style lang="scss">

    $tag_height:34px;//tab高度变量

    .tags {

        position: relative;

        height: $tag_height;

        overflow: hidden;

        background: #fff;

        padding-right: 120px;

        flex: 00auto;

    }

 

    .tags ul {

        box-sizing: border-box;

        width: 100%;

        height: 100%;

    }

 

    .tags-li {

        float: left;

        margin: 3px 5px 2px 3px;

        border-radius: 3px;

        font-size: 12px;

        overflow: hidden;

        cursor: pointer;

        height: $tag_height - 8px;

        line-height: $tag_height - 8px;

        border: 1px solid #e9eaec;

        background: #fff;

        padding: 05px 012px;

        vertical-align: middle;

        color: #666;

        -webkit-transition: all .3s ease-in;

        -moz-transition: all .3s ease-in;

        transition: all .3s ease-in;

    }

 

    .tags-li:not(.active):hover {

        background: #f8f8f8;

    }

 

    .tags-li.active {

        color: #fff;

    }

 

    .tags-li-title {

        float: left;

        max-width: 80px;

        overflow: hidden;

        white-space: nowrap;

        text-overflow: ellipsis;

        margin-right: 5px;

        color: #666;

    }

 

    .tags-li.active .tags-li-title {

        color: #fff;

    }

 

    .tags-close-box {

        position: absolute;

        right: 0;

        top: 0;

        box-sizing: border-box;

        padding-top: 1px;

        text-align: center;

        width: 110px;

        height: $tag_height;

        background: #fff;

        box-shadow: -3px 015px 3px rgba(0, 0, 0, .1);

        z-index: 10;

    }

 

</style>

最后修改路由配置文件,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

constroutes = [{

        path: '/',

        name: 'Login',

        component: Login

    },

    {

        name: 'Home',

        path: '/Home',

        component: Home,

        meta: {

            title: '系统首页'

        }

    }

]

项目创建是用的vue cli3脚手架创建的。

以下是博主微信欢迎沟通交流。

Vue 2.x + Element后台模板开发教程(三)后台首页模板设计

以上是 Vue 2.x + Element后台模板开发教程(三)后台首页模板设计 的全部内容, 来源链接: utcz.com/a/73706.html

回到顶部