资讯专栏INFORMATION COLUMN

vue学习组件之路之menu导航菜单

el09xccxy / 1500人阅读

摘要:后面就是和定位弹出框一样类似的操作,在导航菜单里面我并没有这么做,后面会改成这样的吧。一些多层嵌套的位置问题,尚未完成。在显示的时候会有高度抖动的问题。里面给某些子组件添加样式用到了深度作用。

效果尽量仿着element做。
预览地址

组件之间的通信

 
        
          
          for Mac
           for Windows
             
        
          
            快速入门
            进阶配置
            多语言支持
                         
        
 
selected的传递

如图所示,关于(selected:被选中的那个item),在menu里面控制,通过watchChild“监听每个item”,一旦menu-item被点击便会触发

this.$emit("menuItemUpdate",this.name)

这里menu便会通过menu-item$emit$on实现数据的传递

watchChild(){
                this.items.forEach(vm=>{
                    vm.$on("menuItemUpdate",name=>{
                        this.$emit("update:selected",[name])
                    })
                })
            },

这里的this.items就是收集的每一个menu-item,这在一开始就已经完成了。
要用到依赖注入,这里面子组件menu-item都直接操作menudata,耦合度非常高。

//menu
 provide(){
          return {
              root:this
          }
        }
//menu-item
 inject:["root"],
        created(){
           this.root.addItem(this)
          //.........
        },

然后告诉menu-item你可以被选中了。updated钩子函数用作完成这个任务再适合不过了

 updated(){
           this.updateChild()
        },
 methods:{
     updateChild(){
              this.items.forEach(vm=>{
                  if(this.selected.indexOf(vm.name)>-1){
                      vm.selected = true
                  }else{
                      vm.selected = false
                  }
              })
          }
 }        
路径元素的收集

menu-item被选中时,触发tellParents函数,收集这条路径上所有父元素的name,把这个收集好的数据放到selectedArr里面。这个还可以用来高亮路径上的父元素。
在click的时候触发onClick函数

onClick(){
                //...........
                let subFather = this.$parent.$el.classList.contains("x-sub-menu") this.$parent.$el.classList.contains("x-sub-menu")
                let groupFather = this.$parent.$el.classList.contains("x-menu-item-group")
               //..........
                if(subFather||groupFather){
                 //.......
                    this.tellParents(this)
                   //.......
                }else{
                    //.......
                }

            },

tellParents递归调用自身来收集 name


 tellParents(that){
                if(that.$parent.$parent.$options.name==="x-sub-menu" ||that.$parent.$parent.$options.name==="x-menu-item-group"){
                    this.root.selectedArr.unshift(that.$parent.name)
                    this.tellParents(that.$parent)
                }else{
                    this.root.selectedArr.unshift(that.$parent.name)
                    console.log(this.root.selectedArr)
                }
            },

最后就是我希望在menu-item被选中后,可以关闭路径的所有弹出框popover
这同样需要一个递归遍历

childClosePopover(){
                if(this.$parent.$options.name==="x-sub-menu"){
                    this.open = false
                    this.$parent.childClosePopover()
                }
            },
自定义主题颜色的实现

参照了一下Menu Attribute。
这里的文字颜色和图标颜色是同步的,
hover的css效果和active的一样

text-color文字颜色 。

active-color被选中颜色。

back-ground-color正常背景色 。

active-back-ground-color被选中的背景色 。

数据传递

如图所示的紫色的路线,通过递归遍历通知menu树里面的每一个分支,改变颜色,是否垂直,disabled等等。
大部分添加的功能都在这条线上实现通信。

js控制颜色的更改
watch:{
            selected(){
                if(this.selected&&........{
                    this.$refs.item.style.backgroundColor = ........
                    this.$refs.item.style.color = .........
                    //...........
                }else{
                  //............
                }
            }
        }
弹出框的问题

element对弹出框的操作是以在body上添加子节点的方式。这样子最直接的就是避免了可能存在overflow:hideen的问题。
后面的定位只需要用js来完成就行了,还要考虑到scroll的问题。

最麻烦的地方在于动画过渡上,单纯的用css会有弹出框回到原点的问题。
这里就需要用到
javascript钩子。
官网在这上面的说的很明确,但是实现过程中也踩了一些坑

动画瞬间完成的问题,这在官网上的解释时只用JavaScript做过渡的时候(没用css)的情况下动画会瞬间完成,要使用done。之后试了并没有用。这里并不是只用JavaScript做过渡的。之后想了一下,既然beforeEnterenter瞬间就执行了,并没有动画的事件间隔,为什么不自己加一个 settimeout呢,问题就解决了,可能这种解决方法并不是很好。这里不用$nextTick的原因

  enter(el) {
    setTimeout(()=>{
      //.....
      })
    },

钩子中设置的一些额外的css属性要在afterEnter改回来啊,其中就例如overflow:hiddenheight,导致在vertical垂直面板上弹出框不会撑开父元素的问题。

 afterLeave(el){
              el.style.overflow = ""
              if(this.vertical){
                  el.style.height=""
              }
          },

后面就是和定位弹出框一样类似的js操作,在menu导航菜单里面我并没有这么做,后面会改成这样的吧。

 beforeEnter(el) {
                el.style.position= "absolute"
                el.style.transform=.......
                //.........
          },
  
   enter(el) {
             //......
          },
处理一些细枝末节的问题

hover触发和click触发

弹出框移出消失的时间控制和动画抖动。

高亮线条只在一级子组件中存在

menu-item-group组件的添加,其实只是作为一个中转站而已,无非是拷贝一些函数。

一些多层嵌套的位置问题,尚未完成。

遇到的一些css问题

横版里面active下面的亮条显示,一开始就是设置menu-item里面的border-bottom,因为同时设置了transition。在显示的时候会有高度抖动的问题。后来改用伪类完成,不过在自定义颜色的时候非常麻烦。这个方法也放弃了。最后只有在下面加一个div代替border-bottom作为高亮线条,方法虽然很蠢,但是有效。

scoped里面给某些子组件添加css样式用到了 /deep/深度作用。

简单的总结?

其实以这种显而易见的数据流作为基础,多增加一些功能无非是函数的添加和css的修改。找bug和维护也是相对比较轻松的。最后您如果觉得还不错的话,给我的项目一个star想必也是极好的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102852.html

相关文章

  • vue学习组件menu导航菜单

    摘要:后面就是和定位弹出框一样类似的操作,在导航菜单里面我并没有这么做,后面会改成这样的吧。一些多层嵌套的位置问题,尚未完成。在显示的时候会有高度抖动的问题。里面给某些子组件添加样式用到了深度作用。 效果尽量仿着element做。预览地址 组件之间的通信 showImg(https://segmentfault.com/img/remote/1460000018614516?w=788&h=...

    Vixb 评论0 收藏0
  • CSS学习笔记(九) 界面组件导航菜单

    摘要:为了让包围列表项,没有使用,而是使用了,是因为前者会导致后来添加到下拉菜单中的子菜单无法显示它们最终会显示在父元素的外面,结果会导致溢出而被隐藏。它与父元素之间的间隙,实际上下拉菜单中第一个链接的边框。 菜单由一组链接组成。用 HTML 中的列表元素(ul 或 ol)来分组链接不仅符合逻辑,而且即使没有额外的 CSS 也能适当显示链接的层次。默认情况下,由于列表(li)是块级元素...

    pingink 评论0 收藏0
  • CSS代码重构与优化

    摘要:代码重构的目的我们写代码时,不仅仅只是完成页面设计的效果,还应该让代码易于管理,维护。命名与备注命名是提高代码可读性的第一步,也是及其重要的一步。 写CSS的同学们往往会体会到,随着项目规模的增加,项目中的CSS代码也会越来越多,如果没有及时对CSS代码进行维护,CSS代码不断会越来越多。CSS代码交错复杂,像一张庞大的蜘蛛网分布在网站的各个位置,你不知道修改这行代码会有什么影响,所以...

    fou7 评论0 收藏0
  • CSS代码重构与优化

    摘要:代码重构的目的我们写代码时,不仅仅只是完成页面设计的效果,还应该让代码易于管理,维护。命名与备注命名是提高代码可读性的第一步,也是及其重要的一步。 写CSS的同学们往往会体会到,随着项目规模的增加,项目中的CSS代码也会越来越多,如果没有及时对CSS代码进行维护,CSS代码不断会越来越多。CSS代码交错复杂,像一张庞大的蜘蛛网分布在网站的各个位置,你不知道修改这行代码会有什么影响,所以...

    不知名网友 评论0 收藏0

发表评论

0条评论

el09xccxy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<