2023.4 ElementUI源码-建设组件库文档

2023-02-07  本文已影响0人  wo不是黄蓉

大家好,我是wo不是黄蓉,今年学习目标从源码共读开始,希望能跟着若川大佬学习源码的思路学到更多的东西。

本文是为了学习组件库搭建思路而衍生的一篇文章,最近在思考搭建项目业务组件库,发现公司封装的命令也是基于vue2的,因此开始了学习ElementUI源码学习之路。

调试环境准备

package.jsonscripts中配置

"dev:sourcemap": "npm run bootstrap && npm run build:file && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.demo.js & node build/bin/template.js --sourcemap",

配置sourcemap就可以开启源码调试了,在项目中打好断点

1675863128642.png
入口文件 examples\entry.js

找到build\webpack.demo.js发现就是一些基础的webpack配置,查看webpack配置文件,发现入口为examples\entry.js

这正是一个vue项目,因此npm run dev就是启动一个vue项目,而上面build生成的那些文件,是运行时所需的一些配置

npm run dev首页内容

1675859002151.png

examples\components\header.vue页面导航部分代码,最终生成的路径:/zh-CN/component/installation

 <li class="nav-item">
    <router-link
      active-class="active"
      :to="`/${ lang }/component`">{{ langConfig.components }}
    </router-link>
  </li>

router-link的内容应该在路由配置表里面可以找到,从examples\entry.js可以找到路由配置相关信息

import VueRouter from 'vue-router';
import routes from './route.config';
Vue.use(VueRouter);
const router = new VueRouter({
  mode: 'hash',
  base: __dirname,
  routes
});

router配置来自examples\route.config.js

//这边import使用到的内容就是上节我们说的从npm run build中打包过来的内容
import navConfig from './nav.config';
const LOAD_MAP = {
  'zh-CN': name => {
    return r => require.ensure([], () =>
      r(require(`./pages/zh-CN/${name}.vue`)),
    'zh-CN');
  },
  'en-US': name => {
    return r => require.ensure([], () =>
      r(require(`./pages/en-US/${name}.vue`)),
    'en-US');
  },
};

const LOAD_DOCS_MAP = {
  "zh-CN": (path) => {
    return (r) =>
      require.ensure([], () => r(require(`./docs/zh-CN${path}.md`)), "zh-CN")
  },
  "en-US": (path) => {
    return (r) =>
      require.ensure([], () => r(require(`./docs/en-US${path}.md`)), "en-US")
  },
}
//组件懒加载-这边加载的是语言包下的导航类的组件
const load = function(lang, path) {
  return LOAD_MAP[lang](path);
};
//加载文档组件-这边加载的才是真正的组件
const loadDocs = function(lang, path) {
  return LOAD_DOCS_MAP[lang](path)
}
//注册路由
const registerRoute = (navConfig) => {
  let route = [];
  Object.keys(navConfig).forEach((lang, index) => {
    let navs = navConfig[lang];
    route.push({
      path: `/${ lang }/component`,
      redirect: `/${ lang }/component/installation`,
      component: load(lang, 'component'),
      children: []
    });
    navs.forEach(nav => {
      if (nav.href) return;
      if (nav.groups) {
        nav.groups.forEach(group => {
          group.list.forEach(nav => {
            addRoute(nav, lang, index);
          });
        });
      } else if (nav.children) {
        nav.children.forEach(nav => {
          addRoute(nav, lang, index);
        });
      } else {
        addRoute(nav, lang, index);
      }
    });
  });
  function addRoute(page, lang, index) {
      //判断是否是changelog,不是使用loadDocs加载组件
    const component = page.path === '/changelog'
      ? load(lang, 'changelog')
      : loadDocs(lang, page.path);
    let child = {
      path: page.path.slice(1),
      meta: {
        title: page.title || page.name,
        description: page.description,
        lang
      },
      name: 'component-' + lang + (page.title || page.name),
      component: component.default || component
    };

    route[index].children.push(child);
  }

  return route;
};
let route = registerRoute(navConfig);
export default route;

load函数,这个函数主要是让组件懒加载,LOAD_MAP[lang]返回的是一个函数,即

(name) => {
    return (r) =>
      require.ensure([], () => r(require(`./pages/zh-CN/${name}.vue`)), "zh-CN")
  }

调用LOAD_MAP[lang]这个函数,返回内容即

(r) =>require.ensure([], () => r(require(`./pages/zh-CN/${name}.vue`)), "zh-CN")

registerRoute函数会根据examples\nav.config.json这个json里面配置的内容为各种语言的映射,包括导航和菜单组织信息,将导航和菜单信息都提前配置好在这个文件中,后续组件导航就根据这个文件来生成的。

addRoute函数中,最终组件使用的是loadloadDocs来导入组件的,这两个的区别就是,load加载的组件是导航类的,这个可以在examples\pages\zh-CN中进行验证

1675862334888.png

loadDocs加载的组件是examples\docs\zh-CN

1675862386094.png

为什么这边加载的组件是md文件呢?

因为在build\webpack.demo.js中有这么一段配置,这个是用来解析md文件的loader,先将md文件解析成vue文件,再使用vue-loader解析vue文件,再进行展示页面

      {
        test: /\.md$/,
        use: [
          {
            loader: "vue-loader",
            options: {
              compilerOptions: {
                preserveWhitespace: false,
              },
            },
          },
          {
            loader: path.resolve(__dirname, "./md-loader/index.js"),
          },
        ],
      },
总结:

看一点头绪都没有的代码不妨先看降级的代码,比如我一开始是想学习element-plus源码的,但是新的结构让我觉得陌生,学习摸索大概有一两个星期,也就大概看了个架子,内心其实也是比较受打击的。

就像我之前说的,我不是一个学习技术特别厉害的人,因此学习跨度更大的代码让我提不起兴趣,想要逃避。但是我当我换成看element源码后完全不会有这样的感觉,即使有不太懂的,也可以在网上找到答案,解决我的疑惑。

上一篇 下一篇

猜你喜欢

热点阅读