PrismJS

2018年5月23日 星期三

react-native-autocomplete-input(1)使用筆記

初次使用React Native開發Android與iOS的APP,希望實作一個簡單的輸入提示框的功能,因此在GitHub上找到l-urence的react-native-autocomplete-input來使用看看。


GitHub連結: https://github.com/l-urence/react-native-autocomplete-input
bouchertommy的中文參考:http://hant.helplib.com/GitHub/article_136892

以下針對Gitgub上example/Example.ios.js這個範例做個簡單的筆記:

1.Constructor 建構式:設定物件內的屬性(State)初始值
      query: 紀錄輸入框所記錄的文字
      films: 紀錄所有提示訊息
constructor(props) {
    super(props);
    this.state = {
      films: [],
      query: ''
    };
  }
2.componentDidMount: 生命週期,物件mount後執行
componentDidMount() {
    fetch(`${API}/films/`).then(res => res.json()).then((json) => {
      const { results: films } = json;
      this.setState({ films });
    });
  }
以fetch方法取得json格式的資料,從URL(https://swapi.co/api/films/)來看,可以看到會取得的內容如下,且將result內更新到State屬性的films中。
3.findFilm: 根據目前輸入模糊查詢films內符合的並回傳。
findFilm(query) {
    if (query === '') {
      return [];
    }

    const { films } = this.state;
    const regex = new RegExp(`${query.trim()}`, 'i');
    return films.filter(film => film.title.search(regex) >= 0);
  }
4.remderFilm: 選擇提示後回傳詳細內容。
static renderFilm(film) {
    const { title, director, opening_crawl, episode_id } = film;
    const roman = episode_id < ROMAN.length ? ROMAN[episode_id] : episode_id;

    return (
      <View>
        <Text style={styles.titleText}>{roman}. {title}</Text>
        <Text style={styles.directorText}>({director})</Text>
        <Text style={styles.openingText}>{opening_crawl}</Text>
      </View>
    );
  }
      const {title, director, opening_crawl, episode_id} = film;
      此行是將fims內的各個key取出Value。
5.
render() {
    const { query } = this.state;
    const films = this.findFilm(query);
    const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();

    return (
      <View style={styles.container}>
        <Autocomplete
          autoCapitalize="none"
          autoCorrect={false}
          containerStyle={styles.autocompleteContainer}
          data={films.length === 1 && comp(query, films[0].title) ? [] : films}
          defaultValue={query}
          onChangeText={text => this.setState({ query: text })}
          placeholder="Enter Star Wars film title"
          renderItem={({ title, release_date }) => (
            <TouchableOpacity onPress={() => this.setState({ query: title })}>
              <Text style={styles.itemText}>
                {title} ({release_date.split('-')[0]})
              </Text>
            </TouchableOpacity>
          )}
        />
        <View style={styles.descriptionContainer}>
          {films.length > 0 ? (
            AutocompleteExample.renderFilm(films[0])
          ) : (
            <Text style={styles.infoText}>
              Enter Title of a Star Wars movie
            </Text>
          )}
        </View>
      </View>
    );
  }
      第9行autoCapitalize及autoCorrect屬性(props)為關閉自動轉大寫及自動校正功能。
      第12行的data屬性為提示列表的內容,當提示篩選後(films)數量為1且與TextInput內容相同時設為空([])。
      第13行的defaultValue屬性為TextInput內顯示的文字內容,每次State改變時呼叫render將取得query的值並設定到此屬性中。

方便自己包裝將此範例簡單改寫成以下,並帶入props的方法:
class AutocompleteExample extends Component {
    static propTypes = {
        films: PropTypes.array,
    };
    static defaultProps = {
        films: [],
    };
    constructor(props) {
        super(props);
        this.state = {
            text: ''
        };
    }
    findFilm(text) {
        {/*從輸入找出陣列符合*/}
        if (text === '') {
            return [];
        }    
        const { films } = this.props;
        const regex = new RegExp(`${text.trim()}`, 'i');
        return films.filter(film => film.title.search(regex) >= 0);
    }
    render() {
        const { text } = this.state;
        const films = this.findFilm(text);
        const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim(); 
        return (
            <View >
                <Autocomplete
                    autoCapitalize="none"
                    autoCorrect={false} 
                    containerStyle={styles.autocompleteContainer}
                    inputContainerStyle={{minWidth:115,maxWidth:200}}
                    data={films.length === 1 && comp(text, films[0].title) ? [] : films}
                    defaultValue={text}
                    onChangeText={text => this.setState({ text: text })}
                    placeholder="Enter Star Wars film title"
                    renderItem={
                        ({title}) => (
                            <TouchableOpacity onPress={() => this.setState({ text: title })}>
                                {/*autocomplete 內容*/}
                                <Text style={styles.itemText}>
                                    {title}
                                </Text>
                            </TouchableOpacity>
                        )
                    }
                />
            </View>
        );
    }
}
接著呼叫改寫好的AutocompleteExample使用,例如:
export default class App extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <View  style={styles.container}>
          <AutocompleteExample 
              films= {
                [
                  {title:'001'},
                  {title:'002'},
                  {title:'003'},
                  {title:'004'},
                  {title:'005'},
                  {title:'006'},
                  {title:'007'},
                  {title:'008'},
                  {title:'009'},
                  {title:'010'},
                  {title:'011'},
                  {title:'012'},
                  {title:'013'},
                  {title:'014'},
                ]
              }
          />
      </View>
    );
  }
}

不過範例改寫完使用後,目前有發現兩個尚未解決Issue:
Issue1.提示訊息框並沒有ScrollView的功能
Issue2.提示訊息框呈現半透明,且如果UI有重疊的話會干擾點擊

沒有留言:

張貼留言