iambigchen / elementUICY

0 stars 0 forks source link

尝试着自己实现elementUI #1

Open iambigchen opened 4 years ago

iambigchen commented 4 years ago

尝试着自己实现elementUI

需求分析

之前用elementUI写过很多的项目,只是单纯的拿来用。但是却没有想过是如何实现的,所以打算通过参照着官网的源码,从无到有的自己实现一下elementUI的部分功能。本文纯粹只是自己学习和个人总结使用

项目目录解析

本文用的是webpack进行代码打包,src目录下放的是核心源码,examples下是用vue-cli2构建的一个vue项目。打包后的文件放在lib文件夹下, 所以 package.json中的main指向了lib/index.js

项目搭建

  1. 在空文件夹下执行npm init初始化一个npm项目
  2. 新建一个src文件夹,并在该文件夹下新建index.js作为webpack的入口文件
  3. 在根目录下新建webpack.config.js作为webpack的配置文件
  4. webpack的配置也很简单,只是配置了入口文件和输出,输出到lib文件夹里。并且配置了babel-loadervue-loader, VueLoaderPlugin
  5. 新建examples文件夹,实时查看效果。在examples中使用vue-cli2脚手架新起一个项目。

HelloWorld

1.在src/components下新建一个helloworld文件夹,在该文件夹下,新建index.js和src文件夹。index.js作为这个组件的入口文件,而src里面放的才是该组件的主要实现代码

src/components/helloworld/index.js


// 引入vue组件
import helloworld from './src/main.vue'

// 为该组件添加一个install方法,用于vue extend helloworld.install = function(Vue, options) { // 将该组件挂载到vue的全局组件中 Vue.component(helloworld.name, helloworld) } export default header

>src/components/helloworld/src/main.vue
```js
// main.vue的写法和我们平时写一个vue组件写法一样
<template>
  <div>
    hello world
  </div>
</template>
<script>
export default {
  name: 'helloworld'
}
</script>

这里这样的目录结构,主要是为了按需引入所准备的。后面有会说明这样写的好处

编写入口文件index.js

src/index.js


import helloworld from './components/helloworld'

const components = [ helloworld ]

const install = function(Vue, options) { components.forEach(component => { Vue.component(component.name, component) }) }

export default { version: 1.0, install }

将compoents里的所有组件引入,并且暴露出一个公共的install方法。为什么在入口文件已经有了install方法,在各个单个组件也实现了各自的install方法呢?这里这样做的目的是实现这个ui库可以全量引入和按需引入两种不同引入方法。
`src/index.js`是全量引入的入口文件
`src/components/helloworld/index.js`是按需引入hellworld时的入口文件

#### 把例子跑起来
在我们的examples下,把组件引入并使用,查看是否符合要求

1. 先在根目录下执行`npm link`命令,这条命令是将该npm项目生成本地链接。这样我们就不需要将我们的项目发布到`npm`库才能使用了。方便了本地开发调试
2. 进入examples文件夹下,执行`npm link element-cy`指令。这样就相当于我们在本地安装了`element-cy`,只不过在node-modules里,`element-cy`的代码指向了我们本地的开发环境
3. 在`examples/main.js`中引入我们的ui库
```js
import ElementUI from 'element-cy';
...
Vue.use(ElementUI);
  1. 在某个vue文件中直接使用我们的helloworld组件
    <template>
    <div>
    <helloworld />
    </div>
    </template>

    这时起动examples的服务,在浏览器查看效果,发现我们的helloworld组件已经生效了

iambigchen commented 4 years ago

按需引入

之前的引入方式,是examples/src/main.js中,直接引入我们的ui库。这样的引入方式,是属于全部引入,如果我们不想全部引入,只是使用了该库的个别组件,那我们就需要按需引入的方式了。 按需引入的方法和element-ui一样,需要配合一个babel-plugin-component使用。

babel-plugin-component原理是

import { Button } from 'components'

to

var button = require('components/lib/button')
require('components/lib/button/style.css')

这里也就能看出来之前我们helloworld组件的目录为什么要那么设置了

配置我们examples下的babel-plugin-component插件

examples/.babelrc


{
...
"plugins": ["transform-vue-jsx", "transform-runtime", [
"component",
{
"libraryName": "element-cy",
"style": true,
"styleLibrary": {
"name": "theme-chalk/lib/", // same with styleLibraryName
"path": "[module].css",  // the style path. e.g. module Alert =>  alert/index.css
},
"libDir": "src/components"
}
]]
....
}
这里的配置和element-ui有些不同,因为我们修改了目录结构,所以路径指定也不同了

配置完插件后,就修改我们的main.js,使用按需引入的方式引入
>examples/src/main.js
```js
...
import {helloworld} from 'element-cy'
Vue.use(helloworld)
...