作为网络开发人员,您可能认为移动应用程序开发需要使用另一种编程语言创建新的学习曲线。也许Java和Swift需要添加到你的技能组中,以便在iOS和Android上运行,这可能会让你失望。
但是这篇文章让你感到惊喜!我们将考虑使用WooCommerce平台作为后端,为iOS和Android构建电子商务应用程序。对于任何愿意进入原生跨平台开发的人来说,这都是一个理想的起点。
跨平台发展简史
这是2011年,我们看到混合移动应用程序开发的开始。Apache Cordova,PhoneGap和Ionic Framework等框架慢慢出现。一切看起来都不错,而且网络开发人员正在利用他们现有的知识热切地编写移动应用程序。
但是,移动应用程序仍然看起来像移动版本的网站。没有像Android的材质设计或iOS平板外观的原生设计。导航工作类似于网页,转换并不平坦。用户对使用混合方法构建的应用程序并且梦想本地体验不满意。
快进到2015年3月,React Native出现在现场。开发人员能够使用React构建真正的本地跨平台应用程序,这是许多开发人员喜爱的JavaScript库。他们现在可以轻松地学习一个小型图书馆,而不仅仅是他们对JavaScript的了解。有了这些知识,开发人员现在就瞄准了网络,iOS和Android。
此外,开发过程中对代码所做的更改几乎可以立即加载到测试设备上!当我们通过其他方法进行本地开发时,这往往需要几分钟的时间。开发人员可以享受他们过去喜欢网络开发的即时反馈。
React开发人员非常乐意将他们已经使用的现有模式完全应用于新平台。事实上,他们将目标锁定在两个他们已经熟知的平台上。
这对前端开发很有好处。但是我们对后端技术有什么选择?我们还需要学习新的语言或框架吗?
WordPress REST API
在2016年年底,WordPress发布了期待已久的REST API到其核心,并为具有解耦后端的解决方案打开了大门。
因此,如果您已经拥有WordPress和WooCommerce网站,并希望在您的网站和原生应用中保留完全相同的产品和用户配置文件,本文即为您提供!
假设在本文中做出
我会引导您使用您的WordPress技能,通过使用React Native构建带有WooCommerce商店的移动应用程序。文章假设:
- 您熟悉不同的WordPress API,至少在初学者级别。
- 你熟悉React的基础知识。
- 你准备好了一个WordPress开发服务器。我在Apache上使用Ubuntu。
- 您可以使用Android或iOS设备与世博会进行测试。
我们将在本教程中构建的内容
我们将通过这篇文章构建的项目是一个时尚商店应用程序。该应用程序将具有以下功能:
- 商店页面列出所有产品,
- 单个产品页面包含所选项目的详细信息,
- ‘添加到购物车’功能,
- ‘显示购物车中的项目’功能,
- ‘从购物车删除商品’功能。
本文旨在激励您使用此项目作为使用React Native构建复杂移动应用程序的起点。
注意:对于完整的应用程序,您可以在Github上访问我的项目并克隆它。
开始我们的项目
我们将根据官方的React Native文档开始构建应用程序。在您的开发环境中安装了Node后,打开命令提示符并键入以下命令以全局安装Create React Native App。
npm install -g create-react-native-app
接下来,我们可以创建我们的项目
create-react-native-app react-native-woocommerce-store
这将创建一个新的React Native项目,我们可以使用Expo进行测试。
接下来,我们需要在我们想要测试的移动设备上安装Expo应用程序。它适用于iOS和Android。
在安装了世博应用程序后,我们可以在我们的开发机器上运行npm start。
cd react-native-woocommerce-store
npm start
之后,您可以通过Expo App扫描QR代码,或者在应用程序的搜索栏中输入给定的URL。这将在手机中运行基本的’Hello World’应用程序。我们现在可以编辑App.js,以便对手机上运行的应用程序进行即时更改。
或者,您可以在模拟器上运行该应用程序。但为了简洁和准确,我们将涵盖在实际设备上运行它。
接下来,我们使用以下命令安装应用程序的所有必需软件包:
npm install -s axios react-native-htmlview react-navigation react-redux redux redux-thunk
设置一个WordPress站点
由于本文是关于创建React Native应用程序的,因此我们不会详细讨论创建WordPress网站的细节。请参考这篇关于如何在Ubuntu上安装WordPress的文章。由于WooCommerce REST API需要HTTPS,请确保使用Let’s Encrypt进行设置。请参阅本文以获取操作指南。
我们不在本地主机上创建WordPress安装,因为我们将在移动设备上运行应用程序,并且还需要HTTPS。
一旦WordPress和HTTPS成功建立,我们就可以在网站上安装WooCommerce插件。
安装并激活插件后,按照向导继续进行WooCommerce商店安装。向导完成后,点击“返回仪表板”。
你会被另一个提示迎接。
点击’Let’s go’到’Add example products’。这将节省我们创建自己的产品以显示在应用程序中的时间。
常量文件
要从WooCommerce REST API加载我们商店的产品,我们需要在我们的应用程序中安装相关密钥。为此,我们可以有一个constans.js
文件。
首先创建一个名为’src’的文件夹并在其中创建子文件夹,如下所示:
现在,让我们为WooCommerce生成密钥。在WordPress仪表板中,导航到WooCommerce→设置→API→键/应用程序,然后点击“添加键”。
接下来创建名称为React Native的只读密钥。将消费者密钥和消费者密钥复制到constants.js
文件中,如下所示:
const Constants = {
URL: {
wc: 'https://woocommerce-store.on-its-way.com/wp-json/wc/v2/'
},
Keys: {
ConsumerKey: 'CONSUMER_KEY_HERE',
ConsumerSecret: 'CONSUMER_SECRET_HERE'
}
}
export default Constants;
从反应导航开始
React Navigation是一个在不同屏幕之间导航的社区解决方案,并且是一个独立的库。它允许开发人员使用几行代码设置React Native应用程序的屏幕。
React Navigation中有不同的导航方法:
- 堆栈,
- 开关,
- 标签,
- 抽屉,
- 和更多。
对于我们的应用程序,我们将结合使用StackNavigation
和DrawerNavigation
在不同屏幕之间导航。StackNavigation
与浏览器历史记录在网络上的工作方式类似。我们正在使用它,因为它为标题和标题导航图标提供了一个界面。它具有与数据结构中的堆栈类似的推送和弹出功能。推意味着我们添加一个新的屏幕到导航堆栈的顶部。Pop从堆栈中删除一个屏幕。
该守则显示,StackNavigation
事实上,DrawerNavigation
它本身就是其中的一部分。它还会获取标题样式和标题按钮的属性。我们将导航抽屉按钮放在左边,购物车按钮放在右边。抽屉按钮打开和关闭抽屉,而购物车按钮则将用户带到购物车屏幕。
const StackNavigation = StackNavigator({
DrawerNavigation: { screen: DrawerNavigation }
}, {
headerMode: 'float',
navigationOptions: ({ navigation, screenProps }) => ({
headerStyle: { backgroundColor: '#4C3E54' },
headerTintColor: 'white',
headerLeft: drawerButton(navigation),
headerRight: cartButton(navigation, screenProps)
})
});
const drawerButton = (navigation) => (
<Text
style={{ padding: 15, color: 'white' }}
onPress={() => {
if (navigation.state.index === 0) {
navigation.navigate('DrawerOpen')
} else {
navigation.navigate('DrawerClose')
}
}
}> (
<Text style={{ padding: 15, color: 'white' }}
onPress={() => { navigation.navigate('CartPage') }}
>
<EvilIcons name="cart" size={30} />
{screenProps.cartCount}
</Text>
);
DrawerNavigation
另一方面提供了侧抽屉,这将允许我们在家,商店和购物车之间导航。在DrawerNavigator
列出了不同的屏幕,用户可以访问,即首页,产品页,产品页,购物车页面。它还有一个属性,它将取出抽屉容器:点击汉堡菜单时打开的滑动菜单。
const DrawerNavigation = DrawerNavigator({
Home: {
screen: HomePage,
navigationOptions: {
title: "RN WC Store"
}
},
Products: {
screen: Products,
navigationOptions: {
title: "Shop"
}
},
Product: {
screen: Product,
navigationOptions: ({ navigation }) => ({
title: navigation.state.params.product.name
}),
},
CartPage: {
screen: CartPage,
navigationOptions: {
title: "Cart"
}
}
}, {
contentComponent: DrawerContainer
});
将Redux商店注入App.js
由于我们在这个应用程序中使用Redux,我们必须将商店注入到我们的应用程序中。我们在Provider
组件的帮助下做到这一点。
const store = configureStore();
class App extends React.Component {
render() {
return (
<Provider store={store}>
<ConnectedApp />
</Provider>
)
}
}
然后,我们将有一个ConnectedApp
组件,以便我们可以在标题中包含购物车。
class CA extends React.Component {
render() {
const cart = {
cartCount: this.props.cart.length
}
return (
<StackNavigation screenProps={cart} />
);
}
}
function mapStateToProps(state) {
return {
cart: state.cart
};
}
const ConnectedApp = connect(mapStateToProps, null)(CA);
Redux Store,Actions和Reducers
在Redux中,我们有三个不同的部分:
- Store
保存整个应用程序的整个状态。改变状态的唯一方法是向它发送一个动作。 - 操作
表示意图更改状态的普通对象。 - Reducers
一个接受一个状态和一个动作类型并返回一个新状态的函数。
Redux的这三个组件帮助我们为整个应用程序实现可预测的状态。为了简单起见,我们将看看产品如何在Redux商店中获取和保存。
首先,我们来看看创建商店的代码:
let middleware = [thunk];
export default function configureStore() {
return createStore(
RootReducer,
applyMiddleware(...middleware)
);
}
接下来,产品操作负责从远程网站获取产品。
export function getProducts() {
return (dispatch) => {
const url = `${Constants.URL.wc}products?per_page=100&consumer_key=${Constants.Keys.ConsumerKey}&consumer_secret=${Constants.Keys.ConsumerSecret}`
return axios.get(url).then(response => {
dispatch({
type: types.GET_PRODUCTS_SUCCESS,
products: response.data
}
)}).catch(err => {
console.log(err.error);
})
};
}
产品缩减器负责返回数据的有效载荷以及是否需要修改。
export default function (state = InitialState.products, action) {
switch (action.type) {
case types.GET_PRODUCTS_SUCCESS:
return action.products;
default:
return state;
}
}
显示WooCommerce商店
该products.js
文件是我们的商店页面。它基本上显示了WooCommerce的产品列表。
class ProductsList extends Component {
componentDidMount() {
this.props.ProductAction.getProducts();
}
_keyExtractor = (item, index) => item.id;
render() {
const { navigate } = this.props.navigation;
const Items = (
<FlatList contentContainerStyle={styles.list} numColumns={2}
data={this.props.products || []}
keyExtractor={this._keyExtractor}
renderItem={
({ item }) => (
<TouchableHighlight style={{ width: '50%' }} onPress={() => navigate("Product", { product: item })} underlayColor="white">
<View style={styles.view} >
<Image style={styles.image} source={{ uri: item.images[0].src }} />
<Text style={styles.text}>{item.name}</Text>
</View>
</TouchableHighlight>
)
}
/>
);
return (
<ScrollView>
{this.props.products.length ? Items :
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
<Image style={styles.loader} source={LoadingAnimation} />
</View>
}
</ScrollView>
);
}
}
this.props.ProductAction.getProducts()
并且this.props.products
是可能的,因为mapStateToProps
和mapDispatchToProps
。
mapStateToProps
和 mapDispatchToProps
State是Redux商店,Dispatch是我们开展的行动。这些都将作为组件中的道具公开。
function mapStateToProps(state) {
return {
products: state.products
};
}
function mapDispatchToProps(dispatch) {
return {
ProductAction: bindActionCreators(ProductAction, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ProductsList);
样式
在React中,原生样式通常在同一页面上定义。它与CSS类似,但我们使用camelCase
属性而不是连字符属性。
const styles = StyleSheet.create({
list: {
flexDirection: 'column'
},
view: {
padding: 10
},
loader: {
width: 200,
height: 200,
alignItems: 'center',
justifyContent: 'center',
},
image: {
width: 150,
height: 150
},
text: {
textAlign: 'center',
fontSize: 20,
padding: 5
}
});
单一产品页面
此页面包含所选产品的详细信息。它向用户显示产品的名称,价格和描述。它还具有“添加到购物车”功能。
购物车页面
该屏幕显示购物车中的物品清单。该行动所具有的功能getCart
,addToCart
以及removeFromCart
。减速器同样处理这些动作。动作的识别是通过actionTypes来完成的 – 这些常量描述存储在单独文件中的动作。
export const GET_PRODUCTS_SUCCESS = 'GET_PRODUCTS_SUCCESS'
export const GET_PRODUCTS_FAILED = 'GET_PRODUCTS_FAILED';
export const GET_CART_SUCCESS = 'GET_CART_SUCCESS';
export const ADD_TO_CART_SUCCESS = 'ADD_TO_CART_SUCCESS';
export const REMOVE_FROM_CART_SUCCESS = 'REMOVE_FROM_CART_SUCCESS';
这是CartPage
组件的代码:
class CartPage extends React.Component {
componentDidMount() {
this.props.CartAction.getCart();
}
_keyExtractor = (item, index) => item.id;
removeItem(item) {
this.props.CartAction.removeFromCart(item);
}
render() {
const { cart } = this.props;
console.log('render cart', cart)
if (cart && cart.length > 0) {
const Items = <FlatList contentContainerStyle={styles.list}
data={cart}
keyExtractor={this._keyExtractor}
renderItem={({ item }) =>
<View style={styles.lineItem} >
<Image style={styles.image} source={{ uri: item.image }} />
<Text style={styles.text}>{item.name}</Text>
<Text style={styles.text}>{item.quantity}</Text>
<TouchableOpacity style={{ marginLeft: 'auto' }} onPress={() => this.removeItem(item)}><Entypo name="cross" size={30} /></TouchableOpacity>
</View>
}
/>;
return (
<View style={styles.container}>
{Items}
</View>
)
} else {
return (
<View style={styles.container}>
<Text>Cart is empty!</Text>
</View>
)
}
}
}
正如你所看到的,我们使用了一个FlatList
来遍历购物车物品。它接受一个数组并创建一个要在屏幕上显示的项目列表。
结论
您可以在app.json
文件中配置有关应用程序的信息,例如名称和图标。该应用程序可以在npm安装exp之后发布。
总结一下:
- 我们现在有一个体面的电子商务应用程序与React Native;
- 世博会可用于在智能手机上运行该项目;
- 可以使用现有的后端技术,如WordPress;
- Redux可用于管理整个应用程序的状态;
- Web开发人员,特别是React开发人员可以利用这些知识构建更大的应用程序
对于完整的应用程序,您可以在Github上访问我的项目并克隆它。随意分叉并进一步改进。作为练习,您可以继续在项目中构建更多功能,例如:
- 结帐页面,
- 身份验证,
- 将购物车数据存储在AsyncStorage中,以便关闭应用程序不会清除购物车。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/262697.html