React 与 React-Native 使用同一个 meteor 后台
meteor 可以快速构建 pc,移动端,桌面端应用。
最大的优点是:数据库的数据发生变化时,可以实时推送到前端,非常适用于实时展示的应用开发。
在 react,react-native 应用中,可以仅使用同一个 meteor 后台,实时向前端推送数据。
metaor 安装
windows 安装 meteor
官方推荐 chocolatey 安装 meteor。
- 先从 chocolatey 安装 chocolatey
- 然后在命令行中运行
choco install meteor
但是 meteor 安装速度非常慢,一顿搜索之后,找到了 Windows 下通过二进制包安装的下载地址 https://install.meteor.com/windows,搜索来源 https://github.com/meteor/docs/blob/version-NEXT/long-form/alternate-windows-installation.md
OSX/Linux 安装 meteor
安装非常简单
curl https://install.meteor.com/ | sh
验证安装
命令行输入
meteor --version
输出版本号,表示安装成功
Meteor 1.8.1
mongodb 安装
windows 安装 mongodb
https://www.mongodb.com/ 下载安装包安装
OSX 安装 mongodb
brew install mongod
或者下载二进制包安装
是 mongod ,不是 mongodb
mongodb 图形界面
推荐 https://robomongo.org/, 易于使用,也是免费的。
meteor DDP
react,react-native 使用同一个 meteor 后台,所以 meteor 后台要与前端应用分开编写。
这就涉及到 meteor 中后台与前端的数据交互,meteor 中定义了一个 DDP协议。
DDP协议定义了 meteor 后台发布数据,客户端订阅数据的操作。
本应用使用已经编写好了的 DDP 协议库,地址如下: https://github.com/mondora/ddp.js。
创建 meteor 项目
meteor create --bare [project-name]
更多创建参数
meteor help create
meteor 连接 mongodb
meteor 项目启动命令如下:
meteor run
配置端口
meteor run --port 9090
meteor 连接自己的 mongodb
meteor 安装包中集成了 mongodb,默认启动的是集成的 mongodb。
为了连接自己的 mongodb,需要传入参数
MONGO_URL=mongodb://username:password@localhost:27017/[database-name]?authSource=admin meteor run --port 9090
刚开始没加上 authSource=admin 参数,一直连接不上 mongodb,加上之后就好了,根据需要加。
编写 meteor 后台
import {Meteor} from 'meteor/meteor';
// mongodb 的 todo collection
const Todo = new Meteor.Collection('todo');
// 发布数据,前端就可以调用
Meteor.publish('todo', () => {
return Todo.find();
});
/**
* 定义前端调用的方法
*/
Meteor.methods({
// 查找一条数据
getTodo(id) {
return Todo.findOne(id);
},
// 查找所有数据
getAllTodo() {
return Todo.find().fetch();
},
// 新增
addTodo(item) {
return Todo.insert(item);
},
// 删除
removeTodo(id) {
return Todo.remove({_id: id});
},
// 编辑
editTodo(item) {
return Todo.update({_id: item.id}, {$set: item});
},
/**
*
* @param {number 当前页面 从 1 开始} currentPage
* @param {number 单次请求总条数} pageSize
*/
getPageTodo(currentPage = 1, pageSize = 10) {
if (page < 1) {
return null;
}
// meteor 对 mongodb 的操作方法做了封装
// 更多操作请查看 meteor 官方文档
const total = Todo.find().count();
const list = Todo.find(
{},
{
skip: (currentPage - 1) * pageSize,
limit: pageSize,
}
).fetch();
return {total, data: list};
},
});
// 定义对 mongodb 的操作权限
// 若没有定义,则是允许所有增删改查操作
Todo.deny({
// 是否允许 mongodb 的新增操作, 返回 true 表示允许,否则不允许
insert() {
return true;
},
update() {
return true;
},
remove() {
return true;
},
});
export default Todo;
前端调用
定义高阶组件
为了代码复用,定义了高阶组件,react 与 react-native 可以共用
// meteor.js
import React, {Component} from 'react';
import DDP from 'ddp.js';
/**
* meteor 连接选项
*/
const meteorOptions = {
endpoint: 'ws://192.168.31.121:9090/websocket',// react-native 不支持 localhost,127.0.0.1,请替换为自己的 IPv4 地址
SocketConstructor: WebSocket,
reconnectInterval: 10000,// 重连间隔
autoConnect: true,// 是否自动连接
autoReconnect: true,// 是否自动重连
};
const PUBLIC_EVENTS = [
// 'ready',
// 'nosub',
'added',
'changed',
'removed',
// 'result',
// 'updated',
// 'error',
];
export default (WrapperComponent, {collectionName, methodName}) => {
class MeteorWrapper extends Component {
ddp = new DDP(meteorOptions);
lockRequest = false
recordSubscriptions = {};
state = {
meteorList: [],
initOver: false,
};
componentDidMount() {
if (!this.ddp) {
console.error(`数据推送未连接上服务器!`);
return;
}
// 添加订阅
this.addSubscription();
}
componentWillUnmount() {
// 取消订阅
this.removeSubscription();
// 断开连接
this.ddp.disconnect();
}
getDataResult() {
// 防止初始化请求次数过多
if (this.lockRequest) {
return
}
this.lockRequest = true
const {ddp} = this;
const self = this;
/**
* 调用后台定义的方法, 前端传递数组参数,meteor 后台接受到的是列表参数
*/
ddp.method(methodName, [1, 10]);
ddp.on('result', data => {
const {result} = data;
console.log(data);
self.setState({
meteorList: result,
initOver: true,
});
self.lockRequest = false
});
}
componentDidCatch(error, info) {
console.error(error, info);
}
addSubscription() {
if (!collectionName) {
console.error('mongodb collection 为空!');
return;
}
const {ddp} = this;
const self = this;
// 订阅数据
self.recordSubscriptions[collectionName] = ddp.sub(collectionName);
PUBLIC_EVENTS.forEach(event => {
ddp.on(event, () => {
console.log(event)
self.getDataResult();
});
});
ddp.on('error', error => {
console.error(`服务器推送数据错误,错误消息:${error}`)
});
ddp.on('ready', () => {
self.getDataResult();
});
}
removeSubscription() {
this.ddp.unsub(this.recordSubscriptions[collectionName]);
}
render() {
return <WrapperComponent {...this.props} {...this.state} />;
}
}
return MeteorWrapper;
};
react 使用示例
import React, {Component} from 'react';
import {List, Skeleton} from 'antd';
import './App.css';
import MeteorWrapper from './meteor'
function App(props) {
const {meteorList = [], initOver} = props
return (
<div className="App">
<List
itemLayout="horizontal"
dataSource={meteorList}
renderItem={item => (
<List.Item key={item.id}>
<Skeleton loading={!initOver} active avatar>
<List.Item.Meta
title={item.name}
description={item.desc}
/>
</Skeleton>
</List.Item>
)}
/>
</div>
);
}
export default MeteorWrapper(App, {
collectionName:'todo',
methodName:'getAllTodo'
})
react-native 使用示例
import React from 'react';
import {StyleSheet, Text, View, FlatList} from 'react-native';
import MeteorWrapper from './meteor'
function App(props) {
const {meteorList = [], initOver} = props
return (
<View style={styles.container}>
<FlatList
data={meteorList}
renderItem={({item}) => (
<View style={styles.item}>
<View style={styles.name}><Text>{item.name}</Text></View>
<View style={styles.desc}><Text>{item.desc}</Text></View>
</View>)}
/>
</View>
);
}
export default MeteorWrapper(App, {
collectionName:'todo',
methodName:'getAllTodo'
})
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
fontSize: 14,
lineHeight: 2,
},
item: {
padding: 10,
borderColor: '#ccc',
borderBottomWidth: 1,
borderStyle: 'solid',
},
name: {
color: '#000',
fontWeight: "900",
fontSize: 24
},
desc: {
color: '#666'
}
});
开启远程调试
运行命令
adb shell input keyevent 82
点击 dev setting
然后点击 Debug server host & port for device
设置为 127.0.0。1:8081
再次运行
adb shell input keyevent 82
点击 Debug js remote ,就会自动弹出调试页面。
IOS 运行报错
错误信息如下,请查看解决 React-Native mac10.14.4 运行报错 error Failed to build iOS project
error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65. To debug build logs further, consider building your app with Xcode.app, by opening reactNative.xcodeproj
React 与 React-Native 使用同一个 meteor 后台的更多相关文章
- React 与 React Native 底层共识:React 是什么
此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React 与 React Native 结合学习的方法,此小节主要介绍 React 的底层原理与 ...
- 一次掌握 React 与 React Native 两个框架
此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React 与 React Native 结合学习的方法. 1. 软件开发语言与框架的学习本质 我 ...
- 用react-service做状态管理,适用于react、react native
转载自:https://blog.csdn.net/wo_shi_ma_nong/article/details/100713151 . react-service是一个非常简单的用来在react.r ...
- 小谈React、React Native、React Web
React有三个东西,React JS 前端Web框架,React Native 移动终端Hybrid框架,React Web是一个源码转换工具(React Native 转 Web,并之所以特别提出 ...
- React的React Native
React的React Native React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React ...
- React Navigation & React Native & React Native Navigation
React Navigation & React Native & React Native Navigation React Navigation https://facebook. ...
- 《React Native 精解与实战》书籍连载「React 与 React Native 简介」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- React Navigation / React Native Navigation 多种类型的导航结合使用,构造合理回退栈
React Navigation 更新到版本5已经是非常完善的一套导航管理组件, 提供了Stack , Tab , Drawer 导航方式 , 那么我们应该怎样设计和组合应用他们来构建一个完美的回退栈 ...
- 重谈react优势——react技术栈回顾
react刚刚推出的时候,讲react优势搜索结果是几十页. 现在,react已经慢慢退火,该用用react技术栈的已经使用上,填过多少坑,加过多少班,血泪控诉也不下千文. 今天,再谈一遍react优 ...
随机推荐
- jquery的$.extend和$.fn.extend作用及区别/用span实现进度条/腾讯云IIS端口号修改
jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(); jQuery.extend(); 虽然 javascript 没有明确的类的概念,但是用类来理解它,会更方便. ...
- MyBatis-Spring中间件逻辑分析(怎么把Mapper接口注册到Spring中)
1. 文档介绍 1.1. 为什么要写这个文档 接触Spring和MyBatis也挺久的了,但是一直还停留在使用的层面上,导致很多时候光知道怎么用,而不知道其具体原理,这样就很难做一 ...
- TestNG监听器实现用例运行失败自动截图、重运行功能
注: 以下内容引自 http://blog.csdn.net/sunnyyou2011/article/details/45894089 (此非原出处,亦为转载,但博主未注明原出处) 使用Testng ...
- 内连接查询 (select * from a join b on a.id = b.id) 与 关联查询 (select * from a , b where a.id = b.id)的区别
转自https://blog.csdn.net/l690781365/article/details/76261093 1.首先了解 on .where 的执行顺序以及效率? from a join ...
- plugin.go 源码阅读
, nil) } if c.client != nil { c.client.Close() } ...
- 关于Python元祖,列表,字典,集合的比较
定义 方法 列表 可以包含不同类型的对象,可以增减元素,可以跟其他的列表结合或者把一个列表拆分,用[]来定义的 eg:aList=[123,'abc',4.56,['inner','list'], ...
- Jmeter----创建第一个接口测试流程
第一步.创建线程 第二步.添加一个HTTP请求 第三步.设置request的请求头信息 根据自己需要填写的请求头信息进行填写,如下是我需要接口测试时填写的请求头 第四步.设置相关的HTTP请求参数,完 ...
- MYSQL—— char 与 varchar的区别!
一.char 和 varchar 的区别: 1)取值范围: char:取值范围:0~255 varchar:取值范围:0~65535 2)空间占用与速度: char: 定长字符串,占用空间大,速度快, ...
- 微服务架构 - 基于Harbor构建本地镜像仓库
之前写过<搭建docker本地镜像仓库并提供权限校验及UI界面>文章,然后有同仁评论道这样做太复杂了,如果Harbor来搭建会更简单同时功能也更强大.于是抽时间研究了基于Harbor构建本 ...
- python中字符串拆分与合并——split()、join()、strip()和replace()
Python3 split()方法 描述split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 语法split()方法语法: str.split(str= ...