ReactNative的ES6类写法与未定义错误

ljlz6412 8年前
   <p><strong>ES6</strong>, 即ECMAScript6, JavaScript的新标准, 书写更加规范, 代码更加优雅. React Native推荐使用ES6的类写法代替传统的模块, 即使用<code>extends React.Component</code>代替<code>React.createClass</code>. 本文介绍在ReactNative中ES6的写法, 与传统方法进行对比, 并解决<strong>未定义(undefined)</strong>错误.</p>    <blockquote>     <p>在ES6中, 一定要注意<strong>this</strong>的使用, 否则<code>undefined is not an object</code>.</p>    </blockquote>    <p><img src="https://simg.open-open.com/show/9aa33cf0768bc7c460caacfdf6dcc3af.png" alt="ReactNative的ES6类写法与未定义错误" width="1024" height="768"></p>    <p>ES6</p>    <h2>类的写法</h2>    <p>在ES6中, RN模块使用<code>class</code>形式, 代替<code>var</code>形式, 使代码更加规范.旧的写法, 方法或变量使用<strong>逗号(",")</strong>间隔.</p>    <pre>  <code class="language-javascript">var Feed = React.createClass({});</code></pre>    <p>ES6的写法, 方法或变量结束使用<strong>分号(";")</strong>.</p>    <pre>  <code class="language-javascript">class Feed extends Component {}</code></pre>    <h2>初始化状态</h2>    <p>在ES6中, 使用<code>class</code>类的形式, 因此初始化在<strong>构造器(constructor)</strong>中进进行. 旧的写法, 使用<code>getInitialState</code>, 使用<code>return</code>返回状态.</p>    <pre>  <code class="language-javascript">var Feed = React.createClass({    getInitialState() {      return {        dataSource: new ListView.DataSource({          rowHasChanged: (row1, row2) => row1 !== row2        }),        loaded: false,        isAnimating: true,        isRefreshing: false      };    }  });</code></pre>    <p>ES6的写法, 使用<code>constructor</code>构造器, 直接设置<code>state</code>状态.</p>    <pre>  <code class="language-javascript">class Feed extends Component {    constructor(props) {      super(props);      this.state = {        dataSource: new ListView.DataSource({          rowHasChanged: (row1, row2) => row1 !== row2        }),        loaded: false,        isAnimating: true,        isRefreshing: false      }    }  }</code></pre>    <h2>this绑定</h2>    <p>在ES6中, 注意<strong>this</strong>的作用域, 由于使用类的写法, 所以<strong>this</strong>仅仅指代当前的类, 对于内部类需要重新指定<strong>this</strong>, 指定位置可以任选. 旧的方式直接写, 使用传递的<code>props</code>属性.</p>    <pre>  <code class="language-javascript">var Feed = React.createClass({    // 直接使用this.props属性    renderStories(story) {      return (        <Story story={story} navigator={this.props.navigator}></Story>      );    }      render() {      return (        <ListView          testID={"Feed Screen"}          dataSource={this.state.dataSource}          renderRow={this.renderStories}          .../>      )    }  });</code></pre>    <p>ES6的写法. 在内部类中, 需要重新绑定this. 三种实现方式: 构造时, 调用时, 使用时.</p>    <pre>  <code class="language-javascript">class Feed extends Component {    // 构造器直接绑定方法.    constructor(props) {      super(props);      this.renderStories = this.renderStories.bind(this);    }  }</code></pre>    <pre>  <code class="language-javascript">class Feed extends Component {    // 调用时, 绑定this.    render() {      return (        <ListView          testID={"Feed Screen"}          dataSource={this.state.dataSource}          renderRow={(story) => this.renderStories(story)}          .../>      )    }  }</code></pre>    <pre>  <code class="language-javascript">class Feed extends Component {    // 使用时, 绑定this    render() {      return (        <ListView          testID={"Feed Screen"}          dataSource={this.state.dataSource}          renderRow={this.renderStories.bind(this)}          .../>      )    }  }</code></pre>    <p>注意绑定this失败, 会发生未定义错误, 即<code>undefined is not an object</code>.</p>    <p><strong>错误信息</strong></p>    <p><img src="https://simg.open-open.com/show/aaa979b9c4bda3e0a55c7bca42cb4e65.png" alt="ReactNative的ES6类写法与未定义错误" width="750" height="1334"></p>    <p>崩溃</p>    <p><strong>React Native</strong>推荐使用ES6的语法规范开发, 因此在开发中, 我们尽量使用ES6. 使用类的形式, 对于编辑器更加友好, 也更容易实现自动索引, 方便编程.</p>    <p>感谢我的朋友<strong>前端大神@左大师</strong>的指导!</p>    <p>另外<a href="/misc/goto?guid=4959671734604525528">参考</a></p>    <p>OK, that's all! Enjoy it!</p>    <p><a href="/misc/goto?guid=4959671734691573597">文/SpikeKing(简书作者)</a><br>  </p>