先说前提。

这是极其小几率出现的bug,并不影响一般的网页开发。只是谷歌内核开发的时候才会出现, 基本和前端关系不大。

我们公司有一个pc端的客户端,内嵌了一个谷歌的浏览器。 为了处理某些奇奇怪怪的需求、会按照某些规则屏蔽键盘事件。只有在当前focus可编辑的时候, 才可以使用backspace键这样子, 客户端研发那边使用谷歌的FocusOnEditableField 的API来识别当前的编辑状态

我在使用element重构项目之后,使用了el-select的远程查找、筛选功能,在这里 发现el-select组件全部无法触发FocusOnEditableField了。。。于是开始了dubug之旅。

这个api提到 当前focus的元素如果是可编辑状态,就返回true。这让我想起了dom里面很冷门的一个api

contenteditable 属性规定是否可编辑元素的内容。
复制代码

OK, 来试一下。 这里有几个api可以帮我测试一下

document.activeElement  获取当前文档中获得焦点的元素
dom.contentEditable  获取当前元素的contentEditable值
复制代码
  mounted () {document.onkeydown = function (e) {console.log(document.activeElement.contentEditable)}},
复制代码

但是实际打印出来的都是inherit, 看来contentEditable方法也和dom.style一样只能获得行内的值。 翻翻MDN 找到了这个apiisContentEditable 他可以获取计算之后的contentEditable的值。

OK。再来试试

  mounted () {document.onkeydown = function (e) {console.log(document.activeElement.isContentEditable)}},
复制代码

在select组建中测试返回false。OK。 我们直接通过修改dom属性的方式来看看是不是这个属性的问题。

  mounted() {if (this.$refs.elSelect.$children[0].$options.name === 'ElInput') {this.$refs.elSelect.$children[0].$refs.input.contentEditable = true}},
复制代码

组件加载出来之后,暴力的修改contentEditable属性。。 测试一下, 功能OK, 打完收工~。

当然不可能, 虽然实现了功能,但是有很多疑点啊。 原生的input和elemen库的input都可以正常使用, 应该还有更深层次的问题。。 没办法了, 看源码吧

从package里得知,element通过USE引入的组件都是从\node_modules\element-ui\lib\element-ui.common.js这里引入的。 package里的是未编译过的组件。 开始翻阅源码

然后一无所获。。

编译过的这个文件虽然可以打断点, 但是没有办法去看具体dom的绑定属性。

那就用更简单暴力的方式, 直接从页面上导入element未编译的组建。 node_modules/element-ui/packages/select/src/select.vue就是他了。 然后项目就挂了。这个组件还引入了其他组件, 其中有一部分使用了jsx。 再该环境太麻烦了。直接把和bug无关的代码全部干掉, 项目总算又跑起来了。

这样就清晰多了。。
来看看element的select组建, 涨姿势了。 compositionstart、 compositionupdate、compositionend这三个事件, 新姿势get~。
回归业务,继续找bug。

嗯~~~disabled、readonly这两个属性比较可疑啊。
删掉readonly果然就OK了。 看来问题出现在这里了。

再看看相关的代码

    // 点击父元素的时候toggleMenu() {if (!this.selectDisabled) {if (this.menuVisibleOnFocus) {this.menuVisibleOnFocus = false;} else {this.visible = !this.visible;}if (this.visible) {(this.$refs.input || this.$refs.reference).focus();}}},
复制代码
computed: {readonly() {// trade-off for IE input readonly problem: https://github.com/ElemeFE/element/issues/10403const isIE = !this.$isServer && !isNaN(Number(document.documentMode));return !this.filterable || this.multiple || !isIE && !this.visible;},
}
复制代码

逻辑就应该是, 点击父元素的时候, 更改visible的值, 然后通过计算属性计算出readonly, 然后通过v-bind来修改dom的属性。

看来找到原因了,看起来这个操作是同步事件, 实际上dom的更新是异步事件。
而谷歌的FocusOnEditableField逻辑应该是, 有元素进入focus->检查该元素的readonly、contentEditable等属性。
而实际上呢。修改了 readonly -> 调用focus事件 这里并不是同步的, input在只读状态进入了focus。 所以无法触发FocusOnEditableField事件了。
具体的可以参考Vue.nextTick方法
写个demoe来试试

    <div style="width: 300px;height: 300px;background-color: pink" @click.stop="toggleMenu"><input ref="input" type="text" :readonly="readonly"></div>
复制代码
data () {return {readonly: true}},methods: {toggleMenu() {this.readonly = falseconsole.log(this.$refs.input.readOnly )},}
复制代码

嗯~果然。第一次点击的时候打印的是true。在改一下

    toggleMenu() {this.readonly = falsethis.$nextTick(() => {console.log(this.$refs.input.readOnly)this.$refs.input.focus()})},复制代码

总算找到了问题的原因。

望着桌子上的头发, 这波不亏。

ps: 最近在翻阅element的源码, 收获颇丰。element封装的dispatch方法、broadcast方法也给我以后处理vue组建提供了灵感。感谢大佬们的无私奉献。

纪念逝去的头发--一次debug经历相关推荐

  1. Impala-shell卡顿分析——记一次曲折的Debug经历

    Impala-shell卡顿分析--记一次曲折的Debug经历 问题发现 最近准备在Impala中增加对UTF-8的支持,以修正跟Hive.Spark等基于Java的系统在UTF-8字符串上的不兼容表 ...

  2. 谨以此文纪念逝去的SUN

    谨以此文纪念逝去的SUN        此图转载自Java之父james gosling的blog  http://blogs.sun.com/jag/entry/so_long_old_friend ...

  3. 两次深度debug经历,希望大家不要踩坑

    深度学习模型debug目前来看,还是一个难点问题.pytorch能够有这样的发展势头,容易debug应该是一个突出优点.本篇文章记录一下笔者使用tensorflow时两次debug的经历,希望能给大家 ...

  4. 【pytorch】 grad、grad_fn、requires_grad()、with torch.no_grad() 、net.train()、net.eval():记录一次奇怪的debug经历

    刚开始接触pytorch框架时,最让我觉得神奇的就是它居然可以–自 动 求 导 ! 于是我开始尝试理解内部的运行机制,但很快放弃了,直接当成黑盒使用-- 最近又遇到一个奇怪的bug,让我不得不去学一下 ...

  5. 记一次ssh免密登录失败的debug经历

    1. 问题 设置ssh免密登陆时,发现有一些机器正常登陆,有一些机器提示错误信息:public-key authentication with the server for user gzsun fa ...

  6. 英语总结——纪念逝去的时光

    微微的一阵风略过, 心底荡起一丝丝的痛, 掐指算来,       我逃到这里混混愕愕已过了两个月.       逝去的岁月犹如门前那棵银杏的果子,      有辛酸,有苦涩,还有一种疲惫,       ...

  7. 纪念逝去的岁月——C/C++选择排序

    选择排序 代码 #include <stdio.h>void printList(int iList[], int iLen) {int i = 0;for(i = 0; i < i ...

  8. 纪念逝去的岁月——C/C++字符串反转

    几年前,我还不会写这个 输入:hello world 输出:dlrow olleh 代码 1 #include <stdio.h> 2 #include <string.h> ...

  9. 纪念逝去的岁月——C/C++快速排序

    快速排序 代码 #include <stdio.h>void printList(int iList[], int iLen) {int i = 0;for(i = 0; i < i ...

最新文章

  1. 中国互联网+激光加工行业商业模式创新与投资机会深度研究报告
  2. [自定义区间-Range]书里的例子 - 中文数字类
  3. EnumMap的用法和源码解析
  4. 几种搜索引擎算法的研究
  5. php微信分享时好时坏,手机端微信分享前几天都是正常的今天发现分享出去就不正常了设置,迅睿CMS,CodeIgniter技术文档,PHP开发文档,迅睿CMS框架官方教程...
  6. npm中package.json详解
  7. Spring Boot中的@SpringBootConfiguration注释
  8. 【数据库】Mysql的CONCAT()函数拼接字符串
  9. 【数据分析就业实战】——缺失值的常见处理方法
  10. 怎么去掉网页上复制到word的文章中各种符号例如向下箭头(↓)?
  11. 正则匹配图片地址 php,php正则匹配图片地址
  12. python程序基本结构有哪三种_【Python基础】Python程序结构有哪些
  13. python通过http上传文件
  14. Windows XP Embedded下载
  15. 获取JSON文本(复嵌对象)转换指定JSON数据并Ajax实现数据初始可视化【附上echarts地图官方数据形式json文件数据】
  16. Linux安装显卡驱动后闪屏问题
  17. 形式化方法 | Proof Engineering for Predicate Logic——Coq tatics 在谓词逻辑证明中的应用
  18. 【PS | 学习】蛋黄酥海报制作
  19. TODA EMS(设备管理系统)简介
  20. SI(crosstalk)对common path的影响(CPPR)

热门文章

  1. SQL Server 2012 安装杂谈
  2. 深入python3 (Dive Into Python 3) 在线阅读与下载
  3. Scala的类和对象
  4. 论如何寻找万一的川财证券开户渠道
  5. Flink升级到1.4版本遇到的坑
  6. WPF第一章(XAML前台标记语言(Chapter02代码讲解))
  7. 十大厂商为什么要联合推出“快应用”对标小程序?
  8. queue 队列优先级
  9. [转载] Intention scheduling for BDI agent systems
  10. 公布硕士论文最新进展一(2007.3.6)