Я работаю сверхурочно уже почти три месяца подряд, и недавно я нашел время, чтобы записать некоторые из своих переживаний, которые можно рассматривать как резюме!
предыстория истории
Бизнес компании в основном заключается в выполнении проектов, и основное внимание уделяется индустрии электронной коммерции, поэтому это также определяет, что многие проекты имеют определенные общие черты. В настоящее время показатели компании хорошие (денег в конце года должно быть много), и часто параллельно ведется несколько проектов, что также обнажает проблемы всей команды:
- Несколько параллельных проектов, что приводит к нехватке человеческих ресурсов (эта обезьяна находится в городе третьего уровня, брата с двумя кистями нелегко нанять)
- Низкий уровень повторного использования кода и слишком много дублирования работы (даже проекты с 50% сходства, возможно, придется переделывать, что слишком мало)
- Качество разработки трудно контролировать, а затраты на тестирование высоки.
- Проекты трудно завершить вовремя, часто задерживая
Так что поиск доступного решения, подходящего для ситуации нашей команды, неизбежен!
Технологический стек этой команды ape — vue+webpack, поэтому мое решение может не подойти для других технологических стеков.
Решение первое
На самом деле это провальный план. Позвольте мне сначала представить его здесь и презирать себя!
Общая идея состоит в том, чтобы управлять отображением компонентов на странице через номер элемента, например:
<component-a v-if="projectId === 10000"></component-a>
<component-a v-if="projectId === 10001"></component-a>
Трагедия такого подхода очевидна:
- С увеличением количества проектов бизнес-логика становится все более и более сложной, объем кода становится все больше и больше, и это сильно влияет на скорость рендеринга внешнего интерфейса.
- Код логически связан, и когда несколько человек сотрудничают, могут возникать конфликты, приводящие к неизвестным ошибкам.
Решение второе
В настоящее время это решение находится на практике, и оно может удовлетворить текущие потребности бизнеса на данный момент!
1. Структура каталогов компонентов и страниц
Компоненты каталога компонентов аналогичны страницам каталога страниц, так что вот TabBar (нижняя панель навигации) в компонентах в качестве примера.
Мы видим, что под TabBar есть три файла 0.vue, 29006.vue и index.js:
- 0.vue — стандартный компонент нижней панели навигации.
- 29006.vue — это нижняя панель навигации, настроенная для проекта номер 29006.
- index.js — это вход для всего компонента TabBar. Как сгенерировать этот файл, см. следующее введение.
По аналогии, в pages/Home (главная) мы также можем видеть стандартную домашнюю страницу, домашнюю страницу, настроенную под номер проекта 29006, и файл входа домашней страницы index.js
Во-вторых, структура файлов ресурсов
Файлы стилей и изображений такие же, как и компоненты, представленные ранее, с использованием номера элемента в качестве имени файла, чтобы различать их.
3. Компоненты ссылки на страницу и страницы загрузки маршрута
Каждый компонент имеет index.js в качестве записи, поэтому, если вы добавляете компонент на страницу, просто:
import TabBar from '../../components/TabBar';
Точно так же каждая страница также имеет index.js в качестве записи, поэтому, если вы добавляете компоненты в маршрут, просто:
{
path: '/home',
name: 'home',
title: '首页',
component(resolve) {
require.ensure(['../pages/Home'], () => {
resolve(require('../pages/Home'));
});
},
meta: {requiresAuth: false}
}
В-четвертых, конфигурация проекта
Вы уже поняли общую структуру проекта.Вы должны понимать, что следующий ключ — это то, как генерировать разные файлы ввода index.js и файлы ресурсов в соответствии с номером проекта.
Нижний колонтитул генерации проекта create-platform.js выглядит следующим образом:
const glob = require('glob');
const fsExtra = require('fs-extra')
const platform = process.argv[2]; // 项目号
const vueFile = `${platform}.vue`; // 与项目匹配的vue文件
const defaultVueFile = `0.vue`; // 标准的vue文件
const fs = require('fs');
// 获取指定路径下的入口文件
function getEntries(globPath) {
let files = glob.sync(globPath);
let paths = [];
files.forEach((filepath) => {
let split = filepath.split('/');
let path = split.slice(0, split.length - 1);
path = path.join('/');
paths.push(`${path}`);
});
paths = dedupe(paths);
return paths;
}
// 数组去重
function dedupe(array){
return Array.from(new Set(array));
}
// 写入index.js入口文件
async function writeIndexJS (path, fileName) {
let split = path.split('/');
let componentName = split[split.length - 1];
let f = `${path}/index.js`
try {
await fsExtra.outputFile(f, `import ${componentName} from './${fileName}';\r\nexport default ${componentName};`);
} catch (err) {
console.error(err)
}
}
async function copyFile (src, dest) {
try {
await fsExtra.copy(src, dest, { overwrite: true })
} catch (err) {
console.error(err)
}
}
// 创建index.js
function createIndexJS(paths) {
paths.forEach(async (path) => {
let exists = await fsExtra.pathExists(`${path}/${vueFile}`);
if (exists) {
writeIndexJS(path, vueFile);
} else {
writeIndexJS(path, defaultVueFile);
}
});
}
// copy懒加载所需图片
async function copyLazyLoad() {
let exists = await fsExtra.pathExists(`./src/assets/images/lazy-load/list/${platform}.png`);
if (exists) {
copyFile(`./src/assets/images/lazy-load/list/${platform}.png`, `./static/lazy-load/list.png`);
} else {
copyFile(`./src/assets/images/lazy-load/list/0.png`, `./static/lazy-load/list.png`);
}
exists = await fsExtra.pathExists(`./src/assets/images/lazy-load/thumbnail/${platform}.png`);
if (exists) {
copyFile(`./src/assets/images/lazy-load/thumbnail/${platform}.png`, `./static/lazy-load/thumbnail.png`);
} else {
copyFile(`./src/assets/images/lazy-load/thumbnail/0.png`, `./static/lazy-load/thumbnail.png`);
}
}
// copy样式文件
async function copyLess() {
let exists = await fsExtra.pathExists(`./src/assets/css/main/${platform}.less`);
if (exists) {
copyFile(`./src/assets/css/main/${platform}.less`, `./src/assets/css/main.less`);
} else {
copyFile(`./src/assets/css/main/0.less`, `./src/assets/css/main.less`);
}
exists = await fsExtra.pathExists(`./src/assets/css/theme/${platform}.less`);
if (exists) {
copyFile(`./src/assets/css/theme/${platform}.less`, `./src/assets/css/theme.less`);
} else {
copyFile(`./src/assets/css/theme/0.less`, `./src/assets/css/theme.less`);
}
}
let paths = getEntries('./src/components/**/*.vue'); // 获得入口components目录下的文件
createIndexJS(paths);
paths = getEntries('./src/pages/**/*.vue'); // 获得入口pages目录下的文件
createIndexJS(paths);
copyLazyLoad();
copyLess();
Команда запуска скрипта:
node create-platform.js 29006
Описание сценария
const platform = process.argv[2]; // 以命令行的第三个参数项目号
const vueFile = `${platform}.vue`; // 根据项目号生成匹配的vue文件
const defaultVueFile = `0.vue`; // 标准的vue文件
// 获取指定路径下的入口文件
function getEntries(globPath) {
.........
}
// 创建index.js
function createIndexJS(paths) {
// 遍历目录
paths.forEach(async (path) => {
// 判断目录中是否存在和项目号匹配的vue文件,如果有就使用该文件,如果没有则使用标准的0.vue
let exists = await fsExtra.pathExists(`${path}/${vueFile}`);
if (exists) {
writeIndexJS(path, vueFile);
} else {
writeIndexJS(path, defaultVueFile);
}
});
}
// 写入index.js入口文件
async function writeIndexJS (path, fileName) {
let split = path.split('/');
let componentName = split[split.length - 1]; // 以目录名作为组件和页面名称
let f = `${path}/index.js`
try {
await fsExtra.outputFile(f, `import ${componentName} from './${fileName}';\r\nexport default ${componentName};`);
} catch (err) {
console.error(err)
}
}
Здесь представлено лишь несколько основных методов, другие методы copyLazyLoad и copyLess имеют те же принципы, поэтому они не будут представлены один за другим!
5. Результаты
Команда выполнения
node create-platform.js 29006
Содержимое файла index.js в TabBar выглядит следующим образом:
import TabBar from './29006.vue';
export default TabBar;
Это связано с тем, что существует файл компонента 29006.vue, который соответствует номеру проекта на вкладке TabBar.
Содержимое файла index.js в HomeCategoryColumn выглядит следующим образом:
import HomeCategoryColumn from './0.vue';
export default HomeCategoryColumn;
Это связано с тем, что в HomeCategoryColumn нет файла, соответствующего элементу 29006, поэтому используется стандартный 0.vue.
6. Резюме
Таким образом, с одной стороны, мы можем повторно использовать разработанные компоненты в проекте, и в то же время мы можем реализовать настройку компонентов, и внедрение проекта будет значительно сокращено.
Возможно, это не лучший способ, но в настоящее время он больше соответствует реальной ситуации в нашей команде.Если есть хорошее решение, пожалуйста, сообщите нам, и давайте общаться вместе!
Последнее, что нужно сказать: как только вы входите в переднюю часть, она глубока, как море, и пройти весь путь легко! ! !