meteor 能夠快速構建 pc,移動端,桌面端應用。css
最大的優勢是:數據庫的數據發生變化時,能夠實時推送到前端,很是適用於實時展現的應用開發。前端
在 react,react-native 應用中,能夠僅使用同一個 meteor 後臺,實時向前端推送數據。react
github 代碼地址linux
官方推薦 chocolatey 安裝 meteor。ios
choco install meteor
可是 meteor 安裝速度很是慢,一頓搜索以後,找到了 Windows 下經過二進制包安裝的下載地址 https://install.meteor.com/windows,搜索來源 https://github.com/meteor/docs/blob/version-NEXT/long-form/alternate-windows-installation.mdgit
安裝很是簡單github
curl https://install.meteor.com/ | sh
命令行輸入web
meteor --version
輸出版本號,表示安裝成功mongodb
Meteor 1.8.1
https://www.mongodb.com/ 下載安裝包安裝shell
brew install mongod
或者下載二進制包安裝
是 mongod ,不是 mongodb
推薦 https://robomongo.org/, 易於使用,也是免費的。
react,react-native 使用同一個 meteor 後臺,因此 meteor 後臺要與前端應用分開編寫。
這就涉及到 meteor 中後臺與前端的數據交互,meteor 中定義了一個 DDP協議。
DDP協議定義了 meteor 後臺發佈數據,客戶端訂閱數據的操做。
本應用使用已經編寫好了的 DDP 協議庫,地址以下: https://github.com/mondora/ddp.js。
meteor create --bare [project-name]
更多建立參數
meteor help create
meteor 項目啓動命令以下:
meteor run
配置端口
meteor run --port 9090
meteor 安裝包中集成了 mongodb,默認啓動的是集成的 mongodb。
爲了鏈接本身的 mongodb,須要傳入參數
MONGO_URL=mongodb://username:password@localhost:27017/[database-name]?authSource=admin meteor run --port 9090
剛開始沒加上 authSource=admin 參數,一直鏈接不上 mongodb,加上以後就行了,根據須要加。
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; };
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' })
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 ,就會自動彈出調試頁面。
錯誤信息以下,請查看解決 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