Небольшой партнер из команды, которая поддерживает бизнес апплетов TOPLIFE, надеюсь, он будет вам полезен в использовании Таро.
предисловие
Некоторое время назад фолловинг от нашей Bump LabReactграмматическийМультитерминальный план развития - TaroНаконец-то открытый исходный код для внешнего мира, добро пожаловать на просмотрstar(Сначала воспроизведите волну рекламы). Используется в качестве первой партииTaroОдин из разработчиков апплета TOPLIFE разработал, естественно, много обходных путей, проложил много ям, помог найти много багов. Теперь, когда проект наконец-то онлайн, пришло время подвести итоги и поделиться им с вами.
Сравните с WePY
Когда была разработана первая фаза TOPLIFE, она фактически использоваласьWePY(Таро в то время еще не было разработано), а затем его полностью переоборудовали для использования во второй фазе.Taroразработка. Как человек, который использовал как небольшие среды разработки программ, так и применял их в производственной среде, естественно сравнивать сходства и различия между ними.
Та же точка
- разработка компонента
- поддержка пакетов npm
- поддержка функций ES6+,Promise,Async FunctionsЖдать
- Поддержка прекомпилятора CSS, Sass/Stylus/PostCSS и т. д.
- Поддержка управления состоянием с помощью Redux
- …
Об одном и том же много говорить не надо, на дворе 2018 год.
разница
- стиль разработки
- Принцип реализации
- WePY поддерживает слот, Taro не поддерживает прямой рендеринг дочерних элементов.
стиль разработки
Самая большая разница, естественно, это разница в стиле разработки,WePYИспользуя стиль разработки, похожий на Vue,Taroкласс используетсяReactСтиль разработки, можно сказать, что все равно будет большая разница в опыте разработки. Опубликуйте официальную демонстрацию для краткого объяснения.
WePY demo
<style lang="less">
@color: #4D926F;
.userinfo {
color: @color;
}
</style>
<template lang="pug">
view(class='container')
view(class='userinfo' @tap='tap')
mycom(:prop.sync='myprop' @fn.user='myevent')
text {{now}}
</template>
<script>
import wepy from 'wepy';
import mycom from '../components/mycom';
export default class Index extends wepy.page {
components = { mycom };
data = {
myprop: {}
};
computed = {
now () { return new Date().getTime(); }
};
async onLoad() {
await sleep(3);
console.log('Hello World');
}
sleep(time) {
return new Promise((resolve, reject) => setTimeout(resolve, time * 1000));
}
}
</script>
Taro demo
import Taro, { Component } from '@tarojs/taro'
import { View, Button } from '@tarojs/components'
export default class Index extends Component {
constructor () {
super(...arguments)
this.state = {
title: '首页',
list: [1, 2, 3]
}
}
componentWillMount () {}
componentDidMount () {}
componentWillUpdate (nextProps, nextState) {}
componentDidUpdate (prevProps, prevState) {}
shouldComponentUpdate (nextProps, nextState) {
return true
}
add = (e) => {
// dosth
}
render () {
return (
<View className='index'>
<View className='title'>{this.state.title}</View>
<View className='content'>
{this.state.list.map(item => {
return (
<View className='item'>{item}</View>
)
})}
<Button className='add' onClick={this.add}>添加</Button>
</View>
</View>
)
}
}
Это можно увидеть в WePY,css
,template
,script
Все в файле WPY,template
Также поддерживает несколько синтаксисов механизма шаблонов, а затем поддерживаетcomputed
,watcher
etc, это типичный стиль Vue.
В Taro это совершенно стиль React, в том числеconstructor
,componentWillMount
,componentDidMount
Реагировать, такие как жизненный цикл различных функций, а такжеreturn
вернулся вjsx
, люди, знакомые с React, могут очень быстро начать работу.
Помимо этого есть небольшие отличия:
- Шаблоны в WePY или
wxml
, используются все собственные компоненты апплета, то есть различные компоненты документа апплета; и каждый компонент, используемый в Taro, должен начинаться с@tarojs/components
импортные, в том числеView
,Text
И другие основные компоненты (на самом деле это делается для того, чтобы преобразовать много раз в приготовлении) - обработка событий
- В Таро используется
click
событие вместоtap
мероприятие - WePY использует сокращенное обозначение @+событие, а Таро — on+название события.
- Чтобы предотвратить всплытие на WePY, используется @+event.stop, а Таро нужно использовать явно
e.stopPropagation()
перестать пузыриться - Параметр события WePY может передавать параметры непосредственно после функции, например
@tap="click({{index}})"
; в то время как Таро используетbind
передавать параметры, такие какonClick={this.handleClick.bind(null, params)}
- В Таро используется
- WePY использует собственный жизненный цикл апплета, а компоненты имеют
page
а такжеcomponent
отличие; Taro реализует жизненный цикл, подобный React, и не имеетpage
а такжеcomponent
различие, обаcomponent
В общем ведь есть два разных стиля разработки, и естественно будет много больших и маленьких отличий. Здесь с одной из популярных на данный момент сред разработки апплетовWePYПростое сравнение в основном для удобства всех, чтобы быстрее понятьTaro, чтобы выбрать наиболее подходящий для вас метод разработки.
Опыт практики
Taroофициально предоставленdemoЭто очень просто, в основном, чтобы все могли быстро приступить к работе и приступить к работе. Итак, когда мы хотим разработать масштабный проект, как мы должны его использовать?TaroСделать опыт разработки лучше и повысить эффективность разработки? Как один из сотрудников, активно вовлеченных в разработку апплета TOPLIFE, я хотел бы рассказать о своем практическом опыте и опыте.
Как организовать код
Используйте taro-cli для создания таких шаблонов
├── dist 编译结果目录
├── config 配置目录
| ├── dev.js 开发时配置
| ├── index.js 默认配置
| └── prod.js 打包时配置
├── src 源码目录
| ├── pages 页面文件目录
| | ├── index index页面目录
| | | ├── index.js index页面逻辑
| | | └── index.css index页面样式
| ├── app.css 项目总通用样式
| └── app.js 项目入口文件
└── package.json
Если вводится redux, например, в нашем проекте, каталог выглядит так:
├── dist 编译结果目录
├── config 配置目录
| ├── dev.js 开发时配置
| ├── index.js 默认配置
| └── prod.js 打包时配置
├── src 源码目录
| ├── actions redux里的actions
| ├── asset 图片等静态资源
| ├── components 组件文件目录
| ├── constants 存放常量的地方,例如api、一些配置项
| ├── reducers redux里的reducers
| ├── store redux里的store
| ├── utils 存放工具类函数
| ├── pages 页面文件目录
| | ├── index index页面目录
| | | ├── index.js index页面逻辑
| | | └── index.css index页面样式
| ├── app.css 项目总通用样式
| └── app.js 项目入口文件
└── package.json
TOPLIFE小程序整个项目大概3万行代码,数十个页面,就是按上述目录的方式组织代码的。 Наиболее важные папки в основномpages
,components
а такжеactions
.
-
pagesВнутри находится входной файл каждой страницы.Простая страница может быть непосредственно входным файлом.Если страница более сложная, входной файл будет использоваться как совокупный файл компонента.
redux
Привязка обычно осуществляется здесь. -
компоненты размещеныcomponentsв. Каталог внутри такой, если есть
coupon
страница с купоном, наpages
Конечно, естьcoupon
, как запись страницы, а затем его компоненты сохраняются вcomponents/coupon
внутри, то естьcomponentsОн также будет разделен на модули в соответствии со страницей, и может быть построен общий компонент.components/public
папка для повторного использования.Преимущество этого в том, что между страницаминезависимо друг от друга,не влияют друг на друга. Поэтому некоторые наши разработчики также делят труд по размерам страницы, не мешая друг другу, что значительно повышает эффективность нашей разработки.
-
actionsЭта папка тоже важнее, здесь логика вытягивания данных и повторной обработки данных. Можно сказать, что если данные обрабатываются хорошо и поток понятен, весь проект наполовину успешен.Подробности см. в разделе *** Лучшее использование избыточности***. как указано выше, если
coupon
страницыactions
, то он будет помещен вactions/coupon
Внутри вы снова можете увидеть, что все модули различаются по размеру страницы.
Помимо,assetСтатические ресурсы, для хранения которых используется файл, например некоторые изображения класса значков, но рекомендуется не хранить слишком много, в конце концов, существуют ограничения на пакет. а такжеconstantsЭто место для хранения констант, напримерapi
Доменное имя, конфигурация и т. д.
Если вы будете следовать вышеуказанным или подобным методам организации кода, а также следовать нормам и соглашениям, вы сможете повысить свою эффективность при разработке крупномасштабных проектов, по крайней мере, намного.
лучше использовать редукс
Каждый должен быть знаком с redux, библиотекой управления состоянием, которая обычно используется с некоторым промежуточным ПО. Наш проект в основном используетredux-thunk
а такжеredux-logger
Промежуточное ПО, одно для обработки асинхронных запросов и одно для отладки, трассировкиactions
.
предварительная обработка данных
Я считаю, что с таким моментом сталкивался каждый, данные, возвращаемые интерфейсом, и данные, отображаемые на странице, не полностью совпадают, и часто требуется слой предобработки. Итак, где должна управляться эта бизнес-логика, внутри компонента илиredux
обработать?
Например:
Например, в модуле корзины покупок, показанном выше, данные, возвращаемые интерфейсом,
{
code: 0,
data: {
shopMap: {...}, // 存放购物车里商品的店铺信息的map
goods: {...}, // 购物车里的商品信息
...
}
...
}
Да, магазин товаров и товар в корзине размещены в двух объектах, но представление требует, чтобы они отображались вместе. В настоящее время, если вы напрямую сохраняете возвращенные данные вstore
, то внутри компонентаrender
Когда придет время собрать воедино, сопоставить две информации, а затем отобразить ее, окажется, что логика внутри компонента очень хаотична и недостаточно чиста.
Поэтому я лично рекомендую, чтобы после того, как интерфейс вернул данные, они были непосредственно обработаны в данные, соответствующие отображению страницы, а затемdispatch
Обработанные данные эквивалентны слою перехвата, а именно:
const data = result.data // result为接口返回的数据
const cartData = handleCartData(data) // handleCartData为处理数据的函数
dispatch({type: 'RECEIVE_CART', payload: cartData}) // dispatch处理过后的函数
...
// handleCartData处理后的数据
{
commoditys: [{
shop: {...}, // 商品店铺的信息
goods: {...}, // 对应商品信息
}, ...]
}
Видно, что процесс обработки данных перехватывается и обрабатывается перед рендерингом, а соответствующий товарный магазин и товар помещаются в один объект.
Есть несколько преимуществ для этого
-
Один из них — рендеринг компонентов.чище, вам не нужно заботиться о том, как изменить данные, чтобы они соответствовали требованиям представления внутри компонента,Просто позаботьтесь о логике самого компонента, такие как события кликов, взаимодействия с пользователем и т. д.
-
Во-вторых, поток данных.более контролируемый, если данные, возвращаемые последующим фоном, изменяются, все, что нам нужно сделать, это изменить
handleCartData
Логика в функции не требует изменения логики внутри компонента.Фоновые данные -> обработка перехвата -> ожидаемая структура данных -> компоненты
На самом деле, не только при возврате фоновых данных, но и при необходимости изменения других структур данных может выполняться слой перехвата данных, а время перехвата также может быть скорректировано в соответствии с бизнес-логикой.Соответствуют ли данные представлению, ориентируйтесь только на логику внутреннего взаимодействия, что тоже подходитReact
Его первоначальное намерение, представление, основанное на данных.
подключение может сделать больше
connect
Все знают, что он используется для подключенияstore
,actions
И компоненты, много раз просто скопируйте его в соответствии с шаблонным кодом и измените соответствующие компоненты компонентов.store
,actions
.实际上,我们还可以做一些别的处理,例如:
export default connect(({
cart,
}) => ({
couponData: cart.couponData,
commoditys: cart.commoditys,
editSkuData: cart.editSkuData
}), (dispatch) => ({
// ...actions绑定
}))(Cart)
// 组件里
render () {
const isShowCoupon = this.props.couponData.length !== 0
return isShowCoupon && <Coupon />
}
Вышеупомянутое очень распространеноconnect
пиши тогдаrender
функционировать в соответствии сcouponData
Будут ли данные отображаться. В это время мы можемthis.props.couponData.length !== 0
Это суждение потеряноconnect
, чтобы достичьcomputed
Эффект следующий:
export default connect(({
cart,
}) => {
const { couponData, commoditys, editSkuData } = cart
const isShowCoupon = couponData.length !== 0
return {
isShowCoupon,
couponData,
commoditys,
editSkuData
}}, (dispatch) => ({
// ...actions绑定
}))(Cart)
// 组件里
render () {
return this.props.isShowCoupon && <Coupon />
}
можно увидеть вconnect
определено вisShowCoupon
переменная, реализующаяcouponData
выполнятьcomputed
Эффект.
По сути, это тоже процесс перехвата данных. Кромеcomputed
, и другие функции также могут быть реализованы, которые могут свободно выполняться чиновниками.
Ощущение проекта
Самое большое ощущение, что в процессе разработки,Иногда я забываю, что пишу небольшую программу, и мне кажется, что я пишу страницу React.. Да, когда-то я хотел привязать событие прокрутки к странице, только чтобы понять, что нет такой вещи, какdoucment.body.addEventListener
такого рода вещи. В использованииWePY
В процессе те странные грамматики мне еще напомнили, что это маленькая программа, не страница h5, а использующаяTaro
, эта дифференциация была стерта очень мало. Хотя есть определенныеограничение, но я в основном использую его с привычкой разработки ReactTaro
, можно сказать, что это значительно улучшило мой опыт разработки.
Некоторые моменты, на которые следует обратить внимание
ЭтоTaro
, или разработка небольшой программы, есть на что обратить внимание? Конечно, есть много обходных путей.
Стек страниц имеет только 10 слоев
- Подсчитано, что данные каждой страницы кэшируются внутри апплета, поэтому существует ограничение в 10 слоев. Проблема в том, что если на странице есть круговой переход, то есть страница А может перейти на страницу Б, страница Б тоже может перейти на страницу А, а потом пользователи заходят на Б из А, а когда хотят вернуться на А , они часто ведут прямо на страницу B. Нажмите, чтобы перейти на страницу A,вместо точки возвратаНазад к А, в итоге 10 этаж быстро прорвался. Итак, мы сами
navigateTo
Функция инкапсулирована для предотвращения переполнения.
содержимое страницы кэшируется
- Как упоминалось выше, содержимое страницы кэшируется. Поэтому, если страница отображает представления на основе других данных, при выполнении нового рендеринга будет кеш предыдущего рендеринга, что приведет к мерцающему изменению внешнего вида страницы и очень плохому взаимодействию с пользователем. На самом деле решение очень простое, каждый раз
componentWillUnmount
Просто очищайте данные текущей страницы в течение жизненного цикла. Ведь апплет не х5.Здесь не сказано,что он будет обновляться каждый раз при входе на страницу,и не уничтожаться при выходе.Действия по обновлению и очистке данных нужно активно запускать в жизни циклическая функция.
Невозможно прослушивать события прокрутки страницы в любое время
- Событие прокрутки страницы может быть передано только через
onPageScroll
Слушать, поэтому, когда я хочу прослушать операцию в компоненте, логика этой части заранее.onPageScroll
функций, увеличивая стоимость абстракции. Например, мне нужно развить свиток до определенного положения на потолке.tab
, мог быть вtab
Усовершенствована логика внутренней обработки, что снижает возможность ее повторного использования.
На что обратить внимание при разработке Таро
- Я изначально хотел его подробно описать, но стараниями наших больших начальников и сверхурочной работой был разработан плагин eslint, и Таро завершен.Документация. Пока вы следуете спецификации подключаемого модуля eslint и просматриваете документацию, серьезных проблем возникнуть не должно.Если у вас есть какие-либо вопросы, пожалуйста, задавайтеissue.
Суммировать
В общем, сTaroОпыт разработки небольших программ еще очень хороший.Самое главное, что вы можете использовать jsx для написания небольших программ! ! ! Как поклонник React, я могу сказать, что очень взволнован~
Наконец, добро пожаловать, чтобы следоватьgithub.com/nervjs/taro