簡體   English   中英

如何在ListView的renderRow中訪問`this`?

[英]How to access `this` inside a renderRow of a ListView?

我在ListView的一行內為onPress事件運行函數時遇到麻煩。 我正在關注React Native教程,試圖從那里繼續。 似乎它使用的是ES6語法樣式。

這是代碼的相關部分。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

import React, {  
  TouchableHighlight,
  AppRegistry,
  Component,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
  Alert,
} from 'react-native';

class AwesomeProject extends Component {
  constructor(props) {
    super(props);
    this.something = this.something.bind(this); // <-- Trying this, not even sure why
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  }

//
//Irrelevant code here. Fetching stuff and renderLoadingView
//

  something = function(){
    console.log('something');
    Alert.alert(
      'Alert Title',
      'alertMessage',
    );
  }


  render() {
    console.log('this', this); //this is an instance of AwesomeProject
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMovie}
        style={styles.listView}
        />
    );
  }

  renderMovie(movie) {
    console.log('Not this', this); //this is not an instance of AwesomeProject
    return (
      <TouchableHighlight onPress={() => {console.log(this); this.something()}}>
     <View style={styles.container}>
        <Image
          source={{uri: movie.posters.thumbnail}}
          style={styles.thumbnail}                    
        />
        <View style={styles.rightContainer}>
          <Text style={styles.title}

          >{movie.title}</Text>
          <Text style={styles.year}>{movie.year}</Text>
        </View>
      </View>
       </TouchableHighlight>
    );
  }
}

//
//More irrelevant code here. Styles and the 
//

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

我無法運行something函數。 我嘗試了各種語法,但沒有成功。 這個問題似乎是, this不是我希望它是,並且它不具有可變something定義。

我必須使其起作用的唯一方法是在AwesomeProject類外部使用var something = function(){...}聲明一個外部變量。

AwesomeProject中聲明時,是否可以訪問something AwesomeProject 根據磁通架構,這可能是不好的做法嗎?

原來我自己在這里找到了解決方案: https : //github.com/goatslacker/alt/issues/283#issuecomment-115391700

問題是,與ES6語法,你有沒有自動綁定 this ,所以你需要自己做。

自發布此答案以來,我學到了更多。 真正的問題是在執行函數時(而不是在聲明時) this是“綁定”的。 它指向函數在調用時附加的對象。 例如:

 obj.foo(); //inside foo, this points to obj bar(); //inside bar, this points to the global object (or undefined in strict mode) 

在我的示例中,函數this.renderMovie()作為參數傳遞。 因此,在ListView中它將是一個“局部變量”。 它將被稱為與任何對象“分離”,例如之前的bar()示例,因此this不是我期望的。

可以強制this綁定。

有3種可能的解決方案,我最喜歡第3種:

選項1:在通話時手動綁定

在代碼上,將{this.renderMovie}替換為{this.renderMovie.bind(this)}

  render() {
    console.log('this', this); //this is an instance of AwesomeProject
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMovie.bind(this)} //<-- change here
        style={styles.listView}
        />
    );
  }

選項2:對構造函數進行綁定

當然,綁定正確的函數:

  constructor(props) {
    super(props);
    this.something = this.something.bind(this); // <-- Not this function
    this.renderMovie = this.renderMovie.bind(this); // <-- This function!!
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  }

選項3:使用箭頭語法,讓他們完成工作

我最喜歡這個。 您只需要使用箭頭語法聲明所涉及的函數,因此:

  renderMovie(movie) {
    //code here
  }

變成這個:

  renderMovie = (movie) => {
    //code here
  }

除了https://stackoverflow.com/a/36779517/6100821

選項4:使用綁定運算符

<ListView
    dataSource={this.state.dataSource}
    renderRow={::this.renderMovie} //<-- cleaner, than bind
    style={styles.listView}
    />

注意,這只是一個建議 ,而不是標准!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM