- автор:Джесси Рейндропс
Предыстория проекта:
G Trading H5 — это мультитерминальная игровая торговая платформа. Основываясь на обновлении функционала на уровне продукта и необходимости повышения эффективности разработки, некоторое время назад я использовал Vue и Webpack для проведения постепенного рефакторинга проекта. Так называемый прогрессивный, то есть в каждом цикле модифицируются только некоторые страницы, не затрагивая развитие других бизнесов. На этот раз я переделал список заказов, которые я купил/продал, и детали заказа.
Это совместное использование в основном включает следующие пункты:
- Основная технология
- Компонентизация
- управление данными
- Улучшения на уровне кода
- яма столкнулась
- Точка непрерывной оптимизации
Основная технология
Основными технологиями, используемыми в этом рефакторинге, являются vue2.0 и webpack1.0. Далее они кратко представлены.
Vue.js — это прогрессивный фреймворк для создания пользовательских интерфейсов. В отличие от других тяжеловесных фреймворков, Vue использует инкрементальную разработку снизу вверх. Основная библиотека Vue ориентирована только на уровень представления и очень проста в освоении. В частности, изОфициальный сайтУзнайте, как его использовать.
Webpack — это самый популярный модульный инструмент управления интерфейсными ресурсами и пакетирования. Он может упаковывать множество свободных модулей во внешние ресурсы, соответствующие развертыванию в производственной среде в соответствии с зависимостями и правилами. Он также может разделять код на модули, загружаемые по требованию, и ждать до фактической загрузки асинхронно при необходимости.
Следующее изображение является официальным введением в Webpack, Из этого изображения видно, что файлы взаимозависимых модулей будут упакованы в один или несколько файлов js, что может уменьшить количество HTTP-запросов.
Для конкретного использования Webpack, пожалуйста, обратитесь кОфициальный сайт.Версия Vue, используемая в этом рефакторинге, — 2.1.0, а Webpack — 1.13.2.
Структура каталога:
gmmh5
|-- build //构建目录
| |-- build.js
| |-- dev-client.js
| |-- dev-server.js
| |-- HashedModuleIdsPlugin.js
| |-- utils.js
| |-- webpack.base.conf.js
| |-- webpack.dev.conf.js
| |-- webpack.prod.conf.js
|-- config //配置文件
|-- dist //打包后的文件
|-- src //源码目录
| |--assets // 静态资源
| |--biz // 页面配置文件
| |--common // 公共方法
| |--components // 基础组件
| |--constants
| |--modules // 业务组件
| |--pages // 页面
| |--utils // 工具函数
Как реализовать компонентизацию?
Преимущества компонентизации не перечислены один за другим, единая ответственность, простота обслуживания, расширяемость...
Во-первых, я разделил две страницы на компоненты по функциям и представлению.
Как показано на странице списка заказов на рисунке ниже, страницу можно разделить на три компонента сверху вниз в соответствии с функциями: выбор типа продукта, переключение статуса транзакции и отображение компонентов данных списка.
Выберите тип товара Компонент select-type отвечает за изменение goodsType, а компонент change-state отвечает за изменение состояния Оба компонента передают измененные параметры в файл ввода app.vue, а файл ввода отвечает за получение данных списка, а затем передача данных Компонент списка отвечает за отображение данных списка. Поток данных выглядит следующим образом: Детали заказа обрабатываются таким же образом.Что касается связи между компонентами, данные родительского компонента отправляются дочернему компоненту через реквизит, а дочерний компонент связывается с родительским компонентом через интерфейс события $on, $emit vue. Компоненты Brother или компоненты с более глубокими уровнями используют EventBus для связи, когда vuex в данный момент не используется. Конкретный метод работы заключается в следующем:
Сначала назовите event-bus.js, создайте новый глобальный экземпляр Vue, назовите его EventBus и экспортируйте этот объект.
import Vue from 'vue'
var EventBus = new Vue()
export default EventBus
Внесите Vue и EventBus в компонент A. Когда вызывается метод "emitMethod" в этом компоненте, он запускает событие "EVENT_NAME" и передает параметр "payload".
import Vue from 'vue';
import EventBus from 'event-bus'
Vue.component('component-a', {
...
methods: {
emitMethod () {
EventBus.$emit('EVENT_NAME', payLoad);
}
}
});
В другом компоненте B мы можем зарегистрировать событие прослушивателя для прослушивания события «EVENT_NAME», доставленного EventBus.
import Vue from 'vue';
import EventBus from './event-bus';
Vue.component(‘component-b’, {
...
mounted () {
EventBus.$on('EVENT_NAME', function (payLoad) {
...
});
}
});
Таким образом, компонент B может прослушивать события, инициированные компонентом A, без необходимости рассматривать слишком много иерархических вопросов.
управление данными
Сложность обработки сведений о заказе заключается в том, что их представление на странице зависит от типа элемента и значения статуса транзакции.
На странице H5 покупки и продажи G есть следующие типы товаров, среди которых учетные записи также делятся на мобильные игры, конечные игры и внешние консигнационные учетные записи. Купоны также включают соответствующие купоны, типы обычных купонов. Тип товаров, которые фактически перерабатываются, более сложен, чем на картинке ниже.
Под каждым типом товара есть разные значения статуса, среди которых аккаунт имеет наибольшее количество значений статуса. Тип элемента и значение статуса вместе определяют отображение контента на странице: заголовок описания статуса, верхнее текстовое описание, значок транзакции и кнопка элемента действия. Чтобы иметь дело с такого рода данными, не смешивая их с логикой страницы, я превратил их в таблицу конфигурации. Часть кода выглядит следующим образом:const account = {
'1': {
'title': '待付款',
'topImg': imgState.wait,
'topMsg': topMsgSource.fromFixTxtByFunc,
'btns': [btn.cancel, btn.pay]
},
'2': {
'title': '付款成功',
'topImg': imgState.trade,
'topMsg': topMsgSource.fromFixTxtByFunc,
'btns': [btn.refund, btn.selectCheckType]
},
...
}
account представляет тип счета в товарном типе. «1», «2» — значения состояния.
При получении значения вызывается интерфейс детализации товара на странице, получается детализация данных и выносятся товары_тип и состояние_к_ауту в детализации, то есть тип товара и значение статуса транзакции товара . Затем получите соответствующие данные в конфигурационном файле конфигурации. Например, возьмем заголовок описания статуса:
const vm = this
let goods_type = vm.detail.goods_type
let state_to_out = vm.detail.state_to_out
title = vm.config[goods_type][state_to_out]["title"]
Преимущество ясно, чтобы внести любые изменения в таблице конфигурации могут измениться.
Улучшения на уровне кода
Уменьшить дублирующийся код
В исходном коде существующая ситуация такова: код копируется в нескольких местах, и когда он изменяется, часто неизвестно, где он был изменен или пропущен. Я разобрал много повторяющегося кода, абстрагировал и инкапсулировал логику повторяющегося кода.
Например, многие функции в кнопке операции будут обновлять страницу после вызова ajax, поэтому я извлек ее и написал в виде отдельной функции:
operateRefresh(url, params) {
//通用方法 -- ajax后刷新页面
const vm = this
utils.get(url, params, (res) => {
let data = res.data
if (res.return_code === 0) {
vm.refresh()
} else {
utils.toast(res.return_message)
}
})
}
Подход к написанию принципа единой ответственности
Единая ответственность — это объект (метод), который делает только одну вещь. Если у метода слишком много обязанностей, то изменения в одной ответственности могут повлиять на реализацию других обязанностей, и изменять код становится более опасно.
В этом преобразовании я разделил некоторые большие функции на некоторые маленькие функциональные функции в соответствии с их функциями. Например, первоначальные задачи страницы списка включают в себя: принятие решения о покупке или продаже, получение инициализированного типа продукта, вызов интерфейса для получения данных списка и мониторинг событий других компонентов:
created() {
const vm = this
// 判断用户是买家还是卖家
vm.judgeRole()
// 从url获取goods_type以及trade_mode
vm.getUrlParams()
// 获取列表数据
vm.getList()
// 监听事件
vm.subscribeToEvent()
}
яма столкнулась
Ямы, возникающие в процессе рефакторинга, в основном связаны с недостаточным пониманием бизнеса.На этот раз мы также столкнулись с некоторыми ямами Vue при реконструкции с помощью Vue2.0.
Поскольку Vue выполняет процесс преобразования геттер/сеттер для свойств при инициализации экземпляра, свойство должно существовать в объекте данных, чтобы Vue мог преобразовать его и обнаружить его изменение. Vue не может обнаружить добавление или удаление свойств. В некоторых компаниях я добавлял и изменял свойства данных, но это не запускало повторный рендеринг Vue.На этом этапе я застрял на некоторое время. Позже я прочитал официальную документацию и обнаружил, что она может использовать метод Vue.set(object, key, value) для добавления адаптивных свойств к вложенным объектам, тем самым запуская обновления компонентов:
Vue.set(vm.someObject, 'b', 2)
Кроме того, поскольку Vue выполняет обновления DOM асинхронно. Как только наблюдается изменение данных, Vue открывает очередь и буферизует все изменения данных, которые происходят в том же цикле событий. Если один и тот же наблюдатель запускается несколько раз, он будет помещен в очередь только один раз. Если вы хотите обновить DOM сразу после изменения данных, вы можете использовать Vue.nextTick (обратный вызов) сразу после изменения данных.
Vue.nextTick(function () {
// 数据变化
})
Точка непрерывной оптимизации
Дело завершено, и я также разобрал некоторые моменты, которые можно постоянно оптимизировать:
- представление. Размер некоторых файлов может быть дополнительно уменьшен, кэш может использоваться более эффективно, а скорость рендеринга первого экрана может быть повышена.
- опыт. Улучшите процесс обновления по запросу и добавьте подсказки для взаимодействия со страницей.
- поток данных. При интеграции большего количества сервисов структурный дизайн потока данных должен быть более четким.
- компонентный. Базовые компоненты могут быть более абстрактными, что способствует повторному использованию.
Суммировать
После этого рефакторинга у меня появилось более глубокое понимание и мастерство в бизнесе, и я понимаю, что при столкновении со сложным бизнесом гораздо важнее остановиться и четко обдумать бизнес-сценарий, чем писать код.
На этот раз у меня также есть более глубокое понимание и мастерство Vue, и я напоминаю себе о необходимости постоянно улучшать возможности кодирования и качество кода в ежедневной разработке. В будущем все больше предприятий будут интегрированы в новые рефакторинговые проекты, и другие аспекты также необходимо будет постоянно оптимизировать и изучать.