美文网首页React Native开发程序员React Native实践
阴阳师悬赏封印查询助手(3)

阴阳师悬赏封印查询助手(3)

作者: 封小胖 | 来源:发表于2017-09-03 22:38 被阅读212次

    © fengyu学习

    本系列原本已经打算太监了,但是今早的app销量触动了我,给了我一个正向激励。

    我的第一个上架APP的销量-20170903

    重读了一遍代码,决定继续和大家分享React-Native的实践,聊一下组件之间的通信,使用TextInput组件碰到的坑,和一些上架的体会。

    查询并展示搜索结果

    1、组件间的通讯

    • App入口组件 ShikigamiBox.js
    export default class ShikigamiBox extends Component {
    
        constructor(props) {
            super(props);
            this.state = {
              searchResult: ""
            }
        }
    
        render() {
            return (
            <View style={styles.container}>
                <ShikigamiHeader/>
                <ShikigamiSearch filterShikigamiList={this.filterShikigamiList} />
                <ShikigamiListView showFengyinResult={this.showFengyinResult} filterName={this.state.filterName} />
                <ShikigamiModel clearSearchResult={this.clearSearchResult} content={this.state.searchResult} />
            </View>
            );
        }
    
        showFengyinResult = (searchResult) => {
            this.setState({
              searchResult
            })
        }
    
        clearSearchResult = () => {
            this.setState({
              searchResult: ""
            })
        }
    
        filterShikigamiList = (filterName) => {
            this.setState({
              filterName
            });
        }
    
    }
    
    • 搜索框 ShikigamiSearch.js
    export default class ShikigamiSearch extends Component {
    
        constructor(props) {
            super(props);
            this.state = {
              text: ""
            };
        }
    
        handleChangeText = (text) => {
            setTimeout(() => {
              this.props.filterShikigamiList(text);
              this.setState({
                  text
              });
            }, 50);
        }
    
        render() {
            return (
            <View style={styles.container}>
                <TextInput style={styles.input}
                        placeholder="请输入首字母或式神名"
                        onChange={(evt) => this.setState({ text: evt.nativeEvent.text })}
                        onChangeText={this.handleChangeText}
                        onEndEditing={(evt) => this.setState({ text: evt.nativeEvent.text })}
                        value={this.state.text}
                        />
            </View>
            );
        }
    
    }
    

    React-NativeReact 一脉相承,都是依靠 stateprops 来做到组件的通信以及自身渲染的管理的,比如上面实现的这段代码。

    • ShikigamiSearch 输入框监听了 onChangeText 事件
    • ShikigamiSearch 调用 this.props.filterShikigamiList({$输入的文本})
    • ShikigamiBox 组件调用 this.filterShikigamiList() 改变 state 中的 filterName,触发 render()
    • 因为 ShikigamiListView 组件以 this.state.filterName 作为 props,所以触发了 componentWillUpdate()
    • 此处有业务方法实现过滤数据,并改变 ShikigamiListViewstate 中的 dataSource
    • ShikigamiListView 中展示出过滤后的最新列表

    2、面向对象的思想

    那段时间一直在为了面向对象而面向对象,这个作品算是一个很明显的体现。

    ShikigamiBean.js

    • name(名称)
    • level(等级)
    • logo(图标)
    • initial(首字母)
    • clue(线索)
    import {log} from "../utils/common";
    
    const baseParams = ['name', 'icon'];
    
    export default class ShikigamiBean {
    
        constructor(shikigami) {
    
            for (let i = 0, l = baseParams.length; i < l; i++) {
                let bp = baseParams[i];
                if (!shikigami[bp]) {
                    log('式神属性缺失,初始化失败,缺失属性为:"' + bp + '"');
                    throw new Error("10000");
                }
            }
    
            this.name = shikigami.name;
            this.level = shikigami.level;
            this.icon = shikigami.icon;
            this.initial = shikigami.initial;
            this.clue = shikigami.clue;
        }
    
    }
    

    ShikigamiList.js

    最重要的是里面的filter()方法,确实让过滤式神列表变得十分的清晰

    • A - Z 匹配首字母
    • 首个字模糊匹配
    • 整个名字精准匹配
    • 利用线索进行匹配
    import ShikigamiBean from "./ShikigamiBean";
    import {log} from "../utils/common";
    
    // 普通式神列表
    const COMMON = "commonList";
    
    // 依据首字母进行分类的式神列表
    const SORTBYINITIAL = "sortByInitialList";
    
    export default class ShikigamiList {
    
      initData;
    
      commonList = [];
    
      sortByInitialList = new Set();
    
      constructor(data) {
        this.initData = data;
    
        data.forEach((shikigami, index) => {
          try {
            this.commonList.push(new ShikigamiBean(shikigami));
          } catch (e) {
            log('第' + index + '位的式神初始化失败!');
          }
        });
    
        this.sortByInitial();
      }
    
      // 使用首字母对list中数据进行分类
      sortByInitial() {
        this.commonList.forEach((shikigami, index) => {
          let initial = shikigami.initial,
              sortByInitialList = this.sortByInitialList;
    
          if (!sortByInitialList[initial]) {
            sortByInitialList[initial] = [shikigami];
          } else {
            sortByInitialList[initial].push(shikigami);
          }
        });
      }
    
      filter(value) {
        if (!value) return this.sortByInitialList;
    
        if (/[A-Z]/i.test(value.charAt(0))) {
          const filterInitial = value.charAt(0).toUpperCase();
          const result = this.sortByInitialList[filterInitial];
          if (result) {
            return {[filterInitial]: result};
          }
        }
    
        let matchInitial = "";
        let matchShikigamiArr = [];
    
        let clueShikigamiArr = [];
    
        for (let shikigami of this.commonList) {
          if (shikigami.name.charAt(0) === value.charAt(0)) {
            if (shikigami.name === value) {
              return {[shikigami.initial]: [shikigami]};
            } else {
              if (!matchInitial) {
                matchInitial = shikigami.initial;
              }
              matchShikigamiArr.push(shikigami);
            }
          }
    
          // 线索查询
          if(shikigami.clue && shikigami.clue.indexOf(value) > -1) {
            var copyShikigami = Object.assign({}, shikigami);
            copyShikigami.clueShow = true;
            clueShikigamiArr.push(copyShikigami);
          }
        }
    
        var returnList = {};
    
        if (matchInitial) {
          returnList[matchInitial] = matchShikigamiArr;
        }
    
        if (clueShikigamiArr.length > 0) {
          returnList['线索'] = clueShikigamiArr;
        }
    
        return returnList;
      }
    
      get(key) {
        return this[key];
      }
    }
    
    export {
      COMMON,
      SORTBYINITIAL
    }
    

    3、TextInput组件使用的坑

    印象比较深刻的是中文输入法在输入框中输入的时候,无法及时获取到输入的字母。

    解决方法(自带输入法没问题了,其他的待验证)

    • onChange 方法设置 (evt) => this.setState({ text: evt.nativeEvent.text })
    • onEndEditing 方法设置 (evt) => this.setState({ text: evt.nativeEvent.text })

    参考文章:React Native 中 TextInput 组件和中文输入冲突

    <TextInput style={styles.input}
               placeholder="请输入首字母或式神名"
               onChange={(evt) => this.setState({ text: evt.nativeEvent.text })}
               onChangeText={this.handleChangeText}
               onEndEditing={(evt) => this.setState({ text: evt.nativeEvent.text })}
               value={this.state.text}
               />
    

    4、关于App的上架

    本来当时有挺多体会的,个人心情是多于查流程,走流程。可能应用比较简单吧,所以上架审核的时间都挺快的。

    由于时间比较久远,真的不记得为什么被拒了,好像有一次是2个名称不一致导致的,第二次就上线的很顺利了,不过由于这是个单机应用,几乎没有用到权限,所以可能审核比较宽松。

    还记得用英语和审核人员沟通被拒的原因时,那种忐忑的感觉。

    第一次上架 1.1升级上架

    5、开源

    项目的github地址

    希望这个代码可以对有些朋友有帮助,如果有热心人完善了数据,或者增强了功能,可以私聊我,我可以帮忙上架。

    相关文章

      网友评论

        本文标题:阴阳师悬赏封印查询助手(3)

        本文链接:https://www.haomeiwen.com/subject/trwdjxtx.html