- автор:Джесси Рейндропс
Предыстория проекта:
G Trading H5 — это мультитерминальная игровая торговая платформа. Основываясь на обновлении функционала на уровне продукта и необходимости повышения эффективности разработки, некоторое время назад я использовал Vue и Webpack для проведения постепенного рефакторинга проекта. Так называемый прогрессивный, то есть в каждом цикле модифицируются только некоторые страницы, не затрагивая развитие других бизнесов. На этот раз я переделал список заказов, которые я купил/продал, и детали заказа.
Это совместное использование в основном включает следующие пункты:
- Основная технология
- Компонентизация
- управление данными
- Улучшения на уровне кода
- яма столкнулась
- Точка непрерывной оптимизации
Основная технология
Основными технологиями, используемыми в этом рефакторинге, являются vue2.0 и webpack1.0. Далее они кратко представлены.
Vue.js — это прогрессивный фреймворк для создания пользовательских интерфейсов. В отличие от других тяжеловесных фреймворков, Vue использует инкрементальную разработку снизу вверх. Основная библиотека Vue ориентирована только на уровень представления и очень проста в освоении. В частности, изОфициальный сайтУзнайте, как его использовать.
Webpack — это самый популярный модульный инструмент управления интерфейсными ресурсами и пакетирования. Он может упаковывать множество свободных модулей во внешние ресурсы, соответствующие развертыванию в производственной среде в соответствии с зависимостями и правилами. Он также может разделять код на модули, загружаемые по требованию, и ждать до фактической загрузки асинхронно при необходимости.
Следующее изображение является официальным введением в Webpack, Из этого изображения видно, что файлы взаимозависимых модулей будут упакованы в один или несколько файлов js, что может уменьшить количество HTTP-запросов.
Версия 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 // 工具函数
Как реализовать компонентизацию?
Преимущества компонентизации не перечислены один за другим, единая ответственность, простота обслуживания, расширяемость...
Во-первых, я разделил две страницы на компоненты по функциям и представлению.
Как показано на странице списка заказов на рисунке ниже, страницу можно разделить на три компонента сверху вниз в соответствии с функциями: выбор типа продукта, переключение статуса транзакции и отображение компонентов данных списка.
Что касается связи между компонентами, данные родительского компонента отправляются дочернему компоненту через реквизит, а дочерний компонент связывается с родительским компонентом через интерфейс события $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, и я напоминаю себе о необходимости постоянно улучшать возможности кодирования и качество кода в ежедневной разработке. В будущем все больше предприятий будут интегрированы в новые рефакторинговые проекты, и другие аспекты также необходимо будет постоянно оптимизировать и изучать.