coverPiccoverPic

调试 Vue 源码(v2)

方法

Vue 仓库把源码克隆一份到本地,然后安装pnmp,安装依赖。然后在 package.json 添加一行命令:

json
  1. "scripts": {
  2. "dev2": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:full-dev"
  3. }

npm run dev2跑起来就好了。

示例

我们可以修改 Vue 源码,会实时地编译到 dist/vue.js 中。像这样子,这里修改 src/compiler/create-compiler.ts 的createCompilerCreator函数,使得浏览器把模板编译结果输出到控制台:

ts
  1. export function createCompilerCreator(baseCompile: Function): Function {
  2. return function createCompiler(baseOptions: CompilerOptions) {
  3. function compile(
  4. template: string,
  5. options?: CompilerOptions
  6. ): CompiledResult {
  7. // ...
  8. const compiled = baseCompile(template.trim(), finalOptions)
  9. compiled.errors = errors
  10. compiled.tips = tips
  11. console.log(JSON.stringify(compiled, (() => {
  12. const seen = new WeakSet()
  13. return (key, value) => {
  14. if (typeof value === 'object' && value !== null) {
  15. if (seen.has(value)) {
  16. return '[Circular]'
  17. }
  18. seen.add(value)
  19. }
  20. return value
  21. };
  22. })(), 2));
  23. return compiled
  24. }
  25. return {
  26. compile,
  27. compileToFunctions: createCompileToFunctionFn(compile)
  28. }
  29. }
  30. }

然后在 html 文件引入 dist/vue.js,

html
  1. <script src="../../dist/vue.js"></script>
  2. <div id="demo"></div>
  3. <script type="text/x-template" id="template">
  4. <div>
  5. <div v-for="(item, index) in arr" @click="clickHandler">
  6. Current Value is {{ item }}
  7. </div>
  8. </div>
  9. </script>
  10. <script>
  11. const { ref } = Vue
  12. new Vue({
  13. name: 'Test',
  14. template: '#template',
  15. setup(props) {
  16. const arr = ref([
  17. 1, 1, 4, 5, 1, 4
  18. ])
  19. const clickHandler = () => {}
  20. return {
  21. arr, clickHandler
  22. }
  23. }
  24. }).$mount('#demo')
  25. </script>

我们来看浏览器控制台:

json
  1. {
  2. "ast": {
  3. "type": 1,
  4. "tag": "div",
  5. "attrsList": [],
  6. "attrsMap": {},
  7. "rawAttrsMap": {},
  8. "children": [
  9. {
  10. "type": 1,
  11. "tag": "div",
  12. "attrsList": [
  13. {
  14. "name": "@click",
  15. "value": "clickHandler",
  16. "start": 44,
  17. "end": 65
  18. }
  19. ],
  20. "attrsMap": {
  21. "v-for": "(item, index) in arr",
  22. "@click": "clickHandler"
  23. },
  24. "rawAttrsMap": {
  25. "v-for": {
  26. "name": "v-for",
  27. "value": "(item, index) in arr",
  28. "start": 15,
  29. "end": 43
  30. },
  31. "@click": "[Circular]"
  32. },
  33. "parent": "[Circular]",
  34. "children": [
  35. {
  36. "type": 2,
  37. "expression": "\"\\n Current Value is \"+_s(item)+\"\\n \"",
  38. "tokens": [
  39. "\n Current Value is ",
  40. {
  41. "@binding": "item"
  42. },
  43. "\n "
  44. ],
  45. "text": "\n Current Value is {{ item }}\n ",
  46. "start": 66,
  47. "end": 105,
  48. "static": false
  49. }
  50. ],
  51. "start": 10,
  52. "end": 111,
  53. "for": "arr",
  54. "alias": "item",
  55. "iterator1": "index",
  56. "plain": false,
  57. "hasBindings": true,
  58. "events": {
  59. "click": {
  60. "value": "clickHandler",
  61. "dynamic": false,
  62. "start": 44,
  63. "end": 65
  64. }
  65. },
  66. "static": false,
  67. "staticRoot": false,
  68. "forProcessed": true
  69. }
  70. ],
  71. "start": 0,
  72. "end": 120,
  73. "plain": true,
  74. "static": false,
  75. "staticRoot": false
  76. },
  77. "render": "with(this){return _c('div',_l((arr),function(item,index){return _c('div',{on:{\"click\":clickHandler}},[_v(\"\\n Current Value is \"+_s(item)+\"\\n \")])}),0)}",
  78. "staticRenderFns": [],
  79. "errors": [],
  80. "tips": []
  81. }

就可以看到变化了。这就是 html 中模板编译的结果,ast就是模板的抽象语法树,render就是产生虚拟 DOM 的函数字符串。

0 条评论未登录用户
Ctrl or + Enter 评论
© 2023-2025 LittleRangiferTarandus, All rights reserved.
🌸 Run