taro+react仿微信App聊天实例|taro聊天室
taroChatRoom聊天室是基于taro+react+redux+RN+taropop等技术开发的仿微信App界面聊天IM项目,实现了消息发送、表情动图、预览图片、红包、朋友圈等功能。
Taro多端实践:仿微信聊天室 (H5+小程序+App)
技术实现:
编码/技术:Vscode + react/taro/redux/react-native
iconfont图标:阿里字体图标库
自定义导航栏Navigation + 底部Tabbar
弹窗组件:taroPop(基于Taro封装自定义模态框)
支持编译:H5端 + 小程序 + RN端
项目中顶部导航+tabbar是采用自定义组件模式,具体参看:
Taro自定义Modal对话框组件|taro仿微信、android弹窗
主页面配置
配置页面路径及全局参数,引入公共样式及状态管理
/** * @desc Taro入口页面 app.jsx * @about Q:282310962 wx:xy190310 */ import Taro, { Component } from '@tarojs/taro' import Index from './pages/index' // 引入状态管理redux import { Provider } from '@tarojs/redux' import { store } from './store' // 引入样式 import './app.scss' import './styles/fonts/iconfont.css' import './styles/reset.scss' class App extends Component { config = { pages: [ 'pages/auth/login/index', 'pages/auth/register/index', 'pages/index/index', ... ], window: { backgroundTextStyle: 'light', navigationBarBackgroundColor: '#fff', navigationBarTitleText: 'TaroChat', navigationBarTextStyle: 'black', navigationStyle: 'custom' } } // 在 App 类中的 render() 函数没有实际作用 // 请勿修改此函数 render () { return ( <Provider store={store}> <Index /> </Provider> ) } } Taro.render(<App />, document.getElementById('app'))
Taro表单操作|本地存储处理
在taro中获取表单input值也比较简单,直接使用onInput事件即可
<Input placeholder="请输入手机号/昵称" onInput={this.handleInput.bind(this, 'tel')} />
this.state = { tel: '', pwd: '', } handleInput = (key, e) => { this.setState({ [key]: e.detail.value }) }
通过上面的方法就有简单的获取input值
return ( <View className="taro__container flexDC bg-eef1f5"> <Navigation background='#eef1f5' fixed /> <ScrollView className="taro__scrollview flex1" scrollY> <View className="auth-lgreg"> {/* logo */} <View className="auth-lgreg__slogan"> <View className="auth-lgreg__slogan-logo"> <Image className="auth-lgreg__slogan-logo__img" src={require('../../../assets/taro.png')} mode="aspectFit" /> </View> <Text className="auth-lgreg__slogan-text">欢迎来到Taro-Chatroom</Text> </View> {/* 表单 */} <View className="auth-lgreg__forms"> <View className="auth-lgreg__forms-wrap"> <View className="auth-lgreg__forms-item"> <Input className="auth-lgreg__forms-iptxt flex1" placeholder="请输入手机号/昵称" onInput={this.handleInput.bind(this, 'tel')} /> </View> <View className="auth-lgreg__forms-item"> <Input className="auth-lgreg__forms-iptxt flex1" placeholder="请输入密码" password onInput={this.handleInput.bind(this, 'pwd')} /> </View> </View> <View className="auth-lgreg__forms-action"> <TouchView onClick={this.handleSubmit}><Text className="auth-lgreg__forms-action__btn">登录</Text></TouchView> </View> <View className="auth-lgreg__forms-link"> <Text className="auth-lgreg__forms-link__nav">忘记密码</Text> <Text className="auth-lgreg__forms-link__nav" onClick={this.GoToRegister}>注册账号</Text> </View> </View> </View> </ScrollView> <TaroPop ref="taroPop" /> </View> )
/** * @tpl 登录模板 */ import Taro from '@tarojs/taro' import { View, Text, ScrollView, Image, Input, Button } from '@tarojs/components' import './index.scss' import { connect } from '@tarojs/redux' import * as actions from '../../../store/action'... class Login extends Taro.Component { config = { navigationBarTitleText: '登录' } constructor(props) { super(props) this.state = { tel: '', pwd: '', } } componentWillMount() { // 判断是否登录 storage.get('hasLogin').then(res => { if(res && res.hasLogin) { Taro.navigateTo({url: '/pages/index/index'}) } }) } // 提交表单 handleSubmit = () => { let taroPop = this.refs.taroPop let { tel, pwd } = this.state if(!tel) { taroPop.show({content: '手机号不能为空', time: 2}) }else if(!util.checkTel(tel)) { taroPop.show({content: '手机号格式有误', time: 2}) }else if(!pwd) { taroPop.show({content: '密码不能为空', time: 2}) }else { // ...接口数据 ... storage.set('hasLogin', { hasLogin: true }) storage.set('user', { username: tel }) storage.set('token', { token: util.setToken() }) taroPop.show({ skin: 'toast', content: '登录成功', icon: 'success', time: 2 }) ... } } render () { ... } } const mapStateToProps = (state) => { return {...state.auth} } export default connect(mapStateToProps, { ...actions })(Login)
taro中rn端不支持同步存储,只能改为setStorageSync异步存储了
import Taro from '@tarojs/taro'export default class Storage { static get(key) { return Taro.getStorage({ key }).then(res => res.data).catch(() => '') } static set(key, data){ return Taro.setStorage({key: key, data: data}).then(res => res) } ... }
Taro聊天滚动到消息底部
H5/小程序端则可通过获取createSelectorQuery 来实现滚动到聊天底部,由于RN端不支持createSelectorQuery,则只能另外兼容处理
// 滚动聊天底部 scrollMsgBottom = () => { let query = Taro.createSelectorQuery() query.select('#scrollview').boundingClientRect() query.select('#msglistview').boundingClientRect() query.exec((res) => { // console.log(res) if(res[1].height > res[0].height) { this.setState({ scrollTop: res[1].height - res[0].height }) } }) } scrollMsgBottomRN = (t) => { let that = this this._timer = setTimeout(() => { that.refs.ScrollViewRN.scrollToEnd({animated: false}) }, t ? 16 : 0) }
componentDidMount() { if(process.env.TARO_ENV === 'rn') { this.scrollMsgBottomRN() }else { this.scrollMsgBottom() } }
... // 聊天消息区域 msgPanelClicked = () => { if(!this.state.showFootToolbar) return this.setState({ showFootToolbar: false }) } swtEmojChooseView = (index) => { this.setState({ showFootToolbar: true, showFootViewIndex: index }) } // 表情tab切换 swtEmojTab = (index) => { let lists = this.state.emotionJson for(var i = 0, len = lists.length; i < len; i++) { lists[i].selected = false } lists[index].selected = true this.setState({ emotionJson: lists }) } /* >>> 编辑器/表情处理------------------------------------- */ bindEditorInput = (e) => { this.setState({ editorText: e.detail.value, editorLastCursor: e.detail.cursor }) } bindEditorFocus = (e) => { this.setState({ editorLastCursor: e.detail.cursor }) } bindEditorBlur = (e) => { this.setState({ editorLastCursor: e.detail.cursor }) } handleEmotionTaped = (emoj) => { if(emoj == 'del') return // 在光标处插入表情 let { editorText, editorLastCursor } = this.state let lastCursor = editorLastCursor ? editorLastCursor : editorText.length let startStr = editorText.substr(0, lastCursor) let endStr = editorText.substr(lastCursor) this.setState({ editorText: startStr + `${emoj} ` + endStr }) } ...
最后附上两个vue实例项目,希望能喜欢~~
vue网页版聊天实例:
https://www.cnblogs.com/xiaoyan2017/p/10793728.html
vue+uniapp仿抖音小视频|直播室实例:
https://www.cnblogs.com/xiaoyan2017/p/11835641.html
共同学习,写下你的评论
评论加载中...
相关文章推荐