使用 Vue 实现 Context-Menu 的思考与总结
栏目: JavaScript · 发布时间: 6年前
内容简介:项目是基于当时我的脑海中在思考了把所以,最后的做法就直接硬上了。
项目是基于 vux
做的,本想着偷懒直接在 vux
库翻组件用,但看了一圈下来,居然这么通用的组件在 vuex
中没有!接着又去翻开源的解决方案,看了几个库还算 ok,但此时前端小哥来了,说实现这个菜单不需要用到这么重的东西,直接写就行了。
当时我的脑海中在思考了把 context-menu
封装成一个 component
,通过数据配置的方式动态拓展菜单选项。但没想到前端小哥直接给我干了回来,没必要进行封装,这个组件对页面依赖性太强,就算封装完了下次也不一定能直接用,PM 的思路又这么清奇。
所以,最后的做法就直接硬上了。
实现
调整操作逻辑
该页面是一个通俗意义上的列表展示页,使用了 vux
的 swipeout
表单组件,给用户提供了侧滑操作,需要把原先写好的侧滑功能删除。
调整 UI
在调整 UI 的过程中我感到了 CSS 满满的恶意,当然说是这么说,但实际上还是因为太久没有用而导致的不够熟悉。非常费劲的终于调整了好了新 UI,此时已经过去了整整一天了,非常怀念 autoLayout
。
context-mune
在正式开始写之前,上文已经说了我一直在翻开源库,主要是不懂得如何下手去写。距离上一次写 vue
已经过去快两个月了,而且也没搞清楚如何写一个组件,所以中间有一段时间浪费在了这上。最后的解决思路让我感到意外:
<div class="more-menu-wrapper">
<ul v-show="item.showOption">
<li>更换分类</li>
<li>向上移动</li>
<li>移至顶部</li>
<li>取消收藏</li>
</ul>
</div>
复制代码
没想到使用无序列表就可以完成了~在 iOS 中,我会在 UITableView
和 UIStackView
中纠结。当然只有这样是不行的,当又调整了 UI 后,发现 ...
和 context-menu
“融合”在了一起,没有设计图中的“悬浮”效果,最后的解决方法是:
.more-wrapper {
/* ... */
position: absolute;
.more-menu-wrapper {
position: relative;
/* ... */
}
}
复制代码
当继续调整 CSS 时又发现 context-menu
的会被其父组件挡住, context-menu
的显示范围会限制于其父组件的显示高度,最后得知是 overflow
这个属性在最底层的父组件中设置了 overflow: hidden;
,删除掉,使其为默认的 visible
即可显示为 context-menu
高度溢出的效果。
事件绑定
UI 都调整完后开始绑定事件。因为只是改造 UI,并没有涉及到多少的新逻辑,所以很快的就写出了以下代码:
<ul v-show="item.showOption">
<li @click="moveItem(item)">更换分类</li>
<li @click="moveUp(item)">向上移动</li>
<li @click="setTop(item)">移至顶部</li>
<li @click="deleteItem(item)">取消收藏</li>
</ul>
复制代码
context-menu
的显示依赖 v-show
,当页面首次拉取到网络数据时, data
中对每个 listData
的 item
新增了 context-menu
显示隐藏的初始化标志位 item.showOption = false
,且在这四个入口方法中都控制了 item.showOption
的改变:
//...
moveUp(item) {
item.showOption = false;
// ...
}
//...
复制代码
刷新页面,很愉快的看到了 context-menu
的显示,但在点击菜单选项时没有任何反应!一开始以为是标志位的问题,但看来看去没有任何问题。
本来想去找前端小哥看一眼,但一直不在工位上,最后问了下同组的前端实习生,他认为是 item.showOption
字段在数据更新时没有加上,导致后续直接读取时不存在。
但我其实一直纳闷如果 item.showOption
字段数据不存在的话,那第一次的页面渲染实际上是有错误的。我们两个人看了一会也没发现具体是哪有问题,最后只能四处寻找前端小哥,没想到他已经被封闭起来做商业化了......
前端小哥在文件中加上了 debugger
进行调试,发现进入到 moveUp
等一类事件时虽然 item.showOption
被修改成功了,一旦出去事件周期外,又被改回去了。
最后发现,问题出在被 冒泡
到了父组件中,调用了 ...
所绑定的 onMore
事件中,而在 onMore
事件中 item.showOption = true
,所以实际上是执行了 context-menu
和 ...
的两者所绑定的事件。解决的方法是:
<ul v-show="item.showOption">
<li @click.stop="moveItem(item)">更换分类</li>
<li @click.stop="moveUp(item)">向上移动</li>
<li @click.stop="setTop(item)">移至顶部</li>
<li @click.stop="deleteItem(item)">取消收藏</li>
</ul>
复制代码
使用 @click.stop
来阻止冒泡事件。解决完问题后,前端小哥还好奇我做 iOS 怎么会不知道冒泡事件的问题,但实际上在 iOS 中跟前端的思路完全是反过来的。iOS 的事件响应链是逐级传递到子组件中,也就是向下传递,而不是像前端中的向上传递。所以在遇到这个问题时也就完全没有往冒泡的方面去思考。
触摸其它区域消失 context-menu
在 iOS 中,我会直接封装出一个带有 UIWindow
的组件。与 context-menu
有关的所有操作与主 window
没有任何关系,更别说事件穿透了。所以最终我的做法是多加了一个遮罩层,显示和隐藏的时机与 context-menu
的时机保持一致。
最后在我拿着最终的成果去找前端小哥复查时,他对这个做法不满意,还是觉得要使用 outside-click
的做法。也就是使用 js 中的事件代理,通过 e.targe
去判断。最后找到了可以使用
v-outside-click
进行。关于后续的细节就不展开了, v-outside-click
的使用也十分简洁。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Creative Curve
Allen Gannett / Knopf Doubleday Publishing Group / 2018-6-12
Big data entrepreneur Allen Gannett overturns the mythology around creative genius, and reveals the science and secrets behind achieving breakout commercial success in any field. We have been s......一起来看看 《The Creative Curve》 这本书的介绍吧!