render(){ // Every react component has a render method.
return( // Every render method returns jsx. Jsx looks like HTML, but it's actually javascript and functions a lot like xml, with self closing tags requiring the `/` within the tag in order to work propperly
<div>
Hello World
</div>
);
}
}
注意这里"Hello World"写在 div中. 所有的jsx代码都需要写在一个父div中.
最后我们需要把我们写好的组件render给Dom,这里就需要用到 ReactDOM.render 方法.
在 App.js 的下面添加: ReactDOM.render(<App />, document.getElementById('app'));
第一个参数就是我们App的根组件, 写作<App />的形式. 第二个参数就是我们的APP将要主要的DOM元素. 在这个项目中,就是我们在index中写的id为app的 div标签。
Ok,我们的APP结构已经出来了,经典的hello world已经实现。马上我们就在这个基础上再实现经典的todo app。大致的原型就有一个输入框用来输入代办事项然后添加到事件列表中。事件列表中每一
个代办事项被点击就会标注一条删除线表示完成,点击后面的删除按钮则会将其从列表中删除。通过完成这个APP的过程你将学会一个完整的react app的所有的基本构建块。
生命周期方法和两种形式的组件构建生命周期方法和两种形式的组件构建
我们从一些小的模块开始起步.一个组件component就是一个react app的构件块. 有两种形式的组件: 类组件(Class)和函数型组件(Functional). 在这个项目中,这两种形式的组件我们都会使用, 并且使
用生命周期的钩子,同时也会使用state和props两个react中重要的属性。
首先在 src文件夹中新建components 文件夹,你的文件结构就是这样 ~/src/components。
然后在components中新建文件 ToDoApp.js。 对于所有的react组件我们都需要在头部引入reactimport React from 'react';。
下面我们写一个类组件. 所有的class 组件有一个render方法用来返回jsx。
ToDoApp的class就如下所示:
class ToDoApp extends React.Component {
render() {
return (
<div>To Do App</div>
);
}
}
为了将这个组件注入到我们的APP中, 首先我们需要输出它。 在这个组件代码底部添加 export default ToDoApp;。
然后在app.js顶部我们添加 import ToDoApp from '.components/ToDoApp'; 导入组件用来代替 Hello World 。 render中替换为新的jsx代码 <ToDoApp />半闭合类型的标签即可。
然后在浏览器中你就可以看到"To Do App" 代替了原来的 "Hello World"!这样我们就完成了将第一个子组件嵌入到根组件之中了,这就是构建react app的常规模式。下面继续完善我们的组件。
返回到ToDoApp 中来构建我们的第一个代办事项列表。首先我们使用bootstrap来构建比较方便且美观。 用下面的jsx替换当前render方法中 return 中的jsx:
<div className="row">
<div className="col-md-10 col-md-offset-1">
<div className="panel panel-default">
<div className="panel-body">
<h1>My To Do App</h1>
<hr/>
List goes here.
</div>
</div>
</div>
</div>
现在打开浏览器, 你将会看到一个标题 "My To Do App" 下面跟随一个bootstrap的panel组件里面写有 "List Goes Here",我们将在这个地方构建列表。 那么我们如何将数据存储在我们的列表中呢? 答案
就是使用 state. 每一个类组件都有 state 属性,可以通过 this.state在组件任何位置获取并且用 this.setState({
key: "value" })这种方法来更新状态。但是除非必要我们比较少使用state,这里暂时先使用作为了解,后期会使用redux来管理状态。
在ToDoApp中我们可以使用许多生命周期方法的钩子, 其中一个就是componentWillMount。 这个方法的执行是在页面加载并且render方法之前。可以在其中获取列表数据,在我们的APP中直接用一个虚
拟的数组提供。(值得注意的是componentWillMount会引起很多小问题,因此真实项目中尽量不要使用,而是应该用componentDidMount)。
在 ToDoApp中 render 方法之前添加:
componentWillMount(){ // run before the render method
this.setState({ // add an array of strings to state.
list: ['thing1', 'thing2', 'thing3']
})
};
现在我们获取了一个虚拟列表,需要重点注意的就是react依赖于state和props,只有当state和props改变的时候react组件才会刷新。
现在我们添加列表到这个view里,这里不是直接简单的在里面修改jsx,而是再创建一个新的组件来构建列表,这次我们学习使用函数型组件,需要注意的是函数型组件没有生命周期方法和state属性,它
仅仅是一个返回jsx的函数,并且参数是props。
那么props到底是什么呢?props是从父组件传递进子组件的数据的名字,这是一个很重要的概念,也是react app数据传递的最典型与最推荐的方法。通常我们将数据保持在app的顶端组件,通过组件让
数据流下来保证APP的精确运行。这些数据和props的一些处理可能会影响APP的运行,但是假如你按照这个课程的实践流程来做,这些影响都会很小。
再新建一个components文件夹并在其中新建一个List.js作为我们要创建的函数型组件。用const来新建一个函数,参数名字写作props。
函数形式如下所示:
const List = (props) => { // we're using an arrow function and const variable type, a ES6 features
return (
<div>
I'm a list!!!
</div>
)
};
export default List;
在 ToDoApp.js引入 List用List 组件替换 List goes here.,写法为 <List />.现在在浏览器中就可以看到"I'm a list!!!"
现在我们来把这个变成真实的列表,首先就需要通过props传递数据,我们把这个从state中获取的数据list通过命名为listItems的props传递,写作: <List listItems={this.state.list} /> ,现在 List 已经通过
props获取了 ToDoApp中的数据。
然后在 List 组件中我们需要render一个列表,先用下面的jsx代码代替:
<div>
<ul>
{
list // this is a variable we'll define next
}
</ul>
</div>
注意这个大括号,js可以在这里面执行并将返回添加到view里。首先我们定义一个列表变量:
const list = props.listItems.map((el, i)=>(
// All where doing here is getting the items listItems prop
// (which is stored in the state of the parent component)
// which is an array, and we're running the .map method
// which returns a new array of list items. The key attribute is
// required, and must be unique.
<li key={i}><h2>el</h2></li>
));