当前位置: 首页 > article >正文

Vue Web开发(八)

1. VueWeb面包屑和tag的布局

  本章节完成VueWeb面包屑和tag的布局,并且与左侧菜单联系,涉及组件间通信。
在这里插入图片描述

1.1. 页面创建

  (1)首先我们先完成每个页面的路由,之前已经有home页面和user页面,缺少mail页面和其它选项下的page1和page2页面。在view文件夹下新建mail文件夹,新建index.vue,填充user页面的内容即可。在view下新建other文件夹,新建pageOne.vue和pageTwo.vue,页面内容简单填充即可。三个页面都要更改name属性,后面会用到,首字母大写。
在这里插入图片描述

  新建src/ciews/mail/index.vue

//src/ciews/mail/index.vue
<template>
	<div>网上商品页面</div>
</template>
<script>
	export default {
		name: 'mail',
		data() {
			return {}
		}
	}
</script>

  新建src/ciews/other/pageOne.vue

//src/ciews/other/pageOne.vue
<template>
	<div>网上PageOne页面</div>
</template>
<script>
	export default {
		name: 'PageOne',
		data() {
			return {}
		}
	}
</script>

  新建src/ciews/other/pageTwo.vue

//src/ciews/other/pageTwo.vue
//User.vue文件
<template>
	<div>网上PageTwo页面</div>
</template>
<script>
	export default {
		name: 'PageTwo',
		data() {
			return {}
		}
	}
</script>

  (2)配置路由:在路由主文件添加路由,路由位置在CommonAside的menu数组中保持偶一致。这里的name属性是小写,与上面不相同。

 // isCollapse: false,
                menu: [
                    {
                        id: 0,
                        path: "/home",
                        name: "home",
                        label: "首页",
                        icon: "s-home",
                        url: "Home/Home",
                    },
                    {
                        id: 1,
                        path: "/mail",
                        name: "mail",
                        label: "商品管理",
                        icon: "video-play",
                        url: "MailManage/MailManage",
                    },
                    {
                        id: 2,
                        path: "/user",
                        name: "user",
                        label: "用户管理",
                        icon: "user",
                        url: "UserManage/UserManage",
                    },
                    {
                        label: "其他",
                        icon: "location",
                        children: [
                            {
                                id: 3,
                                path: "/page1",
                                name: "pageOne",
                                label: "页面1",
                                icon: "setting",
                                url: "Other/PageOne",
                            },
                            {
                                id: 4,
                                path: "/page2",
                                name: "pageTwo",
                                label: "页面2",
                                icon: "setting",
                                url: "Other/PageTwo",
                            }
                        ],
                    },
                ]

  (3)为左侧导航栏其他模块二级菜单添加点击事件。为el-menu-item添加点击事件。

 <el-menu-item-group v-for="(subItem,subIndex) in item.children"
                                :key="subItem.path+''">
      <el-menu-item @click="clickMenu(subItem)" :index="subIndex.toString()">
              {{subItem.label}}
      </el-menu-item>
 </el-menu-item-group>

1.2. 面包屑功能

  (1)面包屑有数据记忆存储功能,每次点击导航栏后后记录选中的导航栏并列出。这里需要用到Vuex.Store,我们前面左侧导航栏的收起与展开同样使用到Vuex.Store,store可以看做是容器,里面有四个值,由State、Getters、Mutation、Actions这四种组成。在src/store下的tab.js文件,默认数据定义在state中,我们定义为一个数组tabsList,数组里有多个对象,但这里知识默认对象,对象里有四个属性,path、name、label、icon。currentMenu为一个临时变量,存储点击的tab。

// src/store/tab.js
    state: {
        isCollapse: false,
		//默认菜单面包屑
        tabsList: [{
			id: 0,
			path: "/home",
			name: "home",
			label: "首页",
			icon: "s-home",
			url: "Home/Home",
        }],
		//当前菜单面包屑
        currentMenu: null
    },

  (2)改变tabsList里的内容要用到Vuex.store的mutations。改变state数据的发都会以函数的形式写在mutations中,之后在页面调用即可。selectMenu函数接收两个参数,state和val,此时需要进行判断,当前点击的导航栏是不是首页,用name属性判断,判断传入的item.name是否等于‘home’,如果不是home,需要赋值val给currentMenu,这样currentMenu就会不断累加,最多为五个(首页、用户、商品、其他1、其他2)。此处还需要一个判断,判断当前点击的导航栏是是不是刚刚已经点击过来,点击过了不再进行累加,而是将面包屑跳转到点击过的那一个。这里用到findIndex()方法。判断item.name里是否有val.name。 有的话为1,无的话为-1,无的话那么使用push()方法将val累加到currentMenu。如果点击是‘home’的情况,currentMenu置空。

// src/store/tab.js
 //更改 Vuex 的store中的状态的唯一方法是提交mutations
    mutations: {
        collapseMenu(state) {
            state.isCollapse = !state.isCollapse
        },
        selectMenu(state, val) {
            if (val.name !== 'home') {
                state.currentMenu = val
                const result = state.tabsList
                    .findIndex(item => item.name === val.name)
                if (result === -1) {//不存在
                    state.tabsList.push(val)
                }
            } else {
                state.currentMenu = null
            }
        },
    }

  (3)在src/componentsCommonAside中调用currentMenu,并传入item,item实际就menu数组中的任一对象。

// src/componentsCommonAside.vue
 this.$store.commit('selectMenu',item)
// src/componentsCommonAside.vue
 /**
   * 一级、二级菜单点击事件
   * @param item
    */
    clickMenu(item) {
     //全局引用router跳转
     this.$router.push({
      // name: item.name //名字路由指引
              path:item.path//路径路由指引
       }).catch(e => {})
       this.$store.commit('selectMenu',item)
  },

  (4)更改CommonHeader.vue,使用element ui的面包屑元素。
在这里插入图片描述

//element ui官方案例:Breadcrumb,面包屑
<el-breadcrumb separator="/">
  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
  <el-breadcrumb-item>活动列表</el-breadcrumb-item>
  <el-breadcrumb-item>活动详情</el-breadcrumb-item>
</el-breadcrumb>

  我们需要进行数据渲染,渲染成动态数据,v-for循环tags,:key使用item.path识别。{{}}表示动态渲染数据。
  这里数据比较比较长,item–tags–tabsList–menu。tabsList里的数据也是menu动态加载进去的。

    <el-breadcrumb separator="/">
        <el-breadcrumb-item v-for="item in tags" :key="item.path" :to="{ path: item.path }">{{item.label}}</el-breadcrumb-item>
    </el-breadcrumb>

  (5)修改src/CommonHeader.vue
  src/CommonHeader.vue引入mapState,这个是vuex的辅助函数。

// src/CommonHeader.vue
 import { mapState } from 'vuex'

在computed属性中进行注入,这里起了一个别名tags。

  // src/CommonHeader.vue
  computed:{
      //当前组件需要的全局数据,映射为当前组件computed属性
     //数据注入
      ...mapState({
          tags:state => state.tab.tabsList
      })
  }

  (6)页面会根据面包屑进行,路由也会自行更改。
在这里插入图片描述
  VueWeb Element Ui面包屑示例下载

1.3. tag区域

  这个功能其实类似于面包屑,只是多了删除功能。使用element ui的tag组件。tag组件的close属性表示组件是否可以关闭。tag组件有两个触发事件click、close。分别是点击tag和删除tag。
在这里插入图片描述

 &emsp(1);tag组件为公共组件,在components下新建CommonTag.vue。v-for遍历tags,这里注意,首页tag是不能删除的,closable属性表示有删除按钮,后面可以附带条件。effect属性为主题(样式),表示为高亮显示。判断方法是根据路由地址和当前tag的名称是否一致,注意是route(不是router)一致则为dark(高亮),不一致为plain(白色)。添加改变tag事件和删除tag事件。这里用模块化,用函数实现。

//src/components/CommonTag.vue
<template>
	<div class="tabs">
		<el-tag v-for="(tag,index) in tags" :key="tag.name" :closable="tag.name !== 'home'"
			:effect="$route.name === tag.name ? 'dark' : 'plain'" @click="changeMenu(tag)"
			@close="handleClose(tag,index)" size="small">
			{{ tag.label }}
		</el-tag>
	</div>
</template>

  (2)渲染tag,同样需要用到tabsList,引入mapState,在computed属性中注入,注入为三个点(…),这里同样将tabsList赋值给tags,两个页面的tags互不干扰。

//src/components/CommonTag.vue
<script>
	import {mapState,mapMutations} from 'vuex'
	export default {
		name: 'CommonTag',
		data() {
			return {

			}
		},
		computed: {
			...mapState({
				tags: state => state.tab.tabsList
			}),

		},
		methods: {
			...mapMutations({
				close: 'closeTag'
			}),
			changeMenu()
			handleClose()
		},
	}
</script>

  (3)在src/views/Main.vue引入组件

// src/views/Main.vue
import CommonTag from "../src/components/CommonTag.vue";
export default {
  name: "Home",
  components: {
    CommonTag
  },

   注意在el-header和el-main之间,因为这个组件并不属于header也不属于main,所以在中间。

// src/views/Main.vue
<el-header>
   <common-header></common-header>
</el-header>
<common-tag></common-tag>
<el-main>
   <router-view></router-view>
</el-main>

   覆盖样式

// src/views/Main.vue
<style lang="less" scoped>
    .tabs{
        padding: 20px;
        .el-tag{
            margin-right: 15px;
            cursor: pointer;
        }
    }
</style>

   (4)接下来完成//src/components/CommonTag.vue点击事件个删除事件(重难点!!!),点击就是路由切换。methods里更改函数。

//src/components/CommonTag.vue
   changeMenu(item) {
        this.$router.push({name: item.name})
        console.log(name)
},

   (5)删除tag:
   删除tag也会删除对应的面包屑,面包屑对应的是state.tabsList。首先拿到tag的总长度,总长度减1就是我们当前选中的tag,赋值给length,判断length和index的长度进行比较,如果这两个值相等,那么就表示此时我们选中的tag是tag中的最后一项。首先判断tag.name与当前的路由是否一致,如果不一致,不需要额外操作,直接return,即高亮   在最后一个tag,删除的tag是非选中的tag,所以无需操作。
如果当前删除的tag是最后一个tag,那么高亮部分一个向左移动一格。如果当前菜单高亮才当在中间,并且你删除当前的菜单时,高亮显示向右移动一格。

//src/components/CommonTag.vue
            handleClose(tag,index){
                this.close(tag)
                const length = this.tags.length - 1
                if(tag.name !== this.$route.name){
                    return;
                }
                //高亮向左移动,这里视频代码错误,应该是上面不减1,下面减1.
                if(index === length){
                    this.$router.push({
                        name: this.tags[index].name
                    })
                }else{
                    this.$router.push({
                        name: this.tags[index - 1].name
                    })
                }
            }

   (5)此时在src/store/tab.js需要删除state下的tabsList,修改state必须使用mutations。因此需要在mutations中声明closeTag。

//src/store/tab.js
  closeTag(state,val){
      const result = state.tabsList.findIndex(item => item.name === val.name)
      state.tabsList.splice(result,1)
  }

在这里插入图片描述
   (6)在src/components/CommonTag.vue下调用mutations

//src/components/CommonTag.vue
import { mapState,mapMutations } from 'vuex'
            ...mapMutations({
                close:'closeTag'
            }),

   (7)在src/components/CommonTag.vue总体的script代码。

// src/components/CommonTag.vue
<script>
import { mapState,mapMutations } from 'vuex'
    export default{
        name:'CommonTag',
        data(){
            return{
 
            }
        },
        computed:{
            ...mapState({
                tags:state => state.tab.tabsList
        }) ,
 
        },
        methods:{
            ...mapMutations({
                close:'closeTag'
            }),
            changeMenu(item){
                this.$router.push({ name: item.name })
                console.log(name)
            },handleClose(tag,index){
                this.close(tag)
                const length = this.tags.length - 1
                if(tag.name !== this.$route.name){
                    return;
                }
                //高亮向左移动,这里视频代码错误,应该是上面不减1,下面减1.
                if(index === length){
                    this.$router.push({
                        name: this.tags[index].name
                    })
                }else{
                    this.$router.push({
                        name: this.tags[index - 1].name
                    })
                }
            },
 
        }
        
    }
</script>

  效果图
在这里插入图片描述

   VueWeb Tag示例下载


http://www.kler.cn/a/441073.html

相关文章:

  • 6.进程的使用方式
  • [HOT 100] 0003. 无重复字符的最长子串
  • MATLAB的数据类型和各类数据类型转化示例
  • 鸿蒙开发黑科技“stack叠层”替代customdialog
  • 基于Python的人工智能患者风险评估预测模型构建与应用研究(下)
  • Charles 4.6.7 浏览器网络调试指南:流量过滤与分析(六)
  • Android 写排行榜,顶部前三
  • 字符2
  • Group FLUX - Summary Essay of the Alpha Phase Problem
  • Next.js流量教程:如何在 Next.js 中添加结构化数据以生成丰富摘要(Rich Snippets)
  • 【现代服务端架构】传统服务器 对比 Serverless
  • 电机控制杂谈(23)——共模电压与轴电流
  • es 开启slowlog
  • UIP协议栈 TCP通信客户端 服务端,UDP单播 广播通信 example
  • 本地部署大模型QPS推理测试
  • sql中case when若条件重复 执行的顺序
  • 召回系统介绍
  • 【Elasticsearch】关键数据类型
  • 20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕
  • 蜂鸟视图的蜂鸟云开发者中心更新:JS SDK v3.1.8 与 微信小程序 SDK v3.1.8 全新上线!
  • 【mysql】row模式的主从架构中,删除无主键的表可能导致从库“夯住”或产生较大的同步延迟
  • JDK以及JRE
  • 三菱协议以及C#实现
  • 【十进制整数转换为其他进制数——短除形式的贪心算法】
  • 【kubernetes】kubectl get nodes报NotReady
  • iOS和安卓,怎样才能轻松实现文件互传?