React-Native + ts + mobx 项目

笔记

React-Native + ts + mobx 项目

1.构建一个RN项目

npm install -g expo-cli
expo init foodrn-app
cd foodrn-app
npm start # 也可以使用命令: expo start

2.写底部tab栏

yarn add react-native-tab-navigator -S
yarn add @types/react-native-tab-navigator

创建首页

//app.tsx

import React from 'react';
import Index from './pages/index/Index'
export default function App() {
  return (
    <Index />
  );
}

//index/Index.tsx
// pages/index/Index.tsx
import React, { Component } from 'react'
import { Text, View, Image, StyleSheet } from 'react-native'
// 引入tab插件
import TabNavigator from 'react-native-tab-navigator'
import cookbook from './../../assets/images/cookbook.png'
import cookbookActive from './../../assets/images/cookbook-active.png'
import kind from './../../assets/images/menu.png'
import kindActive from './../../assets/images/menu-active.png'
import location from './../../assets/images/location.png'
import locationActive from './../../assets/images/location-active.png'
import more from './../../assets/images/more.png'
import moreActive from './../../assets/images/more-active.png'

import styles from './style_index'
interface Props {
  
}

interface State {
    selectedTab: string
}

export default class Index extends Component<Props, State> {
  constructor(props: Props) {
    super(props)
  }
  
  state: State = {
    selectedTab:'home'
  }

  componentDidMount() {
    
  }

  render() {
    return (
      <TabNavigator
        // tabBarStyle={styles.tabBarStyle}
      >
            <TabNavigator.Item
                selected={this.state.selectedTab === 'home'}
                title="首页"
                renderIcon={() => <Image source={ cookbook } style = {styles.icon} />}
                renderSelectedIcon={() => <Image source={ cookbookActive } style = {styles.icon} />}
                onPress={() => this.setState({ selectedTab: 'home' })}>
                <View><Text>菜谱大全</Text></View>
            </TabNavigator.Item>  

            <TabNavigator.Item
                selected={this.state.selectedTab === 'kind'}
                title="分类"
                renderIcon={() => <Image source={ kind } style = {styles.icon} />}
                renderSelectedIcon={() => <Image source={ kindActive } style = {styles.icon} />}
                onPress={() => this.setState({ selectedTab: 'kind' })}>
                <View><Text>分类</Text></View>
            </TabNavigator.Item>  

            <TabNavigator.Item
                selected={this.state.selectedTab === 'location'}
                title="地图"
                renderIcon={() => <Image source={ location } style = {styles.icon} />}
                renderSelectedIcon={() => <Image source={ locationActive } style = {styles.icon} />}
                onPress={() => this.setState({ selectedTab: 'location' })}>
                <View><Text>地图</Text></View>
            </TabNavigator.Item>
            
            <TabNavigator.Item
                selected={this.state.selectedTab === 'more'}
                title="更多"
                renderIcon={() => <Image source={ more } style = {styles.icon} />}
                renderSelectedIcon={() => <Image source={ moreActive } style = {styles.icon} />}
                onPress={() => this.setState({ selectedTab: 'more' })}>
                <View><Text>更多</Text></View>
            </TabNavigator.Item>
            
        </TabNavigator>
    )
  }
}

抽离出来的样式

//index/index_style.ts
import { StyleSheet } from 'react-native'

export default StyleSheet.create({
    titleStyle: {
        color:'#666'
    },
    tabBarStyle: {
        paddingBottom: 34,
        height: 80
    },
    selectedTitleStyle: {
        color: '#000'
    },
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
    icon: {
        height:30,
        width: 30
    }
})

需要引用图片所以需要配置一个images.d.ts文件

//images.d.ts
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.svg'
declare module '*.gif'
declare module '*.webp'

4. tabbar 的兼容处理

安装 expo-device

npm i expo-device -S
// 载入模块
import * as Device from 'expo-device'

// 在 TabNavigator 上修改 tabBarStyle
<TabNavigator
  tabBarStyle={
    Device.deviceName === 'iPhone Xʀ' ? styles.tabBarStyle : null
  }

>// **** 将刘海屏的手机名称依次写进去 ****
>const arr = ["iPhone 12 Pro Max"]

tabBarStyle = { arr.includes((Device.deviceName as string)) ? styles.tabBarStyle : {} }

5.引入antd

yarn add @ant-design/react-native

按需加载

yarn add babel-plugin-import
// .babelrc or babel-loader option
{
  "plugins": [
    ["import", { libraryName: "@ant-design/react-native" }] // 与 Web 平台的区别是不需要设置 style
  ]
}

然后再模块里面就可以使用了

import { Button } from '@ant-design/react-native'

6. 引入轮播组件

创建一个Home.tsx文件放轮播图和热门分类

//home/Home.tsx
import React, { Component } from 'react'
import Swiper from './Swiper'
import HotCate from './HotCate'

interface Props {

}
interface State {
    
}

class Home extends Component< Props, State > {
    render (){
        return(
            <>
            <Swiper />
            {/* <HotCate /> */}
            </>
        )
    }
}
export default Home

轮播图组件

需要下载

yarn add @react-native-community/viewpager
//home/Swiper.tsx
import React, { Component } from 'react'
import { View, Text } from 'react-native'
import { Carousel  } from '@ant-design/react-native'

import styles from './style_index'
interface Props {

}
interface State {
    
}

class Swiper extends Component< Props, State > {
    render () {
       return (
        <Carousel
            style={styles.wrapper}
            selectedIndex={2}
            autoplay
            infinite
          >
            <View
              style={[styles.containerHorizontal, { backgroundColor: 'red' }]}
            >
              <Text>Carousel 1</Text>
            </View>
            <View
              style={[styles.containerHorizontal, { backgroundColor: 'blue' }]}
            >
              <Text>Carousel 2</Text>
            </View>
            <View
              style={[
                styles.containerHorizontal,
                { backgroundColor: 'yellow' },
              ]}
            >
              <Text>Carousel 3</Text>
            </View>
            <View
              style={[styles.containerHorizontal, { backgroundColor: 'aqua' }]}
            >
              <Text>Carousel 4</Text>
            </View>
            <View
              style={[
                styles.containerHorizontal,
                { backgroundColor: 'fuchsia' },
              ]}
            >
              <Text>Carousel 5</Text>
            </View>
          </Carousel>
       )
    }
}
export default Swiper

7. 获取轮播图数据

封装一个fetch请求文件

//utils/request.ts

export const get = (url: string) => {
    return fetch(url, {
      method: 'get'
    })
    .then(response => response.json())
    .then(result => {
      return result.data
    })
  }

再需要使用的组件中引入

//Swiper.tsx
import React, { Component } from 'react'
import { View, Text, Image } from 'react-native'
import { Carousel  } from '@ant-design/react-native'

//数据请求
import { get } from './../../utils/request'

import styles from './style_index'
interface Banner {
    bannerid: string,
    bannerimg: string
}
interface Props {

}
interface State {
    list: Array<Banner>
}

class Swiper extends Component< Props, State > {
  state: State = {
    list: []
  }
    async componentDidMount () {
        let list = await get('http://10.20.159.162:3001/api/banner')
        console.log(list)
        this.setState({list})
    }
    render () {
       return (
        <Carousel
            style={styles.wrapper}
            autoplay
            infinite
          >
         {
             this.state.list.map(item => {
                return (
                    <Image
                    source = {{uri: item.bannerimg}}
                    key = {item.bannerid}
                    style={styles.containerHorizontal}
                  >
                  </Image>
                    
                )
             })
             
         }
           
          </Carousel>
       )
    }
}
export default Swiper
文件用到的样式封装
//home/style_index.ts
import React, { Component } from 'react'
import { View, Text, Image } from 'react-native'
import { Carousel  } from '@ant-design/react-native'

// 数据请求
import { get } from './../../utils/request'

import styles from './style_index'
// 定义获取到的数据类型
interface Banner {
    bannerid: string,
    bannerimg: string
}
interface Props {

}
interface State {
    list: Array<Banner>
}

class Swiper extends Component< Props, State > {
  state: State = {
    list: []
  }
    async componentDidMount () {
        let list = await get('http://10.20.159.162:3001/api/banner')
        console.log(list)
        this.setState({list})
    }
    render () {
       return (
        <Carousel
            style={styles.wrapper}
            autoplay
            infinite
          >
         {
             this.state.list.map(item => {
                return (
                    <Image
                    source = {{uri: item.bannerimg}}
                    key = {item.bannerid}
                    style={styles.containerHorizontal}
                  >
                  </Image>
                    
                )
             })
             
         }
           
          </Carousel>
       )
    }
}
export default Swiper

8. Mock模拟数据

cnpm i json-server -g

切换接口

切换接口//单接口
json-server cookbook-hotcat.json --watch --port=3003

// 让手机可见需要更改ip
json-server mock.js --watch --host=10.20.159.162

渲染页面 HotCate.tex

import React, { Component } from 'react'
import { View, Text } from 'react-native'
// 请求数据
import { get } from './../../utils/request'
// 导入宫格布局
import { Grid } from '@ant-design/react-native'
import styles from './style_index'
interface HotCate {
    img: string,
    title: string,
}
interface Props {

}
interface State {
    list: Array<HotCate>
}

class HotCate extends Component< Props, State > {
    // 数据
    state: State = {
        list:[]
    }
    // 数据
    async componentDidMount (){
    let list = await get('http://10.20.159.162:3000/hotcat')
    console.log(list)
    this.setState({list})
    }
   
    render () {
        return (
        <View >
            <Text style = {styles.hottitle}>热门分类</Text>
            <Grid
                // 数据
                data={ this.state.list }
                // 行数
                columnNum={ 4 }
                // 自定义样式
                itemStyle = {{height:60}}
                renderItem = {(el,index) => {
                return <View style= {styles.hotcat}>
                    <Text>{el.title}</Text>
                    </View>
                }}
                carouselProps={{
                style: {
                    width: '100%',
                    height: 320,
                },
                }}
            />
        </View>
           
        )
    }
}
export default HotCate

轮播图数据变更

import React, { Component } from 'react'
import { View, Text, Image } from 'react-native'
import { Carousel  } from '@ant-design/react-native'

// 数据请求
import { get } from './../../utils/request'

import styles from './style_index'
// 定义获取到的数据类型
interface Banner {
    id: string,
    img: string
}
interface Props {

}
interface State {
    list: Array<Banner>
}

class Swiper extends Component< Props, State > {
  state: State = {
    list: []
  }
    async componentDidMount () {
        let list = await get('http://10.20.159.162:3000/swiper')
        this.setState({list})
    }
    render () {
       return (
        <Carousel
            style={styles.wrapper}
            autoplay
            infinite
          >
         {
             this.state.list.map(item => {
                return (
                    <Image
                    source = {{uri: item.img}}
                    key = {item.id}
                    style={styles.containerHorizontal}
                  >
                  </Image>
                    
                )
             })
             
         }
           
          </Carousel>
       )
    }
}
export default Swiper

9. 引入状态管理器

安装mobx状态管理器

yarn add mobx mobx-react
//安装的都是最新版本

旧版本使用方法

// mobx 5 
import { observable, action, computed } from 'mobx'
import { get } from './../utils/request'
interface Ilist {
  id: string
  name: string
  img: string
  all_click: string
  favorites: string
}
class Store {
  @observable list: Array<Ilist> = []

  @action
  async getList () {
    let list = await get('http://www.wudaxun.com:3000/swiper')
    this.list = list
  }
}
export default new Store()

mobx6使用方法

// mobx 6
import { makeAutoObservable } from 'mobx'
import { get } from './../utils/request'
interface Ilist {
  id: string
  name: string
  img: string
  all_click: string
  favorites: string
}
class Store {
  list: Array<Ilist> = []

  constructor () {
    makeAutoObservable(this)
  }

  async getList () {
    let list = await get('http://www.wudaxun.com:3000/swiper')
    this.list = list
  }
}
export default new Store()

定义一个store文件夹

//store/index.ts
import { makeAutoObservable, observe } from 'mobx'
import { get } from './../utils/request'

// 接口
interface Ilist {
    id: string,
    img: string,
    name: string,
    all_click: string,
    favorites: string
}
// 定义状态管理器
class Store {
    list: Array<Ilist> = []
    constructor (){
        makeAutoObservable(this)
    }
    // 异步请求数据
    async getList(){
        let list = await get('http://192.168.1.103:3000/swiper')
        this.list = list
    }
}
const store = new Store()
export default store

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容