react-native + DVA + react-native-snap-carousel

react-native + DVA + react-native-snap-carousel【轮播图】

  • 安装
yarn add react-native-snap-carousel
yarn add @types/react-native-snap-carousel -D

// DVA的使用

// src/config/dva.ts
import { create } from 'dva-core-ts'
import createLoading from 'dva-loading-ts'
import models from '@/models/index'

const app = create({
  onError(err) {
    console.log(err)
  },
})
models.forEach((model) => {
  app.model(model)
})
app.use(createLoading())
app.start()

export default app._store

// src/index.tsx
import React from 'react'
import Navigator from './navigator'
import { Provider } from 'react-redux'
import store from '@/config/dva'
import { StatusBar } from 'react-native'
import '@/config/http'

export default class extends React.Component {
  render() {
    return (
      <Provider store={store}>
        {/* 顶部状态栏组件 */}
        <StatusBar
          backgroundColor="transparent"
          barStyle="dark-content"
          translucent
        />
        <Navigator />
      </Provider>
    )
  }
}

// modal 层

// index.ts
import home from './home'
import { DvaLoadingState } from 'dva-loading-ts'

const models = [home, category, albumModel]

export type RootState = {
  home: typeof home.state
  loading: DvaLoadingState
}

export default models


// cateory.ts
import { Model, Effect } from 'dva-core-ts'
import { Reducer } from 'redux'
import axios from 'axios'
import { RootState } from './index'


// 轮播图
const CAROUSEL_URL = '/mock/20/carousel'

export interface ICarousel {
  id: string
  image: string
  colors: [string, string]
}

export interface HomeState {
  carousels: ICarousel[]
  activeCarouseIndex: number // 当前轮播图的下标
}

interface HomeModel extends Model {
  namespace: 'home'
  state: HomeState
    reducers: {
    setState: Reducer<HomeState>
  }
  effects: {
    fetchCarousels: Effect
  }
}

const initialState: HomeState = {
  carousels: [],
  activeCarouseIndex: 0,
}

const homeModel: HomeModel = {
  namespace: 'home',
  state: initialState,
  reducers: {
    setState(state = initialState, { payload }) {
      return {
        ...state,
        ...payload,
      }
    },
  },
  effects: {
    *fetchCarousels(_, { call, put }) {
      const { data } = yield call(axios.get, CAROUSEL_URL)
      yield put({
        type: 'setState',
        payload: {
          carousels: data,
        },
      })
    },
  },
}

export default homeModel

// view层

import React from 'react'
import { View, StyleSheet } from 'react-native'
import SnapCarousel, {
  ParallaxImage,
  Pagination,
  AdditionalParallaxProps
} from 'react-native-snap-carousel'
import { ICarousel } from 'models/home'
import { viewportWidth, wp, hp } from '@/utils/index'
import { connect, ConnectedProps } from 'react-redux'
import { RootState } from '@/models/index'

const sliderWidth = viewportWidth
const sideWidth = wp(90)
export const sideHeight = hp(26)
const itemWidth = sideWidth + wp(2) * 2

const mapStateToProps = ({ home }: RootState) => ({
  data: home.carousels,
  activeCarouseIndex: home.activeCarouseIndex,
})

const connector = connect(mapStateToProps)

type ModelState = ConnectedProps<typeof connector>

interface IProps extends ModelState {
}

class Carousel extends React.Component<IProps> {

  onSnapToItem = (index: number) => {
    const { dispatch } = this.props
    dispatch({
      type: 'home/setState',
      payload: {
        activeCarouseIndex: index,
      }
    })
  }

  renderItem = ({ item }: { item: ICarousel }, parallaxProps?: AdditionalParallaxProps) => {
    return (
      <ParallaxImage
        source={{ uri: item.image }}
        style={styles.image}
        containerStyle={styles.imageContainer}
        parallaxFactor={0.8} // 视察参数
        showSpinner
        spinnerColor="rgba(0, 0, 0, 0.25)"
        {...parallaxProps}
      />
    )
  }

  get pagination() {
    const { data, activeCarouseIndex } = this.props
    return (
      <View style={styles.paginationWrapper}>
        <Pagination
          containerStyle={styles.paginationContainer}
          dotContainerStyle={styles.dotContainer}
          dotStyle={styles.dot}
          activeDotIndex={activeCarouseIndex}
          dotsLength={data.length}
          inactiveDotScale={0.7}
          inactiveDotOpacity={0.4}
        />
      </View>
    )
  }

  render() {
    const { data } = this.props
    return (
      <View>
        <SnapCarousel
          data={data}
          renderItem={this.renderItem}
          sliderWidth={sliderWidth}
          itemWidth={itemWidth}
          hasParallaxImages
          onSnapToItem={this.onSnapToItem}
          loop
          autoplay
        />
        {this.pagination}
      </View>
    )
  }
}

const styles = StyleSheet.create({
  imageContainer: {
    width: itemWidth,
    height: sideHeight,
    borderRadius: 8,
  },
  image: {
    ...StyleSheet.absoluteFillObject,
    resizeMode: 'cover',
  },
  paginationWrapper: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  paginationContainer: {
    position: 'absolute',
    top: -20,
    backgroundColor: 'rgba(0, 0, 0, 0.35)',
    paddingHorizontal: 3,
    paddingVertical: 4,
    borderRadius: 8,
  },
  dotContainer: {
    marginHorizontal: 6,
  },
  dot: {
    width: 6,
    height: 6,
    borderRadius: 3,
    backgroundColor: 'rgba(255, 255, 255, 0.92)'
  }
})

export default connector(Carousel)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值