Realm 的两个特性: 单向数据流和响应式绑定(React Native 版 )
发布于 3 个月前 作者 russj 595 次浏览 来自 分享

这两个特性也是目前随着前端 UI 越来越复杂,用来解耦的好方法。

单向数据流 Unidirectional data flow

简单来说单向数据流就是确保数据是单向绑定的,例如下图,数据的更新永远是顺着一个方向而不能反过来。

unidirectional-diagram.png

要做到数据的单向流动,需要做到以下两个方面。

数据状态只保存在一处。 Single source of truth

数据状态只保存在一处不用多说了,主要就是数据结构的设计,要避免把一种状态用两种描述放在不同的表里,然后再来同步。这样你再精巧的代码都弥补不了数据结构的缺陷。数据结构比代码重要。

状态的读写操作分开,在状态改变后通知更新 UI。

写操作直接操作数据,不要有中间状态,然后通知数据更新。Realm 是通过 realm.write 来处理所有的写操作。

realm.write(() => {
  let myCar = realm.create('Car', { //创建新的记录
    make: 'Honda',
    model: 'Civic',
    miles: 1000,
  });
  myCar.miles += 20; // 更新
  realm.delete(myCar); //删除
});

如果你在realm.write() 之外试图写操作,就会抛出错误。

在更新后,会有一个 change event

realm.addListener('change', () => {
  //通知更新界面
})

这样读写分开可以降低程序的复杂度,使得逻辑更清晰。至于界面的更新就交给 React 了,配合得正好。

所以其实可以考虑直接使用 Realm 来作为 Flux 架构的 Store,而不用 Redux。(一个猜测

Reactive

Realm 查询的结果是自动更新的。例如

realm.gif

输入姓名后点击 Save,人数就自动更新。在上面例子中,我们只需在 componentWillMount 里查询(绑定)一次返回的 results 值, 此后只要 Person 数目改变,界面里的 results.length 就会改变,而不用再次去查询数据库了。React 会帮助你高效处理界面更新的部分。代码如下

class rmdemo extends Component {
  constructor(props) {
    super(props)
    this.state = {
      inputText: ''
    }
  }
  componentWillMount(){
    this.realm = new Realm({
      schema:[{name:'Person', properties:{name: 'string'}}]
    })
    this.results = this.realm.objects('Person')
    this.realm.addListener('change', () => {
      this.forceUpdate()
    })
  }
  _handleTouch(){
    this.realm.write(()=>{
      this.realm.create('Person', [this.state.inputText]);
    })
  }
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native and Realm!
        </Text>
        <Text style={styles.welcome}>
          Count of Persons in Realm: {this.realm.objects('Person').length}
        </Text>
        <View style={{alignItems: 'center'}}>
          <TextInput
            style={{height: 40, width: 200, borderColor: 'gray', borderWidth: 1}}
            onChangeText={(inputText) => this.setState({inputText})}
            value={this.state.inputText}
          />
          <TouchableWithoutFeedback onPress={this._handleTouch.bind(this)}>
            <View>
              <Text style={{fontSize: 24, color: 'blue'}}>
                Save
              </Text>
            </View>
          </TouchableWithoutFeedback>
        </View>
      </View>
    )
  }
}
回到顶部