菜鸟读element源码一

440 阅读3分钟

文章写作原因

因为有看到索尼大佬的element源码阅读博客,怀着敬仰的心情拜读发现自己是个菜鸟,发现自己的知识是真的很薄弱😭,所以决心自己手动起来,边实现源码边读边记录。 我会将自己实践过程中的部分问题也放在文章中,希望大佬们能帮帮我这个菜鸟,拜谢。

模仿代码中均以el-test 替换el, 目的是为了边模仿边测试和el组件的效果对比

项目的构建过程

这是项目的主体结构

我把自己实现的element代码放在plugins文件夹下,因为目前刚刚开始,不太知道说element文件的放置有什么奥秘,所以就简单区分了一下项目结构。每个el-test-xxx分别代表当前实现的和正在实现的element组件,css中放置各自组件对应的css代码。这是因为有看到element的组件和样式文件是分开放的,组件在packages文件夹下当中,样式文件在lib/theme-chalk文件夹下。

提出疑问一

为什么element的文件会这样放置? 对我这个菜鸟而言,我觉得把css和vue放在同一个组件下不是更加的方便,尤其是在有如此多的组件,如果element的开发人员想要更改某些样式,那不是还要去lib下找好久?

/plugins/index.js 仿照element的index文件,导入所有的组件 index.js的代码现在如下

import ElTestRow from "./el-test-row/row.js"
import ElTestCol from "./el-test-col/col.js"

const components = [ElTestRow, ElTestCol]

export default function install(Vue){
  //注册组件
  components.forEach(component => {
    console.log(component)
    Vue.component(component.name, component)
  })
}

if(typeof window !== undefined && window.Vue) {
  console.log('using install')
}

和element的index有区别的地方在于 我们使用element的时候我们在main.js中需要

import ElementUI from 'element-ui';    
Vue.use(ElementUI);

我的实现需要如下方法引入

import install from '@/plugins/index.js'
install(Vue)

原因是因为在element的index中install方法如下

const install = function(Vue, opts = {}) {
  locale.use(opts.locale);
  locale.i18n(opts.i18n);

  components.forEach(component => {
    Vue.component(component.name, component);
  });
};

/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue);
}

按照我的理解,element中是检测了window.Vue是否存在,然后执行install方法,导入所有组件,但是在仿制过程中,我发现我的代码并没有执行install方法,我的index中

if(typeof window !== undefined && window.Vue) {
  console.log('using install')
}

并没有执行打印操作,所以需要在main中执行install方法

提出疑问二 (已解决于2919-06-29,答案见文章尾)

有没有大佬可以告诉我这是因为什么原因,我的console.log并没有执行, element是怎么执行了install方法?

总结

本篇算是开篇,以后会陆续更新,我会把自己学习的心得和疑惑都放出来,如果有解决方案我也会在后续的文章中说明。希望和大家一起学习。

疑问二 答案

Vue源码中对于Vue.use有过描述,Vue.use(xxx)会检测xxx中是否包含install方法,并执行。因此,plugins/inddex.js文件修改如下

const install = function (Vue){
  //注册组件
  components.forEach(component => {
    console.log(component)
    Vue.component(component.name, component)
  })
}

export default {
  install
}

在main.js中

import ElTestUI from '@/plugins/index.js'

// 导入组件
Vue.use(ElTestUI);

(以下内容来自一位头条大佬的解释)

并且 console.log未打印的原因并不是if未执行,在import的时候,if函数已经执行,但是因为使用了webpack并且是在nodes环境下运行的vue项目,node环境下并无window变量,因此不会执行。 if的本意是为了判断element库的使用是通过cdn方式还是通过es6语法编译而成,通过cdn引入的情况为了保证代码能够正常使用vue,需要暴露给window一个vue变量,此时if值为true,将执行if里的console