我以爲代碼在有些程序員手裏,就好像是畫筆,能夠創造不少東西
不要以爲創意少就叫沒有創意,天天進步一點點,世界更美好
首先源碼地址爲:https://github.com/byk04712/mobx-todos
感謝無私開源的程序員,是大家讓代碼更美好
先看效果
這個是一個todo的mobx小項目,咱們主要看看數據處理部分react
//根App.js文件中,主要是渲染組件main //App.js import React from 'react'; import { AppRegistry } from 'react-native'; import Main from './Main'; AppRegistry.registerComponent('mobx_todos', () => Main);
在main.js中,咱們先來看佈局
git
這個裏面顯示了,實際上是將佈局分紅了上中下三部分程序員
class App extends Component { todoList = new TodoList(); render() { return ( <View style={styles.container}> <Header data={this.todoList}/> <ShowTodos data={this.todoList}/> <Filter data={this.todoList}/> </View> ); } } export default App;
先看header部分代碼,看這個代碼寫的多美麗啊,這個仍是該做者2年前寫的呢~github
class Header extends Component { static propTypes = { data: PropTypes.instanceOf(TodoList) }; addItem = () => { const { data } = this.props; if (this.inputValue === undefined || this.inputValue.replace(/\s+/g, '') === '') { return alert('請輸入任務名稱'); } data.addItem(this.inputValue); // clear input & reset input value this.input.clear(); this.inputValue = ''; //還處理了黃色預警 Keyboard.dismiss(); }; render() { return ( <View style={styles.header}> <TextInput style={styles.input} ref={input => this.input = input} underlineColorAndroid='transparent' placeholder='在此輸入新增的任務' onChangeText={text => this.inputValue = text} maxLength={10} /> <TouchableOpacity onPress={this.addItem} style={styles.button}> <Text style={styles.buttonText}>Add Todo</Text> </TouchableOpacity> </View> ); } }
showtodos裏面卻是沒有什麼很特別的,不太重要的是裏面的小的組件,已經完成和未完成的,還有樣式的處理
react-native
class ShowTodos extends Component { static propTypes = { data: PropTypes.instanceOf(TodoList) }; renderRow = (data) => { return (<TodoItem data={data}/>) }; render() { const { data } = this.props; return ( <View style={styles.showTodos}> <ListView style={styles.listView} enableEmptySections initialListSize={data.items.length} dataSource={ds.cloneWithRows(data.items.slice())} renderRow={this.renderRow} /> </View> ); } }
@observer class TodoItem extends Component { static propTypes = { data: PropTypes.instanceOf(Todo) }; render() { const { data } = this.props; //這個的處理有意思 let flag; if (data.done) { flag = { textDecorationLine: 'line-through' }; } else { flag = { textDecorationLine: 'none' }; } return ( <TouchableOpacity onPress={data.switchDone}> <View style={styles.item}> <Text style={[styles.name, flag]} numberOfLines={1}>{data.name}</Text> <Text style={[styles.done, flag]}>{data.done ? '已完成' : '未完成'}</Text> <TouchableOpacity style={styles.del} onPress={data.remove}> <Text style={styles.delText}>x</Text> </TouchableOpacity> </View> </TouchableOpacity> ); } }
class Todo { id = `${Date.now()}${Math.floor(Math.random()*1000)}`; @observable name = ''; @observable done = false; todos = null; constructor(name, done, todos) { this.name = name; this.done = done; this.todos = todos; } @action('任務 已完成/未完成 狀態切換') switchDone = () => { this.done = !this.done; }; @action('刪除當前項') remove = () => { if (this.todos) { this.todos._items.remove(this); } } }
這個是篩選部分
less
@observer class Filter extends Component { static propTypes = { data: PropTypes.instanceOf(TodoList) }; render() { const { data } = this.props; return ( <View style={styles.filter}> <Text>篩選:</Text> <FilterButton size={data.countAll} active={data.filter === ALL} onPress={data.filterAll}>所有</FilterButton> <FilterButton size={data.countCompleted} active={data.filter === COMPLETED} onPress={data.filterCompleted}>已完成</FilterButton> <FilterButton size={data.countUncompleted} active={data.filter === UNCOMPLETED} onPress={data.filterUncompleted}>未完成</FilterButton> </View> ); } }
看main.js中的所有代碼dom
import React,{ Component, PropTypes } from 'react'; import { TouchableOpacity, Dimensions, StyleSheet, TextInput, ListView, Keyboard, View, Text } from 'react-native'; import { observable, computed, action, useStrict } from 'mobx'; import { observer } from 'mobx-react/native'; // 開啓嚴格模式,建議開啓。開啓後全部修改 observable 的操做都必須放在 action 裏完成 useStrict(true); const { width, height } = Dimensions.get('window'); const contentWidth = width - 60; const [ALL, COMPLETED, UNCOMPLETED] = ['ALL', 'COMPLETED', 'UNCOMPLETED']; const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F7F7F7', alignItems: 'center', paddingVertical: 80 }, header: { width: contentWidth, height: 40, flexDirection: 'row', borderWidth: 1, borderColor: 'green' }, input: { flex: 1, paddingHorizontal: 10 }, button: { width: 80, backgroundColor: 'green', justifyContent: 'center', alignItems: 'center' }, buttonText: { color: 'white' }, showTodos: { borderColor: 'green', borderLeftWidth: 1, borderRightWidth: 1, width: contentWidth, height: height - 300 }, listView: { paddingHorizontal: 10 }, item: { flexDirection: 'row', height: 50, borderBottomColor: '#CCC', borderBottomWidth: StyleSheet.hairlineWidth, justifyContent: 'space-between', alignItems: 'center', }, name: { fontSize: 16, width: contentWidth - 90, overflow: 'hidden' }, done: { fontSize: 12, color: 'gray' }, del: { borderWidth: 1, borderColor: 'gray', width: 20, height: 20, borderRadius: 10 }, delText: { alignSelf: 'center' }, filter: { width: contentWidth, height: 50, borderWidth: 1, borderColor: 'green', flexDirection: 'row', alignItems: 'center', paddingHorizontal: 5 }, condition: { paddingHorizontal: 5, paddingVertical: 7, marginHorizontal: 4, borderWidth: StyleSheet.hairlineWidth, borderColor: 'gray' }, conditionText: { fontSize: 14, letterSpacing: 2 } }); class TodoList { @observable _items = []; @observable filter = ALL; // 初始化3條測試數據 constructor() { this._items.push(new Todo('Travel', true, this)); this._items.push(new Todo('Metting', false, this)); this._items.push(new Todo('Conversation', true, this)); } @computed get items() { return this._items.filter(item => { if (this.filter === ALL) { return item; } else if (this.filter === COMPLETED) { return item.done; } else if (this.filter === UNCOMPLETED) { return !item.done } }); } @computed get countAll() { return this._items.length; } @computed get countCompleted() { return this._items.filter(item => item.done).length; } @computed get countUncompleted() { return this._items.filter(item => !item.done).length; } @action('添加任務') addItem = (name) => { if (name) { this._items.push(new Todo(name, false, this)); } }; @action('篩選所有') filterAll = () => { this.filter = ALL; }; @action('篩選已完成的') filterCompleted = () => { this.filter = COMPLETED; }; @action('篩選未完成的') filterUncompleted = () => { this.filter = UNCOMPLETED; } } class Todo { id = `${Date.now()}${Math.floor(Math.random()*1000)}`; @observable name = ''; @observable done = false; todos = null; constructor(name, done, todos) { this.name = name; this.done = done; this.todos = todos; } @action('任務 已完成/未完成 狀態切換') switchDone = () => { this.done = !this.done; }; @action('刪除當前項') remove = () => { if (this.todos) { this.todos._items.remove(this); } } } // Stateless Functional Component (無狀態的功能組件) const FilterButton = function(props) { const { onPress, children, active, size } = props; let buttnStyle, buttonTextStyle; if (active) { buttnStyle = {backgroundColor: 'green'}; buttonTextStyle = {color: 'white'}; } else { buttnStyle = {backgroundColor: '#F7F7F7'}; buttonTextStyle = {color: '#666'}; } return ( <TouchableOpacity onPress={onPress} disabled={active}> <View style={[styles.condition, buttnStyle]}> <Text style={[styles.conditionText, buttonTextStyle]}>{children}({size})</Text> </View> </TouchableOpacity> ); }; class Header extends Component { static propTypes = { data: PropTypes.instanceOf(TodoList) }; addItem = () => { const { data } = this.props; if (this.inputValue === undefined || this.inputValue.replace(/\s+/g, '') === '') { return alert('請輸入任務名稱'); } data.addItem(this.inputValue); // clear input & reset input value this.input.clear(); this.inputValue = ''; //還處理了黃色預警 Keyboard.dismiss(); }; render() { return ( <View style={styles.header}> <TextInput style={styles.input} ref={input => this.input = input} underlineColorAndroid='transparent' placeholder='在此輸入新增的任務' onChangeText={text => this.inputValue = text} maxLength={10} /> <TouchableOpacity onPress={this.addItem} style={styles.button}> <Text style={styles.buttonText}>Add Todo</Text> </TouchableOpacity> </View> ); } } @observer class ShowTodos extends Component { static propTypes = { data: PropTypes.instanceOf(TodoList) }; renderRow = (data) => { return (<TodoItem data={data}/>) }; render() { const { data } = this.props; return ( <View style={styles.showTodos}> <ListView style={styles.listView} enableEmptySections initialListSize={data.items.length} dataSource={ds.cloneWithRows(data.items.slice())} renderRow={this.renderRow} /> </View> ); } } @observer class Filter extends Component { static propTypes = { data: PropTypes.instanceOf(TodoList) }; render() { const { data } = this.props; return ( <View style={styles.filter}> <Text>篩選:</Text> <FilterButton size={data.countAll} active={data.filter === ALL} onPress={data.filterAll}>所有</FilterButton> <FilterButton size={data.countCompleted} active={data.filter === COMPLETED} onPress={data.filterCompleted}>已完成</FilterButton> <FilterButton size={data.countUncompleted} active={data.filter === UNCOMPLETED} onPress={data.filterUncompleted}>未完成</FilterButton> </View> ); } } @observer class TodoItem extends Component { static propTypes = { data: PropTypes.instanceOf(Todo) }; render() { const { data } = this.props; //這個的處理有意思 let flag; if (data.done) { flag = { textDecorationLine: 'line-through' }; } else { flag = { textDecorationLine: 'none' }; } return ( <TouchableOpacity onPress={data.switchDone}> <View style={styles.item}> <Text style={[styles.name, flag]} numberOfLines={1}>{data.name}</Text> <Text style={[styles.done, flag]}>{data.done ? '已完成' : '未完成'}</Text> <TouchableOpacity style={styles.del} onPress={data.remove}> <Text style={styles.delText}>x</Text> </TouchableOpacity> </View> </TouchableOpacity> ); } } class App extends Component { todoList = new TodoList(); render() { return ( <View style={styles.container}> <Header data={this.todoList}/> <ShowTodos data={this.todoList}/> <Filter data={this.todoList}/> </View> ); } } export default App;
是這個博客代碼寫的很好,仍是個人mobx不好啊,喜歡這個demo佈局