Создайте библиотеку компонентов Vue VV-UI с нуля

внешний интерфейс GitHub Vue.js Markdown

Предисловие:

Компонентизация интерфейса — одна из горячих тем сегодня, а также проблема, с которой мы часто сталкиваемся при разработке одностраничных приложений.Теперь у нас есть очень хорошо функционирующий Element-UI. Различные крупные производители также один за другим анонсировали XXX-UI с открытым исходным кодом. Но есть и некоторые проблемы, например, каждой компании могут потребоваться разные бизнес-компоненты, или мы хотим разработать собственную библиотеку компонентов, чтобы повысить управляемость компонентами. Итак, как мы это делаем? Вот запись процесса сборки библиотеки компонентов с нуля.На данный момент есть только несколько простых компонентов, но я тоже буду потихоньку обновлять и поддерживать.

Адрес проекта на гитхабе:github
Адрес демонстрации проекта:демо

1. Подготовка окружающей среды

Чтобы создать библиотеку компонентов, нам нужно подготовить ряд сред.Во-первых, нам нужно рассмотреть следующие вопросы:

  1. Как построить строительные леса
  2. Как спланировать структуру каталогов
  3. Как писать документацию

Во-первых, для среды скаффолдинга уже есть очень зрелый официальный скаффолдинг Vue, мы просто используем его.

# 全局安装 vue-cli
$ npm install --global vue-cli
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project
# 安装依赖,走你
$ cd my-project
$ npm install
$ npm run dev

Тогда давайте посмотрим на второй вопрос, как спланировать созданную нами структуру каталогов? Сначала нам нужен каталог для хранения компонентов и каталог для хранения примеров. Итак, нам нужно изменить структуру проекта, сгенерированную vue-cli:

.
...
|-- examples      // 原 src 目录,改成 examples 用作示例展示
|-- packages      // 新增 packages 用于编写存放组件
...
. 

В этом случае нам нужно внести некоторые коррективы в наш конфигурационный файл webpack: во-первых, изменить каталог, где исходная компиляция указывает на src, на examples, а во-вторых, для того, чтобыnpm run buildДля нормальной компиляции пакетов нам также нужно добавить еще один каталог компиляции для babel-loader:

{
   test: /\.js$/,
   loader: 'babel-loader',
   include: [resolve('examples'), resolve('test'), resolve('packages')]
}

Таким образом, мы создали простую структуру каталогов.
Далее нам нужно подумать о том, как писать документацию. Для написания документов, естественно, больше всего подходит уценка, так как же мы можем писать документы уценки под vue? Ответ, конечноvue-markdown-loader. Затем мы настроили соответствующую информацию о плагине в соответствии с документацией:

rules: [
   {
     test: /\.md$/,
     loader: 'vue-markdown-loader'
   }
 ]

Что ж, можно начинать пробовать писать документацию, создать новый test.md в директории example/docs.

# test
> Hello World

Также создайте новый маршрут, указывающий на наш файл md:

{
  path: '/test',
  name: 'test',
  component: r => require.ensure([], () => r(require('../docs/test.md')))
}

откройте наш браузерhttp://localhost:8080/#/testХа-ха, это действительно сработало. Не слишком радуйтесь.... Проблема еще позади: мы ожидаем, что документ не только скомпилирует markdown, но и лучше распознает демо-блок кода с одной стороны для демонстрации, с другой стороны, лучше всего отобразите демонстрационный код, например:

Итак, что нам нужно сделать? vue-mark-down определенно больше, чем это! Поэтому мы продолжили читать его документацию и обнаружили, что он на самом деле инкапсулируетmarkdown-it, который поддерживает опцию options. Таким образом, мы можем определить уникальные идентификаторы для нашей уценки, здесь я использую demo Определяет, где должен отображаться блок кода, поэтому мне нужно настроить параметр параметров:

const vueMarkdown = {
  preprocess: (MarkdownIt, source) => {
    MarkdownIt.renderer.rules.table_open = function () {
      return '<table class="table">'
    }
    MarkdownIt.renderer.rules.fence = utils.wrapCustomClass(MarkdownIt.renderer.rules.fence)
    return source
  },
  use: [
    [MarkdownItContainer, 'demo', {
      // 用于校验包含demo的代码块
      validate: params => params.trim().match(/^demo\s*(.*)$/),
      render: function(tokens, idx) {
        
        var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);

        if (tokens[idx].nesting === 1) {
          var desc = tokens[idx + 2].content;
          // 编译成html
          const html = utils.convertHtml(striptags(tokens[idx + 1].content, 'script'))
          // 移除描述,防止被添加到代码块
          tokens[idx + 2].children = [];

          return `<demo-block>
                        <div slot="desc">${html}</div>
                        <div slot="highlight">`;
        }
        return '</div></demo-block>\n';
      }
    }]
  ]
}

Вот краткое описание того, что делает этот код: во-первых, скомпилировать фрагмент vue в контенте в html для отображения, а с другой стороны, использовать Highlight для выделения блока кода.demo-blockЭто наш определенный компонент:

<template>
  <div class="docs-demo-wrapper">
      <div :style="{maxHeight: isExpand ? '700px' : '0'}" class="demo-container">
        <div span="14">
          <div class="docs-demo docs-demo--expand">
            <div class="highlight-wrapper">
              <slot name="highlight"></slot>
            </div>
          </div>
        </div>
      </div>
    <span 
           class="docs-trans docs-demo__triangle" 
           @click="toggle">{{isExpand ? '隐藏代码' : '显示代码'}}</span>
  </div>
</template>

Таким образом, наш test.md можно записать так:

2. Как писать компоненты

Окружение готово, и тогда мы начнем писать компоненты, учитывая библиотеку компонентов, чтобы мы могли сделать так, чтобы наши компоненты поддерживали глобальный импорт и импорт по запросу.Если глобальный импорт, то все компоненты должны быть зарегистрированы на компоненте Vue, а экспорт :

const install = function(Vue) {
  if (install.installed) return;
  components.map(component => Vue.component(component.name, component));
};

export default {
  install
};

Затем для загрузки по требованию нам нужен только один компонент экспорта:

import Button from './button/index.js';
import Row from './row/index'
import Col from './col/index'

const components = [
  Button,
  Row,
  Col
];

const install = function(Vue) {
  if (install.installed) return;
  components.map(component => Vue.component(component.name, component));
};

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

export default {
  install,
  Button,
  Row,
  Col
};

Во-вторых, нам также необходимо рассмотреть проблему: поскольку это одностраничное приложение, необходимо решить проблему конфликтов стилей, если в компоненте используется soped, то стиль не может быть извлечен из компонента, а цель настройки цвета темы не может быть достигнуто. Нам нужен набор стилей, которые могут обрабатываться отдельно, могут компилироваться сами по себе и не могут загрязнять друг друга. В настоящее время особенно важна БЭМ-спецификация css. Если вы еще не знаете, что такое ссылка БЭМ:Woohoo. Я 3 с prussian.com/CSS/CSS-arc….
Говоря об этом, текущий плагин, который лучше поддерживает спецификацию БЭМ, — это postcss, который позволяет нам настраивать коннекторы и аббревиатуры между БЭМами:

{
  "browsers": ["ie > 8", "last 2 versions"],
  "features": {
    "bem": {
      "shortcuts": {
        "component": "b",
        "modifier": "m",
        "descendent": "e"
      },
      "separators": {
        "descendent": "__",
        "modifier": "--"
      }
    }
  }
}

Таким образом, мы можем извлечь стили отдельно, упаковать и скомпилировать их через gulp:

gulp.task('compile', function() {
  return gulp.src('./src/*.css')
    .pipe(postcss([salad]))
    .pipe(cssmin())
    .pipe(gulp.dest('./lib'));
});

Наконец, сгенерируйте наш код стиля.

Хорошо, давайте начнем наш тест:

import VVUI from '../packages/index'
import '../packages/theme-default/lib/index.css'

Vue.use(VVUI)

Все выглядит так красиво....

Оптимизация и недостатки

  • Код экспорта компонента не поддерживает автоматическую генерацию: например, наш индексный файл компонента необходимо перезаписывать каждый раз при добавлении компонента.
    Вы можете попробовать конфигурацию веб-пакета,npm run devКогда компонент автоматически обнаруживает и помогает нам написать код для экспорта.
  • Дефекты в разделении структуры каталогов: В настоящее время весь контент поддерживает только китайский язык.Если вы хотите поддерживать интернационализацию, вам необходимо перенастроить структуру каталогов.
  • Публикация тегов: необходимо написать сценарии для поддержки публикации тегов.
  • Слишком мало компонентов:Документ только что написан, и компонентов пока не так много.Потихоньку поддерживайте его.Верю,компонентов будет все больше и больше.Также можно добавлять часто используемые компоненты в процессе ведения бизнеса,что более удобно для вашего будущего обслуживания и обучения.

Заключение:

Адрес проекта на гитхабе:github
Адрес демонстрации проекта:демо
Добро пожаловать, чтобы поддерживать PR вместе, добро пожаловать, звезда

о

Автор: обезьяна Ван

Моя домашняя страница:monkeyWang

Публичный аккаунт WeChat: время от времени будут публиковаться технические статьи о внешнем интерфейсе, пожалуйста, обратите внимание

WeChat.QQ.com/Day/Y II XQ YJ E8…(автоматическое распознавание QR-кода)