溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

發(fā)布時(shí)間:2021-06-17 16:56:50 來(lái)源:億速云 閱讀:294 作者:Leah 欄目:web開發(fā)

本篇文章給大家分享的是有關(guān)使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

、技術(shù)點(diǎn)

  • MVVM框架:react / react-native / react-native-cli

  • 狀態(tài)管理:react-redux / redux

  • 頁(yè)面導(dǎo)航:react-navigation

  • rn彈窗組件:rnPop

  • 打包工具:webpack 2.0

  • 輪播組件:react-native-swiper

  • 圖片/相冊(cè):react-native-image-picker

{
 "name": "RN_ChatRoom",
 "version": "0.0.1",
 "aboutMe": "QQ:282310962 、 wx:xy190310",
 "dependencies": {
  "react": "16.8.6",
  "react-native": "0.60.4"
 },
 "devDependencies": {
  "@babel/core": "^7.5.5",
  "@babel/runtime": "^7.5.5",
  "@react-native-community/async-storage": "^1.6.1",
  "@react-native-community/eslint-config": "^0.0.5",
  "babel-jest": "^24.8.0",
  "eslint": "^6.1.0",
  "jest": "^24.8.0",
  "metro-react-native-babel-preset": "^0.55.0",
  "react-native-gesture-handler": "^1.3.0",
  "react-native-image-picker": "^1.0.2",
  "react-native-swiper": "^1.5.14",
  "react-navigation": "^3.11.1",
  "react-redux": "^7.1.0",
  "react-test-renderer": "16.8.6",
  "redux": "^4.0.4",
  "redux-thunk": "^2.3.0"
 },
 "jest": {
  "preset": "react-native"
 }
}

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

◆ App全屏幕啟動(dòng)頁(yè)splash模板

react-native如何全屏啟動(dòng)? 設(shè)置StatusBar頂部條背景為透明 translucent={true},并配合RN動(dòng)畫Animated

/**
 * @desc 啟動(dòng)頁(yè)面
 */

import React, { Component } from 'react'
import { StatusBar, Animated, View, Text, Image } from 'react-native'

export default class Splash extends Component{
  constructor(props){
    super(props)
    this.state = {
      animFadeIn: new Animated.Value(0),
      animFadeOut: new Animated.Value(1),
    }
  }

  render(){
    return (
      <Animated.View style={[GStyle.flex1DC_a_j, {backgroundColor: '#1a4065', opacity: this.state.animFadeOut}]}>
        <StatusBar backgroundColor='transparent' barStyle='light-content' translucent={true} />

        <View style={GStyle.flex1_a_j}>
          <Image source={require('../assets/img/ic_default.jpg')} style={{borderRadius: 100, width: 100, height: 100}} />
        </View>
        <View style={[GStyle.align_c, {paddingVertical: 20}]}>
          <Text style={{color: '#dbdbdb', fontSize: 12, textAlign: 'center',}}>RN-ChatRoom v1.0.0</Text>
        </View>
      </Animated.View>
    )
  }

  componentDidMount(){
    // 判斷是否登錄
    storage.get('hasLogin', (err, object) => {
      setTimeout(() => {
        Animated.timing(
          this.state.animFadeOut, {duration: 300, toValue: 0}
        ).start(()=>{
          // 跳轉(zhuǎn)頁(yè)面
          util.navigationReset(this.props.navigation, (!err && object && object.hasLogin) ? 'Index' : 'Login')
        })
      }, 1500);
    })
  }
}

◆ RN本地存儲(chǔ)技術(shù)async-storage

/**
 * @desc 本地存儲(chǔ)函數(shù)
 */
import AsyncStorage from '@react-native-community/async-storage'
export default class Storage{
  static get(key, callback){
    return AsyncStorage.getItem(key, (err, object) => {
      callback(err, JSON.parse(object))
    })
  }
  static set(key, data, callback){
    return AsyncStorage.setItem(key, JSON.stringify(data), callback)
  }
  static del(key){
    return AsyncStorage.removeItem(key)
  }
  static clear(){
    AsyncStorage.clear()
  }
}
global.storage = Storage

聲明全局global變量,只需在App.js頁(yè)面一次引入、多個(gè)頁(yè)面均可調(diào)用。

storage.set('hasLogin', { hasLogin: true })
storage.get('hasLogin', (err, object) => { ... })

◆ App主頁(yè)面模板及全局引入組件

import React, { Fragment, Component } from 'react'
import { StatusBar } from 'react-native'
// 引入公共js
import './src/utils/util'
import './src/utils/storage'
// 導(dǎo)入樣式
import './src/assets/css/common'
// 導(dǎo)入rnPop彈窗
import './src/assets/js/rnPop/rnPop.js'
// 引入頁(yè)面路由
import PageRouter from './src/router'
class App extends Component{
 render(){
  return (
   <Fragment>
    {/* <StatusBar backgroundColor={GStyle.headerBackgroundColor} barStyle='light-content' /> */}
    {/* 頁(yè)面 */}
    <PageRouter />
    {/* 彈窗模板 */}
    <RNPop />
   </Fragment>
  )
 }
}

export default App

◆ react-navigation頁(yè)面導(dǎo)航器/地址路由、底部tabbar

由于react-navigation官方頂部導(dǎo)航器不能滿足需求,如是自己封裝了一個(gè),功能效果有些類似微信導(dǎo)航。

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

export default class HeaderBar extends Component {
  constructor(props){
    super(props)
    this.state = {
      searchInput: ''
    }
  }
  render() {
    /**
     * 更新
     * @param { navigation | 頁(yè)面導(dǎo)航 }
     * @param { title | 標(biāo)題 }
     * @param { center | 標(biāo)題是否居中 }
     * @param { search | 是否顯示搜索 }
     * @param { headerRight | 右側(cè)Icon按鈕 }
     */
    let{ navigation, title, bg, center, search, headerRight } = this.props
    return (
      <View style={GStyle.flex_col}>
        <StatusBar backgroundColor={bg ? bg : GStyle.headerBackgroundColor} barStyle='light-content' translucent={true} />
        <View style={[styles.rnim__topBar, GStyle.flex_row, {backgroundColor: bg ? bg : GStyle.headerBackgroundColor}]}>
          {/* 返回 */}
          <TouchableOpacity style={[styles.iconBack]} activeOpacity={.5} onPress={this.goBack}><Text style={[GStyle.iconfont, GStyle.c_fff, GStyle.fs_18]}>&#xe63f;</Text></TouchableOpacity>
          {/* 標(biāo)題 */}
          { !search && center ? <View style={GStyle.flex1} /> : null }
          {
            search ? 
            (
              <View style={[styles.barSearch, GStyle.flex1, GStyle.flex_row]}>
                <TextInput onChangeText={text=>{this.setState({searchInput: text})}} style={styles.barSearchText} placeholder='搜索' placeholderTextColor='rgba(255,255,255,.6)' />
              </View>
            )
            :
            (
              <View style={[styles.barTit, GStyle.flex1, GStyle.flex_row, center ? styles.barTitCenter : null]}>
                { title ? <Text style={[styles.barCell, {fontSize: 16, paddingLeft: 0}]}>{title}</Text> : null }
              </View>
            )
          }
          {/* 右側(cè) */}
          <View style={[styles.barBtn, GStyle.flex_row]}>
            { 
              !headerRight ? null : headerRight.map((item, index) => {
                return(
                  <TouchableOpacity style={[styles.iconItem]} activeOpacity={.5} key={index} onPress={()=>item.press ? item.press(this.state.searchInput) : null}>
                    {
                      item.type === 'iconfont' ? item.title : (
                        typeof item.title === 'string' ? 
                        <Text style={item.style ? item.style : null}>{`${item.title}`}</Text>
                        :
                        <Image source={item.title} style={{width: 24, height: 24, resizeMode: 'contain'}} />
                      )
                    }
                    {/* 圓點(diǎn) */}
                    { item.badge ? <View style={[styles.iconBadge, GStyle.badge]}><Text style={GStyle.badge_text}>{item.badge}</Text></View> : null }
                    { item.badgeDot ? <View style={[styles.iconBadgeDot, GStyle.badge_dot]}></View> : null }
                  </TouchableOpacity>
                )
              })
            }
          </View>
        </View>
      </View>
    )
  }
  goBack = () => {
    this.props.navigation.goBack()
  }
}
// 創(chuàng)建底部TabBar
const tabNavigator = createBottomTabNavigator(
  // tabbar路由(消息、通訊錄、我)
  {
    Index: {
      screen: Index,
      navigationOptions: ({navigation}) => ({
        tabBarLabel: '消息',
        tabBarIcon: ({focused, tintColor}) => (
          <View>
            <Text style={[ GStyle.iconfont, GStyle.fs_20, {color: (focused ? tintColor : '#999')} ]}>&#xe642;</Text>
            <View style={[GStyle.badge, {position: 'absolute', top: -2, right: -15,}]}><Text style={GStyle.badge_text}>12</Text></View>
          </View>
        )
      })
    },
    Contact: {
      screen: Contact,
      navigationOptions: {
        tabBarLabel: '通訊錄',
        tabBarIcon: ({focused, tintColor}) => (
          <View>
            <Text style={[ GStyle.iconfont, GStyle.fs_20, {color: (focused ? tintColor : '#999')} ]}>&#xe640;</Text>
          </View>
        )
      }
    },
    Ucenter: {
      screen: Ucenter,
      navigationOptions: {
        tabBarLabel: '我',
        tabBarIcon: ({focused, tintColor}) => (
          <View>
            <Text style={[ GStyle.iconfont, GStyle.fs_20, {color: (focused ? tintColor : '#999')} ]}>&#xe61e;</Text>
            <View style={[GStyle.badge_dot, {position: 'absolute', top: -2, right: -6,}]}></View>
          </View>
        )
      }
    }
  },
  // tabbar配置
  {
    ...
  }
)

◆ RN聊天頁(yè)面功能模塊

1、表情處理:原本是想著使用圖片表情gif,可是在RN里面textInput文本框不能插入圖片,只能通過(guò)定義一些特殊字符 :66: (:12 [奮斗] 解析表情,處理起來(lái)有些麻煩,而且圖片多了影響性能,如是就改用emoj表情符。

使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室

faceList: [
  {
    nodes: [
      '?','?','?','?','?','?','?',
      '?','?','?','?','?','?','?',
      '?','?','?','?','?','?','del',
    ]
  },
  ...
  {
    nodes: [
      '?','?','?','?','?','?','?',
      '?','?','?','?','?','??','??',
      '??','??','???','????','????','?????','del',
    ]
  },
  ...
]

2、光標(biāo)定位:在指定光標(biāo)處插入內(nèi)容,textInput提供了光標(biāo)起始位置

let selection = this.textInput._lastNativeSelection || null;
this.textInput.setNativeProps({
  selection : { start : xxx, end : xxx}
})

3、textInput判斷內(nèi)容是否為空,過(guò)濾空格、回車

isEmpty = (html) => {
  return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == ""
}
/**
 * 聊天模塊JS----------------------------------------------------
 */
// ...滾動(dòng)至聊天底部
scrollToBottom = (t) => {
  let that = this
  this._timer = setTimeout(() => {
    that.refs.scrollView.scrollToEnd({animated: false})
  }, t ? 16 : 0);
}
// ...隱藏鍵盤
hideKeyboard = () => {
  Keyboard && Keyboard.dismiss()
}
// 點(diǎn)擊表情
handlePressEmotion = (img) => {
  if(img === 'del') return
  let selection = this.editorInput._lastNativeSelection || null;
  if (!selection){
    this.setState({
      editorText : this.state.editorText + `${img}`,
      lastRange: this.state.editorText.length
    })
  }
  else {
    let startStr = this.state.editorText.substr(0 , this.state.lastRange ? this.state.lastRange : selection.start)
    let endStr = this.state.editorText.substr(this.state.lastRange ? this.state.lastRange : selection.end)
    this.setState({
      editorText : startStr + `${img}` + endStr,
      lastRange: (startStr + `${img}`).length
    })
  } 
}
// 發(fā)送消息
isEmpty = (html) => {
  return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == ""
}
handleSubmit = () => {
  // 判斷是否為空值
  if(this.isEmpty(this.state.editorText)) return
  let _msg = this.state.__messageJson
  let _len = _msg.length
  // 消息隊(duì)列
  let _data = {
    id: `msg${++_len}`,
    msgtype: 3,
    isme: true,
    avator: require('../../../assets/img/uimg/u__chat_img11.jpg'),
    author: '王梅(Fine)',
    msg: this.state.editorText,
    imgsrc: '',
    videosrc: ''
  }
  _msg = _msg.concat(_data)
  this.setState({ __messageJson: _msg, editorText: '' })
  this.scrollToBottom(true)
}

// >>> 【選擇區(qū)功能模塊】------------------------------------------
// 選擇圖片
handleLaunchImage = () => {
  let that = this
  ImagePicker.launchImageLibrary({
    // title: '請(qǐng)選擇圖片來(lái)源',
    // cancelButtonTitle: '取消',
    // takePhotoButtonTitle: '拍照',
    // chooseFromLibraryButtonTitle: '相冊(cè)圖片',
    // customButtons: [
    //   {name: 'baidu', title: 'baidu.com圖片'},
    // ],
    // cameraType: 'back',
    // mediaType: 'photo',
    // videoQuality: 'high',
    // maxWidth: 300,
    // maxHeight: 300,
    // quality: .8,
    // noData: true,
    storageOptions: {
      skipBackup: true,
    },
  }, (response) => {
    // console.log(response)
    if(response.didCancel){
      console.log('user cancelled')
    }else if(response.error){
      console.log('ImagePicker Error')
    }else{
      let source = { uri: response.uri }
      // let source = {uri: 'data:image/jpeg;base64,' + response.data}
      that.setState({ imgsrc: source })
      that.scrollToBottom(true)
    }
  })
}

以上就是使用react native 怎么實(shí)現(xiàn)一個(gè)微信聊天室,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI