全国咨询热线:18720358503

微信小程序免费_Vue在页面右上角完成可悬浮/隐藏

类别:企业动态 发布时间:2021-01-08 浏览人次:

Vue在页面右上角实现可悬浮/隐藏的系统菜单       这篇文章主要介绍了Vue在页面右上角实现可悬浮/隐藏的系统菜单,实现思路大概是通过pro凡科抠图将showCancel这个Boolean值传递到子组件,对父子组件分别绑定事件,来控制这个系统菜单的显示状态。需要的朋友可以参考下

这是个大多数网站很常见的功能,点击页面右上角头像显示一个悬浮菜单,点击页面其他位置或再次点击头像则菜单隐藏。

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

知识点

组件及组件间通信 计算属性

正文

1. 父组件

这里暂时只涉及系统菜单这一个功能,因此路由暂未涉及。

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

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

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

 t-header :showCancel=showCancel /t-header 

接着import写好的子组件:

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

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

components: {
 THeader
}

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

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

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

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

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

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

 template 
 div id="app" @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为系统菜单,最开始是这个样子:

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

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

于是万事大吉,也就是像这样:

 script 
 export default {
 pro凡科抠图: {
 showCancel: {
 type: Boolean
 methods: {
 doSomething() {},
 switchCancelBoard() {
 this.showCancel = !this.showCancel;
 computed: {
 ifShowCancel() {
 return this.showCancel;
 /script 

然而第一波踩坑之后一起表明显然我还是太年轻。下面是一些不好的示范:

prop来的showCancel值的确可以用,点击子组件按钮的时候,

this.showCancel=!this.showCancel

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

vue.esm.js efeb:578 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever ponent re-renders. Instead, use a puted property based on the prop's value.

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

另外,尽管在这个按钮上实现了显示状态的切换,但是点击其他区域的时候,并不会隐藏它,原因是:子组件prop值的变化并没有影响到父组件,因此showCancel的值一直保持初始值没有变化,而只有在这个值被更新时才会触发子组件中相关值的更新。

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

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

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

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

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

3. 父子互相通信

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

在这一步我摒弃了点击按钮时的去操作子组件内属性的想法,既然计算属性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);
}

这样处理流程就变成了:点击按钮- 作为计算属性的ifShowCancel值传入父组件并触发父组件事件,对showCancel赋值- 父组件属性更新- 触发子组件prop更新- pute,更新ifShowCancel值- v-show起作用。
另外在点击其他区域时,通过父组件绑定的click事件,就可以重置showCancel值,进而隐藏掉出现的系统菜单。

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

4. 完整代码

/*父组件*/
 template 
 div id="app" @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 你好,管理员! /span 
 span @click.stop="switchCancelBoard" 
 div v-show="ifShowCancel" 
 li @click.stop="doSomething" title="用户设置" 设置 /li 
 li @click.stop="doSomething" title="退出登录" 退出 /li 
 /ul 
 /div 
 /span 
 /div 
 /div 
 /template 
 script 
 export default {
 pro凡科抠图: {
 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)
 padding-left: 0px
 margin: 0px
 width: 100%
 height: 40px
 line-height: 40px
 text-align: center
 list-style-type: none
 :hover
 background-color: #eaeaea
 /style 

总结

以上所述是小编给大家介绍的Vue在页面右上角实现可悬浮/隐藏的系统菜单,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对凡科网站的支持!


下一篇:没有了

推荐阅读

微信小程序免费_Vue在页面右上角完成可悬浮/隐藏

Vue在网页页面右上方完成可飘浮/掩藏的系统软件莱单 本文关键详细介绍了Vue在网页页面右上方完成可飘浮/掩藏的系统软件莱单,完成构思大约是根据pro凡科抠图将showCancel这一Boo...

2021-01-08
SEO是平庸还是高深

谢谢大伙儿关心《SEO是平凡還是深奥》话题讨论,搜易高新科技()投身公司企业网站建设、网络推广服务1六年,针对《SEO是平凡還是深奥》有自身独特的看法,期待能协助到大伙儿,一...

2021-01-08
中企动力1.18建站节增强用户体验 加速企业品牌更

您的部位: > 新闻报道新闻资讯 > 中企驱动力1.18建网站节提高客户感受 加快公司知名品牌更为制造行业打造出一个非常的传统节日,为公司产生一份独特的礼品,中企驱动力1.18建网站...

2021-01-08
小程序流程商城优点_详解webpack4多进口、多页面

详细说明webpack4多通道、多张面新项目搭建实例 本文关键详细介绍了详细说明webpack4多通道、多张面新项目搭建实例,网编感觉挺好的,如今共享给大伙儿,也给大伙儿做下参照。...

2021-01-08
不会网站建设怎么办-中山海腾注塑机企业网站建

中山市海腾注塑料机械技术专业生产制造生产厂家 企业是以市场销售及服务于一体的技术专业塑胶机械设备企业。往年来,伴随着 海达 知名品牌的持续提高和众多客户对海达塑料机械...

2021-01-08
怎样学会寻找你的意向用户?

由于这种人全是被你塑造好啦的,因此对你分享的內容都不会太过抵触,她们在大多数数状况下是会点一下进来收看的。除开经营新号以外,找寻一些群发消息和全自动加上的手机软件...

2021-01-08
X

400-8700-61718720358503
企业邮箱2639601583@qq.com
官方微信