在開發 Nautil 中我想作些不同的嘗試。javascript
和主流的 react 生態格格不入,nautil 像是對 react 的反目,但實際上我但願在現有優秀的 UI 框架上,作一些不同的東西。nautil 基於「觀察者模式」,在 react 中實現相似 vue 同樣的屬性更新的響應式模式,以及今天要講的雙向綁定。html
單向數據流vue
React 推崇單向數據流,組件經過 props 接收數據,控制 UI 展現。當用戶對組件進行操做時,在每個操做上,組件調用 props 上傳遞的函數,並將內部的狀態數據做爲參數傳遞給這些回調函數。而這些回調函數,必須修改原來傳入的 props 值,才能保證組件的 UI 以新的界面展現。java
單向數據流的好處,是保證了組件的純粹性,用戶不用擔憂反作用,並且嚴格按照 immutable 數據的方式控制 UI 展現。react
雙向綁定git
在早期的 angular1.x 版本中,一個 directive 聲明 scope 屬性爲 = 時,angular 會將該屬性和外部傳入的屬性進行雙向綁定。外部對應的屬性發生變化時,該 directive 內部也會因爲對應屬性的變化而從新渲染。固然,這也是由於 angular 是髒檢查機制,從頂往下全量檢查。github
在 vue 中,表單組件 input 等支持 v-model 屬性實現雙向綁定,這給單向數據流的應用框架提供了一種思路。vue 的實現,其實是用一個 v-model 指令,完成單向的數據傳入和 @input 事件響應。而正好由於 vue 基於模板語法,屬性路徑(keyPath)的使用很是方便,因此 v-model 的實現很是優雅。數組
在 react 中雙向綁定app
基於 v-model 的解決思路,一個雙向綁定,實質是一個單向數據傳入,和一個事件的響應。所以,咱們在 react 中,也能夠模擬這種實現。框架
class Input extends Component {
static props = {
$value: [String, Function],
}
render() {
const { $value } = this.props
const [value, reflect] = $value
return <input type="text" value={value} onChange={e => reflect(e.target.value)} /> } }複製代碼
這樣的代碼很是容易理解。無非是迫使一個 prop 傳入的值是一個特定數組結構。
class App extends Component {
state = {
value: 'xxx',
}
render() {
return <Input $value={[this.state.value, value => this.setState({ value })]} /> } }複製代碼
按照這樣的思路,咱們基本能夠實現 v-model 在 react 中的運行模式。可是顯然,這樣還不夠簡單,有沒有更簡潔的寫法?
在 nautil 中實現了更簡單的內部雙向綁定操做,可在組件內像 vue 同樣,寫 this.attrs ++ 這樣的語法。若是你感興趣,不妨一試。