原文出处

千帆竞发尝试:

大家已经可以依附state与props的概念做五个小练习了。它是三个ToDo
List,相当于待办列表。差相当少长上面这些样子:

图片 1

To Do List草图

咱俩把它分为五个页面。最右边是增加待办事项的分界面,记为ToDoListAdd。中间和最左边其实是同一个分界面,记为ToDoListMain,它具备二种不相同景况。

小编们先来看ToDoListAdd分界面。它有上中下四个部分。最上面是贰个可点击返回的尾部,中间是用来输入文字的TextInput,底部是三个肯定增加的Button。

有未有觉察它和上二遍我们的flexbox小演习分界面很像吧?没有错,基于上一篇的布局知识,大家得以一本万利地把页面修改成那样。

再来看ToDoListMain分界面,它与ToDoListAdd很像。尾部的”增添”用以跳转至ToDoListAdd。“多选”用以让每叁个待办项的Checkbox突显出来,而且出示最下边包罗全选Checkbox的footer。

要完全地成功那几个利用,本文的字数是非常不足的,后续文章会深深到进一步细节的地点。但是首先,本文仲介绍如何贯彻以下基本成效:1.施用state调整编辑状态;2.运用state完成分界面包车型地铁跳转;3.父亲和儿子组件之间的通信。让大家起首工编织写程序,穿插着介绍着三点内容。

手续1,使用flex布局产生ToDoListAdd分界面。在根目录新建三个文书ToDoListAdd.js,定义ToDoListAdd类。为越来越简明,这里省去须求组件的引入代码,以及体制代码。

export default class ToDoListAdd extends Component<Props> {
constructor(props) { super(props); } onPress() { } // 方今为空 render()
{ return ( <View style={styles.container}> <View
style={styles.header}> <Text style={styles.add}
onPress={this.props.onBack}>重返</Text> </View> <View
style={styles.body}> <TextInput /> </View> <View
style={styles.footer}> <Button title=”明确” onPress={this.onPress}
style={styles.btn} /> </View> </View> ); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
export default class ToDoListAdd extends Component<Props> {
    constructor(props) {
        super(props);
    }
    onPress() { } // 暂且为空
    render() {
        return (
            <View style={styles.container}>
                <View style={styles.header}>
                    <Text style={styles.add} onPress={this.props.onBack}>返回</Text>
                </View>
                <View style={styles.body}>
                    <TextInput />
                </View>
                <View style={styles.footer}>
                    <Button title="确定" onPress={this.onPress} style={styles.btn} />
                </View>
            </View>
        );
    }
}

值得注意的是,这里”再次回到”开关的onPress回调函数来自于props。也等于说,当那个ToDoListAdd被选取的时候,父组件必要钦点传给子组件(这里子组件就是ToDoListAdd)的onBack的值。能够看到,到近些日子甘休,上边的ToDoListAdd组件其实是叁个”无状态”组件。它只是对父组件传来的props的渲染。但事实上,TextInput日常是有事态的,因为在这之中的值会随着用户的改动而变化。这里大家一时没有处理它。

步骤2,起始创造ToDoListMain组件。当初叶妄图这么些组件的时候,至少有两件专业是内需考虑的:

待办事项的数据源,应该来自这里?突显和隐形尾部的事态存应该在哪个地方?

先是个难题,为了汇报方便,大家把待办事项的数码源用变量todoList来代表。
todoList能够领略为部分动静,它是急需在ToDoListMain组件中被呈现和操作的。有八个todoList的可选地方,要么放在ToDoListMain组件自个儿,要么放在ToDoListMain更上一层的机件中。于此同不寻常间,当ToDoListAdd组件试图增多一个新的待办事项时,ToDoListAdd组件是亟需修改todoList那个数据源的。假使todoList在ToDoListMain组件中,ToDoListAdd组件就须要和ToDoListMain组件举行通讯。但那实际就绕了两个天地,因为从草图的逻辑上看,ToDoListAdd是与ToDoListMain同级的贰个分界面,它们之间要通讯,一般的做法是依附共同的父组件。所以,就以那件事例来讲,把数据源就径直放在ToDoListAdd和ToDoListMain共同的父组件中是更利于的抉择。接下来拜访到,那几个合伙的父组件就是App.js,它将引进ToDoListAdd和ToDoListMain,大家还有只怕会App.js中手动设置渲染接纳的逻辑。

第二个难点,突显和隐身尾巴部分是只在ToDoListMain组件中运用的意况,它不与外面有挂钩,所以放在它里面就可以。

通过地点的剖析,大家创制起来创立ToDoListMain如下:

export default class ToDoListmain extends Component<Props> {
constructor(props) { super(props); this.state = { isEditing: false };
this.onEdit = this.onEdit.bind(this); this.renderItem =
this.renderItem.bind(this); } renderFooter(toggleCheckAll, isAllChecked)
{ if (!this.state.isEditing) { return null; } const count =
this.props.todoList.filter(item => item.isChecked).length; return (
<View style={styles.footer}> <CheckBox
onValueChange={toggleCheckAll} value={isAllChecked} /> <Text
style={styles.menu}>{`已选择:${count}项`}</Text>
</View> ); } onEdit() { this.setState((prevState) => { return {
isEditing: !prevState.isEditing } }); } renderItem(item) { return
(<ToDoListItem {…item} toggleItemCheck={this.props.toggleItemCheck}
isEditing={this.state.isEditing} />); } render() { const {
toggleCheckAll, isAllChecked, onAddItem, todoList } = this.props; return
( <View style={styles.container}> <View
style={styles.header}> <Text style={styles.add}
onPress={onAddItem}>增多</Text> <Text
style={styles.title}>待办列表</Text> <Text
style={styles.multi} onPress={this.onEdit}>{this.state.isEditing ?
‘撤除’ : ‘多选’} </Text> </View> <FlatList
style={styles.body} isEditing={this.state.isEditing} data={todoList}
renderItem={this.renderItem} /> {this.renderFooter(toggleCheckAll,
isAllChecked)} </View> ); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
export default class ToDoListmain extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            isEditing: false
        };
        this.onEdit = this.onEdit.bind(this);
        this.renderItem = this.renderItem.bind(this);
    }
    renderFooter(toggleCheckAll, isAllChecked) {
        if (!this.state.isEditing) {
            return null;
        }
        const count = this.props.todoList.filter(item => item.isChecked).length;
        return (
            <View style={styles.footer}>
                <CheckBox onValueChange={toggleCheckAll} value={isAllChecked} />
                <Text style={styles.menu}>{`已选择:${count}项`}</Text>
            </View>
        );
    }
    onEdit() {
        this.setState((prevState) => {
            return {
                isEditing: !prevState.isEditing
            }
        });
    }
    renderItem(item) {
        return (<ToDoListItem {…item}
            toggleItemCheck={this.props.toggleItemCheck}
            isEditing={this.state.isEditing} />);
    }
    render() {
        const { toggleCheckAll, isAllChecked, onAddItem, todoList } = this.props;
        return (
            <View style={styles.container}>
                <View style={styles.header}>
                    <Text style={styles.add} onPress={onAddItem}>添加</Text>
                    <Text style={styles.title}>待办列表</Text>
                    <Text style={styles.multi}
                        onPress={this.onEdit}>{this.state.isEditing ? ‘取消’ : ‘多选’}
                    </Text>
                </View>
                <FlatList style={styles.body} isEditing={this.state.isEditing}
                    data={todoList} renderItem={this.renderItem} />
                {this.renderFooter(toggleCheckAll, isAllChecked)}
            </View>
        );
    }
}

笔者们见到该器件唯有二个意况,isEditing。它调控了左上角的文字是”打消”依旧”多选”,也调整了底层是还是不是出示。

笔者们在调整底部是不是出示时,调用了三个自定义的函数,用它的重返值最为内容插入在调用函数的职位。在索罗德N中,假如在渲染的时候回来null,就象征什么也不渲染。所以调用renderFooter时,在isEditing状态为false时,什么都不渲染。

toggleCheckAll用来调整是还是不是全选待办事项。isAllChecked是剖断是否全选。onAddItem用作点击”加多”文字的回调。而todoList正是最关键的待办事项的数据源了。它们都源于ToDoListMain的父组件,通过props传下来。

而ToDoListMain组件内部,有七个onEdit函数,用作右上角”撤消”和”多选”文字onPress时的回调。在里头大家看到本田CR-VN中安装state的不易方法是调用this.setState方法。

其它,为了演示方便,这里运用官方提供的Checkbox组件来表示待办事项是否check了。但以此Checkbox组件的莫过于唯有Android平台才有,iOS下未有。而对iOS的管理,策动在后面包车型地铁篇章中等专门的工作高校门分享。

再有一点值得注意的地点,是引入了FlatList组件来对todoList数据源进行渲染。FlatList是官方提供的意向展现列表的零部件,老版本的ListView已经被标识为弃用了(deprecated)。FlatList组件对列表的渲染做了好些个性子优化和效果与利益巩固。我们临时只是使用它来轻巧显示待办列表。

每贰个待办事项应用了自定义的另一个零部件ToDoListItem,大家霎时来拜谒它。

手续3,达成ToDoListItem组件。它并未有和煦的状态,也只是对父组件内容的显得。

export default class ToDoListItem extends Component<Props> {
constructor(props) { super(props); } render() { const { toggleItemCheck,
item } = this.props; const { isChecked, detail, level } = item; const
basicLevelStyle = styles.level; let specificLevelStyle; if (level ===
‘info’) { specificLevelStyle = styles.info; } else if (level ===
‘warning’) { specificLevelStyle = styles.warning; } else {
specificLevelStyle = styles.error; } return ( <View
style={styles.container}> {this.props.isEditing && <CheckBox
onValueChange={(value) => toggleItemCheck(item, value)}
style={styles.checkbox} value={isChecked} />} <Text
style={styles.detail}>{detail}</Text> <View
style={[basicLevelStyle, specificLevelStyle]}></View>
</View> ); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
export default class ToDoListItem extends Component<Props> {
    constructor(props) {
        super(props);
    }
    render() {
        const { toggleItemCheck, item } = this.props;
        const { isChecked, detail, level } = item;
        const basicLevelStyle = styles.level;
        let specificLevelStyle;
        if (level === ‘info’) {
            specificLevelStyle = styles.info;
        } else if (level === ‘warning’) {
            specificLevelStyle = styles.warning;
        } else {
            specificLevelStyle = styles.error;
        }
        return (
            <View style={styles.container}>
                {this.props.isEditing && <CheckBox onValueChange={(value) => toggleItemCheck(item, value)} style={styles.checkbox} value={isChecked} />}
                <Text style={styles.detail}>{detail}</Text>
                <View style={[basicLevelStyle, specificLevelStyle]}></View>
            </View>
        );
    }
}

特别是,每一种是不是被check,那几个情景其实来自于todoList数据源,而每一种的Checkbox的value完全受控于父组件传来的值,所以这种用户输入型的机件,其值完全受控于父组件的props的传值的,也常被堪当受控组件(Controlled
Component)。

原文出处。除此以外,todoList的每一项,我们用level来表示待办项的某种等第,用detail表示它的故事情节,用isChecked来代表它是不是产生。

原文出处。原文出处。不过做了那样多,大家还什么都没见到啊。所以,接下去的显要一步,正是把ToDoListMain和ToDoListAdd的渲染逻辑一口气写到App.js中去。

手续4,写最外层的渲染逻辑。在App.js中,引进

import ToDoListMain from ‘./ToDoListMain’; import ToDoListAdd from
‘./ToDoListAdd’;

1
2
import ToDoListMain from ‘./ToDoListMain’;
import ToDoListAdd from ‘./ToDoListAdd’;

然后定义App组件

export default class App extends Component<Props> {
constructor(props) { super(props); this.state = { current: ‘main’,
todoList: [原文出处。 { level: ‘info’, detail: ‘一般的天职’, isChecked: false,
key: ‘0’ }, { level: ‘warning’, detail: ‘较重要的任务’, isChecked:
false, }, { level: ‘error’, detail: ‘极其主要且紧急的天职’, isChecked:
false, key: ‘2’ } ] } this.onAddItem = this.onAddItem.bind(this);
this.onBack = this.onBack.bind(this); this.toggleCheckAll =
this.toggleCheckAll.bind(this); this.toggleItemCheck =
this.toggleItemCheck.bind(this); } onAddItem() {
this.setState((prevState) => { return { current: ‘add’ } }); }
onBack() { this.setState({ current: ‘main’ }); } toggleCheckAll() {
const flag = this.isAllChecked(); const newTodos =
this.state.todoList.map(item => { return { …item, isChecked: !flag
}; }); this.setState({ todoList: newTodos }); } toggleItemCheck(item,
key) { const newTodos = this.state.todoList.map(todo => { if (todo
!== item) { return todo; } return { …todo, isChecked: !item.isChecked
} }); this.setState({ todoList: newTodos }); } isAllChecked() { if
(!this.state.todoList) return false; if (this.state.todoList.length ===
0) return false; return this.state.todoList.every(item =>
item.isChecked); } render() { if (this.state.current === ‘main’) {
return (<ToDoListMain isAllChecked={this.isAllChecked()}
toggleCheckAll={this.toggleCheckAll}
toggleItemCheck={this.toggleItemCheck} onAddItem={this.onAddItem}
todoList={this.state.todoList} />); } else { return (<ToDoListAdd
onBack={this.onBack} />); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
export default class App extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            current: ‘main’,
            todoList: [
                {
                    level: ‘info’,
                    detail: ‘一般的任务’,
                    isChecked: false,
                    key: ‘0’
                },
                {
                    level: ‘warning’,
                    detail: ‘较重要的任务’,
                    isChecked: false,
                },
                {
                    level: ‘error’,
                    detail: ‘非常重要且紧急的任务’,
                    isChecked: false,
                    key: ‘2’
                }
            ]
        }
        this.onAddItem = this.onAddItem.bind(this);
        this.onBack = this.onBack.bind(this);
        this.toggleCheckAll = this.toggleCheckAll.bind(this);
        this.toggleItemCheck = this.toggleItemCheck.bind(this);
    }
    onAddItem() {
        this.setState((prevState) => {
            return {
                current: ‘add’
            }
        });
    }
    onBack() {
        this.setState({
            current: ‘main’
        });
    }
    toggleCheckAll() {
        const flag = this.isAllChecked();
        const newTodos = this.state.todoList.map(item => {
            return {
                …item,
                isChecked: !flag
            };
        });
        this.setState({
            todoList: newTodos
        });
    }
    toggleItemCheck(item, key) {
        const newTodos = this.state.todoList.map(todo => {
            if (todo !== item) {
                return todo;
            }
            return {
                …todo,
                isChecked: !item.isChecked
            }
        });
        this.setState({
            todoList: newTodos
        });
    }
    isAllChecked() {
        if (!this.state.todoList) return false;
        if (this.state.todoList.length === 0) return false;
        return this.state.todoList.every(item => item.isChecked);
    }
    render() {
        if (this.state.current === ‘main’) {
            return (<ToDoListMain
                isAllChecked={this.isAllChecked()}
                toggleCheckAll={this.toggleCheckAll}
                toggleItemCheck={this.toggleItemCheck}
                onAddItem={this.onAddItem}
                todoList={this.state.todoList} />);
        } else {
            return (<ToDoListAdd onBack={this.onBack} />);
        }
    }
}

我们看到App组件有八个情形,三个是current,用以内定当前渲染的是哪位分界面(其实我们那边就多个分界面)。另三个是todoList数据源。

分界面是什么切换的啊?

阅览render函数,里面正是分界面渲染逻辑,若是this.state.current的值是main,那么就能够渲染App就能够渲染ToDoListMain,不然,渲染ToDoListAdd。你能够领略成,大家手动完成了三个特意轻易的前端路由。这一切都是基于当state生成时,相应的界面自动重新渲染了。

更实际地以来,大家把onAddItem作为props的两日质量传给ToDoListMain,把onBack也作为贰特性质传给ToDoListAdd。所以当它们的头顶相应文字被点击时,实际上调用的,是概念在App组件中的回调函数。回调函数修改了current状态,而current状态的改造引起了App的render函数重新被调用,它依据近日的current状态而再次渲染了相应的分界面。

todoList中每项的key值是给FlatList作为独一标记用的。

另外,在setState句子中,大家会组织三个新的变量,然后一把setState,并不是去修改原有的state。那也是奇骏N中的常用做法。对于初学者的话,恐怕语法有一些奇异。不过,那样做是有它的说辞的。简单来说,因为LX570N在底部大批量使用了比较对象是还是不是变动的逻辑,假设各个便利对象的各类属性,何况对象很复杂的话,这一个相比的逻辑是极慢的。不过,相比很多个对象的引用是还是不是等于却很轻易,直接二个表明式就可以了。所以,我们在setState时数十次会组织贰个新的指标。越来越深的机理就留给读者去追究啦。

好了,让我们运行初步后,看看效果怎么着呢。

图片 2

本文通过二个ToDo
List的事例,介绍了福特ExplorerN中最核心的多少个概念state和props。并简短完结了情形提高、组件间的通讯等职能。

不过那一个例子还没完。那么些ToDo
List近期只是一个出示的职能,怎么着对它们举行编辑、增添、删除,后续会尤其分享。

文章中使用到的源码下载:
todo-list.zip

1 赞 收藏
评论

图片 3

React Native基础&入门教程:以二个To Do List小例子,看props和state

2018/08/09 · 基本功才能 ·
React Native

原稿出处:
葡萄干城技术公司   

在上篇中,大家介绍了怎么是Flexbox布局,以及怎样利用Flexbox布局。还并未有看过的伙伴迎接回到文章列表点击查阅在此之前的小说领悟。

那正是说,当我们有了大旨的布局概念之后,就足以做一些风趣的品味了。可是,它们会有叁个美中不足:只是不识不知地呆在那边,不收受举报。换句话说,它们从使用起来到甘休,独有一种状态。

留心,下面这句话实际包括了安德拉N中(当然同有的时候候也是React中)四个要命重大的定义:

  • 率先,“从使用起来到竣事”,意味着它在岁月上有一段生命周期(Life
    Cycle)
  • 其次,应用其实能够享有很多种状态(State),比方,不荒谬时是一种景况,出错开上下班时间是另一种意况。而且那个情状能够在少数标准下进展改换。

基本概念:

在SportageN中,分界面包车型地铁变型对应着程序状态的成形。或然说,分界面包车型大巴变化,正是因为使用的情景发生了转移而产生的。应用的场所首要由八个变量支配,props和state,它们能够存在于继续自React.Component的每三个零件中。state由组件自个儿定义,用来管理组件及其子组件的图景。而props来自于父组件,在本组件中一定于常量,它的退换格局只可以来自于父组件。

在翼虎N中,分界面包车型客车转换对应着程序状态的变动。恐怕说,分界面包车型地铁变动,就是因为使用的动静发生了更改而致使的。应用的气象首要由多个变量支配,props和state,它们能够存在于继续自React.Component的每三个组件中。state由组件自己定义,用来治本组件及其子组件的景况。而props来自于父组件,在本组件中一定于常量,它的退换情势只好来自于父组件。

state和props都不容许手动地一贯设值。像this.state.a = 1恐怕this.props.b =
2这种代码是会报错的。要改造state,只可以是在本组件中调用this.setState方法。而要改换props,只好注重于它的值在传下来以前,已经在其父组件中被改变。

既是在组件中,state属性无论从字面意思如故程序语义上,都以用来表示境况的,那么为啥还要求一个props属性呢?

自家的精晓重要有两个原因。

先是,因为有一点点组件其实是“无状态”的。它们只是接受父组件传给它们的东西,然后安安分分把它们渲染出来。它们自身内部不保留任何景况,它们只是对父组件状态的反馈。或许说:“它们不生养地方,它们只是父组件状态的显示屏。”父组件的情况通过props传递给子组件。大家平日会组织这种无状态的组件,因为它义务单一,封装性好,可看做更眼花缭乱组件的内核。

第二,由于父组件与子组件之间频仍供给联合浮动,props正是最直接的提供联动的一手。父组件中构造子组件时,就像是函数调用的传参一样,把需求的事物传给子组件的props。

state和props的重要特色是,暗中认可景况下。当它们改造时,QX56N会自动东西渲染与之有关的分界面以保险和state与props同步。为啥说“暗中同意境况下”,是因为我们得以应用生命周期函数手动“截断”这几个渲染逻辑,本文暂不涉及。

别的,在卡宴N中,其实也能够采用不属于props和state的变量,来手动调控组件的状态。但是不引入这么做。因为那会使事态的决定方法变得不合併,不便中华民族解放先锋前时期维护。

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图