Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

  • TypeScript

  • Vue

  • ElementUI

    • 基于 ElementUI 封装的 TextEllipsis
    • 基于 ElementUI 封装的 Tree
    • 基于 ElementUI 封装的 Tree2
    • 基于 ElementUI 封装的 SelectTree
    • 基于 ElementUI 封装的 NumberInput
    • 基于 ElementUI 封装的基础 table 和 form
    • 基于 ElementUI 封装的 TreeTable
    • 基于 VuePress 搭建一个类似 ElementUI 的说明文档
    • el-tree 节点过滤加载对应子节点
    • 简单调试 node_modules 源码
    • ElementUI 问题集合
    • 树形表格更新后保持折叠状态
    • 开始和完成时间互相限制
  • React

  • AntD

  • 前端
  • ElementUI
Henry
2020-12-09

简单调试 node_modules 源码

最近在修改自己封装的组件 bug 时, 发现需要调试一下 ElementUI 源码, 就想着趁次机会记录一下如何简单调试 node_modules 的源码

由 bug 截图可知是由于调用 form 的 resetFields (重置) 方法触发的, 所以我们需要在源码中找到 resetFields 方法

在 node_modules/element-ui/packages/form/src/form.vue 中找到如下代码:

resetFields() {
  if (!this.model) {
    console.warn('[Element Warn][Form]model is required for resetFields to work.');
    return;
  }
  this.fields.forEach(field => {
    field.resetField();
  });
}
1
2
3
4
5
6
7
8
9

所以我们现在需要找 resetField 方法

在当前目录中的 form-item.vue 中找到如下代码:

resetField() {
  this.validateState = '';
  this.validateMessage = '';

  let model = this.form.model;
  let value = this.fieldValue;
  let path = this.prop;
  if (path.indexOf(':') !== -1) {
    path = path.replace(/:/, '.');
  }

  let prop = getPropByPath(model, path, true);

  this.validateDisabled = true;
  if (Array.isArray(value)) {
    prop.o[prop.k] = [].concat(this.initialValue);
  } else {
    prop.o[prop.k] = this.initialValue;
  }

  // reset validateDisabled after onFieldChange triggered
  this.$nextTick(() => {
    this.validateDisabled = false;
  });

  this.broadcast('ElTimeSelect', 'fieldReset', this.initialValue);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

由以上代码我们可以简单得知首先重置了提示信息及状态, 然后关闭验证: this.validateDisabled = true , 防止重置初始值时验证, 接着重置初始值, 在 $nextTick 中打开验证

再结合咱们自己封装的代码可以做如下推理: ElementUI 关闭验证并重置初始化, 并且使用 $nextTick 将打开验证放入队列中等待执行; 而在重置初始化后, 咱们组件同时 watch 到 value 改变, 从而执行 init 方法, 而 init 中调用了 $nextTick , 所以其实 init 中的处理也放到了队列中等待执行了, 但是是排在打开验证之后执行; 接着主线程执行完成, 执行队列中的任务, 由于打开验证在前, 所以先是打开验证, 再执行 init 中的处理, 而 init 中处理后调用了 emit 和 blur , 触发验证, 而此时是重置后的初始值(空串), 所以会出现必填提示

猜想如上, 接下来就需要验证一下了

首先在源码的 validateDisabled 改变后输出一下该值, 并在组件相应的地方输出一下, 简略代码如下:

源码 node_modules/element-ui/packages/form/src/form-item.vue

resetField() {
  // do something
  this.validateDisabled = true;
  console.log('this.validateDisabled', this.validateDisabled)
  // do something
  this.$nextTick(() => {
    this.validateDisabled = false;
    console.log('this.validateDisabled', this.validateDisabled)
  });
}
1
2
3
4
5
6
7
8
9
10

组件 SelectTree

watch: {
  value () {
    console.log(this.value, 'value')
    // 为了检测 v-model 的变化
    if (this.value + '' !== this.selectData + '') {
      console.log('value change')
      this.treeKey = Math.random()
      this.init()
    }
  }
},
methods: {
  init () {
    console.log('init')
    this.$nextTick(() => {
      if (this.isMultiple) {
        this.handleCheckChange()
      } else {
        this.handleCurrentChange()
      }
    })
  },
  emitBase () {
    console.log('emitBase')
    this.$emit('input', this.selectData)
    this.$emit('change', this.selectData, this.selectNode)
  },
  // 单选, 节点被点击时的回调, 返回被点击的节点数据
  handleCurrentChange () {
    // do something
    console.log('current change')
    // 由于只验证重置, 所以只保留以下部分代码
    const currentNode = this.$refs.tree.getCurrentNode()
    // 当前传入的值在 tree 中无法找到, 需要清空 select 值
    if (!currentNode) {
      this.selectData = ''
      this.selectNode = null
      if (this.isFirst) {
        this.isFirst = false
      } else {
        console.log('空串')
        this.emitBase()
        this.$refs.select.blur()
      }
      return
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

重启服务(改源码后必须重启服务) 后发现只有组件的输出, 并没用源码的输出, 难道是找错位置了吗?

no log

在网上查找后, 原来是要在 lib 中的源码输出: 在 vue 项目的 node_modules/element-ui 目录下加 console.log 打印, 为什么没有效果? - SegmentFault 思否 (opens new window)

因为你实际上使用的 element 组件是经过压缩编译过后的文件, 也就是 lib 文件夹中的文件. 所以你在 node_modules 文件夹下的 src 中的 console.log 没有作用.

在 node_modules/element-ui/lib/form-item.js 中添加输出并重启服务后, 发现还是没有输出

后经过微信群大佬指点:

你看看入口文件是哪个, 在那个文件里面加

终于在 package.json 中找到了: "main": "lib/element-ui.common.js"

在 node_modules/element-ui/lib/element-ui.common.js 中添加输出后终于看到结果了:

log

由上图输出可以看出和猜测的完全一致

至此本次愉快的调试之旅就结束了

什么? 你说问题还没有解决? 本次之旅只是负责调试并找到问题的原因, 并不提供解决方案; 如需解决方案, 你看看是不是开头漏了什么 ^_^

编辑 (opens new window)
#Js#ElementUI
上次更新: 5/27/2023, 1:02:05 PM
el-tree 节点过滤加载对应子节点
ElementUI 问题集合

← el-tree 节点过滤加载对应子节点 ElementUI 问题集合→

最近更新
01
version 1.15
07-01
02
version 1.14
06-27
03
version 1.13
06-27
更多文章>
Theme by Vdoing | Copyright © 2017-2023 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式