查看: 0|回复: 0

Vue在页面右上角实现可悬浮/隐藏的系统菜单 [复制链接]

匿名  发表于 2020-10-4 02:15:26

Vue在页面右上角实现可悬浮/隐藏的系统菜单

这是个大多数[dà duō shù]网站很常见[cháng jiàn]的功能,点击页面右上角头像显示一个悬浮菜单,点击页面其他[other]位置[wèi zhi]或再次点击头像则菜单隐藏。


dz论坛


作为一个jQuery前端攻城狮实现这个功能可以[ kě yǐ]说是很easy了,但是[dàn shì]对只刚粗看了一遍vue文档的菜鸟来说,坑还是要亲自踩过才算圆满。


知识点



      
  • 组件及组件间通信

  •   
  • 计算属性


正文


1. 父组件


这里暂时只涉及系统菜单这一个功能,因此[ yīn cǐ]路由暂未涉及。


基本思路是:通过props将showCancel这个Boolean值传递到子组件,对父子组件分别绑定事件,来控制这个系统菜单的显示状态。其中在父组件的绑定click事件中,将传入子组件的showCancel值重置。


这里就涉及第一个小知识点——子组件调用:


首先写好等待被子组件渲染的自定义元素:




<t-header :showCancel=showCancel></t-header>


接着import写好的子组件:




import THeader from "./components/t-header/t-header";


然后在组件中注册子组件:




components: {
THeader
}


到这里,新入坑的同学可能[would]会比较疑惑这几行代码是怎样把子组件对应到<t-header>标签的,官方文档是这样[then]说的:


当注册组件 (或者 prop) 时,可以[ kě yǐ]使用 kebab-case (短横线分隔命名)、camelCase (驼峰式命名) 或 PascalCase (单词首字母大写命名);


在 HTML 模板中,请使用 kebab-case;


我的理解是(举例),当自定义元素为<t-header>时,注册组件名可以[ kě yǐ]有三种写法:t-header、tHeader和THeader,在这种情况下注册的组件会自动识别并渲染到<t-header>。


需要注意[zhù yì]的是,以上使用的是HTML 模板,是在单文件组件里用<template><template/>指定的模板;另外存在一种[yī zhǒng]字符串模板,是用在组件选项里用template: "" 指定的模板。当使用字符串模板时,自定义标签可以[ kě yǐ]用三种写法,具体情况请移步官方文档 组件命名约定。


这样[then]父组件的雏形就诞生了:




<template>
<div  @click="hideCancel">
<t-header :showCancel=showCancel></t-header>
<!-- <router-view/> -->
</div>
</template>
<script>
import THeader from "./components/t-header/t-header";
export default {
name: "app",
components: {
  THeader
},
data() {
  return {
  showCancel: false
  };
},
methods: {
  hideCancel() {
  this.showCancel = false;
  }
}
};
</script>


2. 子组件


子组件中.cancel为打开系统菜单的按钮,.cancel-div为系统菜单,最开始[appeared]是这个样子:




<template>
<div >
/*这里是logo和title*/
...
/*这里是用户名和按钮*/
<div >
  <span >你好,管理[guǎn lǐ]员!</span>
  <span  @click.stop="switchCancelBoard">
  <div  v-show="showCancel">
   <ul>
   <li @click.stop="doSomething" title="用户设置">设置 </li>
   <li @click.stop="doSomething" title="退出登录">退出 </li>
   </ul>
  </div>
  </span>
</div>
</div>
</template>


按照踩坑之前的思路,在子组件接到showCancel值后用v-show控制显示隐藏,那么在父子组件的绑定click事件中只需要根据情况更改showCancel值就可以[ kě yǐ]了,只要注意[zhù yì]对系统菜单内几个选项的绑定事件不要[压嘛碟]触发父子组件上的绑定事件——总不能一点菜单它就没了,所以在绑定事件中用到了.stop,即

@click.stop="doSomething"


于是万事大吉,也就是像这样[then]




<script>
export default {
props: {
  showCancel: {
  type: Boolean
  }
},
methods: {
  doSomething() {},
  switchCancelBoard() {
  this.showCancel = !this.showCancel;
  }
},
computed: {
  ifShowCancel() {
  return this.showCancel;
  }
}
};
</script>


然而[however]第一波踩坑之后一起[yī qǐ]表明显然我还是太年轻。下面是一些[yī xiē]不好的示范:


prop来的showCancel值的确可以[ kě yǐ]用,点击子组件按钮的时候[When]


this.showCancel=!this.showCancel


实现了菜单的显示/隐藏,但是[dàn shì]一打开控制台,每次点击贡献了一条报错:



vue.esm.js?efeb:578 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop"s value.



意思是:避免修改prop值,因为父组件一旦re-render,这个值就会被覆盖;


另外,尽管在这个按钮上实现了显示状态的切换,但是[dàn shì]点击其他[other]区域[qū yù]时候[When],并不会隐藏它,原因是:子组件prop值的变化并没有影响[yǐng xiǎng]到父组件,因此[ yīn cǐ]showCancel的值一直保持初始值没有变化,而只有在这个值被更新时才会触发子组件中相关值的更新。


——好吧,那么老老实实的用一个计算属性接收showCancel值,这样[then]实现点击子组件控制系统菜单的状态切换;


获得了计算属性ifShowCancel,组件相应的变成了v-show="ifShowCancel",我试图在绑定事件里通过this.ifShowCancel=!this.ifShowCancel切换菜单状态,报错,得到报错信息:Computed property "ifShowCancel" was assigned to but it has no setter;


明白了,要以直接赋值的形式[form]改变计算属性ifShowCancel的值,需要一个setter函数,但是[dàn shì]setter函数中无法[to be]修改prop值,因此[ yīn cǐ]在getter中也就无法[to be]通过return this.showCancel来更新这个计算属性,所以这个方法貌似也行不通;


到此为止,好像路都成了堵死状态:prop值不能改->要用计算属性;计算属性不能改->需要setter;而写入了getter、setter,计算属性的值依赖于prop值->prop值不能改。——一个堪称完美的闭环诞生了!


走投无路之际我想起了$emit和$on这一对。


3. 父子互相通信


前边的prop实现了从父到子的单向通信,而通过$emit和$on,就可以[ kě yǐ]实现从子组件到父组件的通信:这不能直接修改父组件的属性,但却可以[ kě yǐ]触发父组件的指定绑定事件,并将一个值传入父组件。


在这一步我摒弃了点击按钮时的去操作子组件内属性的想法,既然计算属性ifShowCancel依赖于prop值,那么就在点击按钮时,通过$emit触发父组件的事件,并将需要修改的属性值传入父组件,于是:




/*父组件自定义元素绑定switch-show事件*/
<t-header :showCancel=showCancel @switch-show="switchShow"></t-header>
// 父组件js
methods: {
//会被子组件$emit触发的方法
switchShow(val) {
this.showCancel = val;
}
}
// 子组件js
methods: {
//按钮上的绑定click事件
switchCancelBoard() {
this.$emit("switch-show", this.ifShowCancel);
}
}


这样[then]处理流程[process]就变成了:点击按钮->作为计算属性的ifShowCancel值传入父组件并触发父组件事件,对showCancel赋值->父组件属性更新->触发子组件prop更新->触发重新compute,更新ifShowCancel值->v-show起作用。

另外在点击其他[other]区域[qū yù]时,通过父组件绑定的click事件,就可以[ kě yǐ]重置showCancel值,进而隐藏掉出现[chū xiàn]的系统菜单。


下边放出这个功能的完整代码。


4. 完整代码




/*父组件*/
<template>
<div  @click="hideCancel">
<t-header :showCancel=showCancel @switch-show="switchShow"></t-header>
<!-- <router-view/> -->
</div>
</template>
<script>
import THeader from "./components/t-header/t-header";
export default {
name: "app",
components: {
  THeader
},
data() {
  return {
  showCancel: false
  };
},
methods: {
  hideCancel() {
  this.showCancel = false;
  },
  switchShow(val) {
  this.showCancel = val;
  }
}
};
</script>
<style scope lang="stylus">
</style>
/*子组件*/
<template>
<div >
<div >
  <div ></div>
  <h2 >Title</h2>
</div>
<div >
  <span >你好,管理[guǎn lǐ]员!</span>
  <span  @click.stop="switchCancelBoard">
  <div  v-show="ifShowCancel">
   <ul>
   <li @click.stop="doSomething" title="用户设置">设置 </li>
   <li @click.stop="doSomething" title="退出登录">退出 </li>
   </ul>
  </div>
  </span>
</div>
</div>
</template>
<script>
export default {
props: {
  showCancel: {
  type: Boolean
  }
},
methods: {
  doSomething() {},
  switchCancelBoard() {
  // this.ifShowCancel = !this.showCancel;
  this.$emit("switch-show", !this.ifShowCancel);
  }
},
computed: {
  ifShowCancel() {
  return this.showCancel;
  }
}
};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>
.header-wrapper
background: #1C60D1
color: #fff
width: 100%
height: 50px
line-height: 50px
position: fixed
top: 0px
left: 0px
font-size: 0
.title-wrapper
  display: block
  position: relative
  float: left
  height: 50px
  .logo
  display: inline-block
  background-image: url("./logo.png")
  background-size: 30px 30px
  background-repeat: no-repeat
  width: 30px
  height: 30px
  margin-top: 10px
  .title
  display: inline-block
  font-size: 16px
  height: 50px
  line-height: 50px
  margin: 0px auto 0px 16px
  font-weight: normal
  vertical-align: top
.info-wrapper
  display: block
  position: relative
  float: right
  height: 50px
  width: 160px
  font-size: 0
  .username
  display: inline-block
  height: 50px
  line-height: 50px
  font-size: 14px
  vertical-align: top
  .cancel
  display: inline-block
  vertical-align: middle
  background-image: url("./cancel.png")
  background-size: 32px 32px
  cursor: pointer
  background-repeat: no-repeat
  width: 32px
  height: 32px
  .cancel-div
   position: absolute
   display: block
   width: 60px
   height: 80px
   background: #fff
   z-index: 50
   top: 40px
   right: 16px
   font-size: 14px
   color: #646464
   box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.4)
   ul
   padding-left: 0px
   margin: 0px
   li
    width: 100%
    height: 40px
    line-height: 40px
    text-align: center
    list-style-type: none
    &:hover
    background-color: #eaeaea
</style>


总结


以上所述是小编给大家介绍的Vue在页面右上角实现可悬浮/隐藏的系统菜单,希望[xī wàng]对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感[gǎn]谢大家对三亚游艇出租网站的支持[support]



地插太阳能景观灯,双俢小说全集,仪器分析比较类论文题目,山楂和蜂蜜水能减肥吗,电影txt免费下载,电影天堂 美丽密令,东莞三月天气预报,1080p电影下载,新能源汽车的试点政策,电影就是电影下载,36dj,长沙航空技术学校招生电话,昭君出塞电视剧,中式风格 装修,顶级瑞士手表复刻表,bt电影下载,谷歌翻译的发声,北海市铁山港2019征收范围,陕西有色新能源产业园,最新电影 下载,当北海舰队女兵好吗,安徽名人,澳门特色美食在哪条街,今日涟源天气预报,别墅装修清除甲醛,中老年长款羊毛衫女装,高清电影 下载,老电影保密局的枪声,带肉的玄幻小说1v1,办公室装修工程预算,酒店以前的装修翻新,最新电影下载,大码女装秋装新款毛衫,保险岗前培训课程表,北京名人摄影学校学费,无限今日天气插件,新开淘宝店要多少钱,淘宝客服回复,年终奖税率表,ck手表修理一般多少钱,崇文门特色美食,论文查重 自己的文章,翻译风波百度云,天堂电影下载,黑家传媒刘阔快手视频,伦理电影哪里可以看,节奏很快的女生英文dj,淘宝服装客服招聘,北海在地震2019年,学校食品安全与营养管理规定,南宁7号线地铁线路图 最新,pe袋环保标志,淘宝到货怎么退款,广西北海旅游 季节,电影毁灭迅雷下载,快手作品怎么添加歌曲,新房装修详细施工顺序,宁夏银川工商中职学校,最新电影下载,长治双语学校收费多少,中国美食教学反思部编,河北的钻石香烟价格表,信阳装修价格,
█主██跃██后██儿██益██十██人██赵██郁██帐██陟██集██设██联合式██祜██容██适██友█

1.年轻狂想法俩老夫妻某日吃晚饭时突发奇想:裸餐!找找从前的感觉!脱光后老太婆道:我还有反应耶!乳房还和年轻时一样发热!老头斜了一眼道:耷拉到汤里了!
2.各位段友们,我先问问。当年孙悟空大闹天宫,横扫千军万马,八路神仙。为什么跟了唐僧后连人家的坐骑都打不过?求不黑,正解!
3.生命是一个从生到死的过程,如果我们活着的目的只是为了探寻捷径,那么生下来就死,无疑是最快捷的路程。
4.估计现在还在找调宿舍一妹纸最近迷恋唱自编的《鲁冰花》:“天上的星星不说话,地上的xx叫呱呱~~”,然后把我们的名字填入其中。一天她又开唱,刚唱到天上的星星,我以迅雷不及掩耳之势豪迈地接了一句:参百斗啊!妹纸顿被噎住,估计现在还在找调……
5.生容易,活容易,生活,不容易。人很多,物很多,人物不很多。比如我。
6.当你见识到男人最好一面时,请不要爱上他,因为那不是全部。只有当你见到过他愤怒、沮丧、暴躁和孤独,才可以确定感情。许多人,总是以一个侧面来爱上人,所以她未来会失望,觉得对方变了一个人。但那反而是事实的全部。见到一个人最差的样子,却依旧能爱上,才是真爱。
7.以后沙子给煮烂点某日,和宿舍哥们去牛肉店开荤。席间,“咯嘣”一声,哥们突然咬到一粒不大不小的沙子。哥们爆怒,马上唤来服务员。哥们:“老板给我过来,太不像话了”我:“算了,没必要闹事了……”话还没说完,老板已经到了哥们:“以后沙子给煮烂一点……。”
8.恍恍惚惚间,发觉那份爱开始变质。
9.使人生不再遗憾的是经验。
10.聪明丈夫某夫妇当街而过,一只鸽子飞过天空,一泡鸽粪不偏不倚正巧落在太太肩上,太太急了,忙叫丈夫拿纸。丈夫抬头,见鸽子不讲卫生,到处拉屎,却不知妻子叫他拿纸干吗,说:叫我有啥办法,追上前去给它擦屁股呀!
11.Always use the proper name for things. Fear of a name increases fear of the thing itself.对事物永远使用正确的称呼。对一个名称的恐惧,会强化对这个事物本身的恐惧。
12.美女卷珠帘,深坐蹙蛾眉,但见泪痕湿,不知心恨谁。
13.读而未晓则思,思而未晓则读。——朱熹
14.挥手告别,扬帆远航,别不了的,是你抛出的那根友谊的缆绳,无形中牢牢地系在我心上。
15.如果你受苦了,感谢生活,那是它给你的一份感觉;如果你受苦了,感谢上帝,说明你还活着。人们的灾祸往往成为他们的学问。
16.燥热的三伏天里,为了让这条短信能给你带去一丝清凉,我特意把双手浸泡在加了冰和薄荷叶的水盆里,希望你接到短信时,能感受到冰的凉爽,薄荷的清香!

█主██跃██后██儿██益██十██人██赵██郁██帐██陟██集██设██联合式██祜██容██适██友█
转载请保留:http://www.discuz.kim/discuz-94895-1-1.html|点击下载本文Word文档



返回顶部

Discuz!

论坛,【www.discuz.link】
本站是 Discuz! 论坛社区产品的官方交流站点。
提供风格、模板、插件、产品扩展、技术支持等全方位服务。
Discuz! 论坛(BBS),是一个采用 PHP 和 MySQL 等其他多种数据库构建的性能优异、功能全面、安全稳定的社区论坛平台,
是全球市场占有率第一的社区论坛(BBS)软件。描述来自官方;
Copyright (C) 2001-2020 www.discuz.link, All rights reserved.

Powered by Discuz! X3.4 请勿发布违反法律法规的言论,会员观点不代表本站立场!
底部导航:Archiver|手机版| dz论坛