React学习笔记-8-属性和状态详解
- 属性的含义和用法
props=properties 英文中属性的意思。属性不可以修改,也就是属性不可以由组件进行修改,组件的属性是由父组件传递过来的,相当于组件在出生的时候带的。用法
第一种:直接在调用组件的时候传入一个键值对,
这个键值对可以是字符串:<HelloWorld name="李明"></HelloWorld>
可以是大括号:大括号本质上是一个js的求值表达式,里面可以写很多内容,最简单的就是写数据,直接拿到的数字
<HelloWorld name={123}></HelloWorld>可以是大括号,里面是字符串:他的值就是里面的字符串,当然在实例的使用中,我们直接入第一个一样使用。
<HelloWorld name={"Tim"}></HelloWorld>可以是一个数组:这样属性拿到的也是一个数组,在编写多选框和表单的时候用的多看,组件可以根据传入的属性来构建子组件
<HelloWorld name={[1,2,3]}></HelloWorld>可以直接传入一个变量:这个变量可以在外部定义,然后在组件里面去引用他。变量可以是一个数组,对象,字符串,数值都可以,
<HelloWorld name={variable}></HelloWorld>可以是函数求值表达式:就是直接定义一个函数并调用他,一个的形式就是两个括号放在一起,这样我们就可以定义一个匿名函数并调用他,大括号的值就是匿名函数的返回值.
第二种:可以理解为展开,我们使用这三个点,就可以直接把里面的值拿出来,可以拿到两个属性,如果把三个点去掉,HelloWorld拿到的就是一个props对象,还得自己展开。
var props={
one:"123",
two:321,
} <HelloWorld {...props} />这个props有两个属性,一个one,一个two,如果我们使用第一种键值对的方式,就得写两个,这样写起来比较繁琐,而且我们如果修改props,就得修改下面的属性引用。代码的可维护性不高,而且动态性不高。
var props={
one:"123",
two:321,
} <HelloWorld one={props.one} two={props.two} />第三种:最不常用的,setProps可以设置组件的属性,他接受的参数是一个对象,他会用这个对象来更新属性,但是在实际使用中,很好用这个因为我们是不能够在组件内部去修改属性的,这样会违背react的设计原则。在组件外部直接用上面两种。
instance.setProps({name:"Tom"}) - 实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
var style={
color:"red",
border:"1px solid #f09", };
var HelloWorld=React.createClass({
render: function(){
return <p>Hello,{this.props.name ? this.props.name : "world"}</p>
},
});
var HelloUniverse=React.createClass({
getInitialState:function(){
return {name:''};
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render:function(){
return <div>
<HelloWorld name={this.state.name}></HelloWorld>
<br/>
<input type="text" onChange={this.handleChange} />
</div>
},
});
React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body); </script>
</body>
</html>注意图中的红色标记区域,如果把div和return分开放在两行就会报错,如下
报错:
Uncaught Error: Invariant Violation: HelloUniverse.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
修改代码使用第二种赋值方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
var style={
color:"red",
border:"1px solid #f09", };
var HelloWorld=React.createClass({
render: function(){
return <p>Hello,{this.props.name1+' '+this.props.name2}</p>
},
});
var HelloUniverse=React.createClass({
getInitialState:function(){
return {
name1:'tom',
name2:'John',
};
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render:function(){
return <div>
<HelloWorld {...this.state}></HelloWorld>
<br/>
<input type="text" onChange={this.handleChange} />
</div>
},
});
React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body); </script>
</body>
</html>第三种:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
var style={
color:"red",
border:"1px solid #f09", };
var HelloWorld=React.createClass({
render: function(){
return <p>Hello,{this.props.name ? this.props.name : "world"}</p>
},
});
var instance=React.render(<HelloWorld></HelloWorld>,document.body);
//这里返回的是react的返回值,这里设置的是HelloWorld的属性,并且render函数进行了更新
instance.setProps({name:'tom'}) </script>
</body>
</html> - 状态的含义和用法
状态 state:使用this.state来引用,state本身就是状态的意思,状态指的是事物所处的状况,状况就是环境。注意:状态是事物自己处理的,不和属性一样,属性是天生的,事物一般来说没有办法修改。状态是事物本身的是事物的私有属性,也就是由自己决定,父组件和子组件都不能改变他。给定了状态就一定知道结果是什么。用法:
getInitialState:初始化每个实例特有的状态
setState:更新组件状态,原则上是经常使用的,但是setProps原则上面不推荐你使用,setState会触发的行为,他会调用diff算法。
实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
var style={
color:"red",
border:"1px solid #f09", };
var HelloWorld=React.createClass({
render: function(){
return <p>Hello,{this.props.name}</p>
},
});
var HelloUniverse = React.createClass({
getInitialState: function(){
return {
name: 'Tom',
};
},
handleChange:function(event){
this.setState({name:event.target.value});
},
render: function(){
return <div>
<HelloWorld name={this.state.name}></HelloWorld>
<br />
<input type="text" onChange={this.handleChange} />
</div>
},
});
React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body) </script>
</body>
</html> - 属性和状态对比
属性和状态的相似点:
4.1.1都是纯js对象
4.1.2都会触发render函数更新
4.1.3都具有确定性
状态相同,结果一定相同,这就是确定性。给定了相同的属性或者相同的状态,结果都是一样的。属性 状态
能否在父组件获取初始值 可以 不可以
能否有父组件进行修改 可以 不可以
能否在组件内部设置默认值 可以 可以
能否在组件内部修改 不可以 可以
能否设置子组件的初始值 可以 不可以
能否修改子组件的初始值 可以 不可以 - 如何区分属性和状态
组件在运行时需要修改的数据就是状态。
属性的核心要点就是不能修改! - 属性和状态实战
编写一个简单的文章评论框
第一步:分析构成项目的组件。 第二步:分析组件的关系及数据传递 第三步:编写代码6.1添加两个组件,并用React.render渲染到页面上,Content内容组件,Comment评论框组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>属性和状态实战</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
render:function(){
return <p>content</p>;
},
});
//父组件
var Comment = React.createClass({
render:function(){
//我们现在东西是写死的,下一个例子的写法是动态的生成。
return <Content></Content>;
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.2在Comment里面添加一个下拉列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>属性和状态实战</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
render:function(){
return <p>content</p>;
},
});
//父组件
var Comment = React.createClass({
render:function(){
//我们现在东西是写死的,下一个例子的写法是动态的生成。
return <div>
<select>
<option value="1">Tim</option>
<option value="2">Jerry</option>
<option value="3">LiMing</option>
<option value="4">Jhon</option>
</select>
<Content></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.3在父组件comment里面添加一个getInitialState组件,names属性的值是一个数组。这样的好处是后面如果加入新的回复对象,我们可以进行更新。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>属性和状态实战</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
render:function(){
return <p>Content</p>;
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"]
};
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={option}>{this.state.names[option]}</option>)
};
return <div>
<select>
{options}
</select>
<Content></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.4(我们这个例子有bug,选中以后弹出的是选项的角标,6.5中会有讲解。)父组件comment里面增加了handleSelect函数来处理select的选中事件,然后在select里面添加onChange事件,并且给他绑定handleSelect事件,当我们在select选中选项的时候,就会触发handleSelect事件,他会将我们选中的值赋值给state中的selectName属性,由于我们要将这个selectName赋值给我们的子组件,所以需要在getInitialState里面初始化一个selectName,并且赋值为空,最后我们在content组件里面给selectName赋值,他的值为this.state.selectName,也就是我们选中的名字,还要注意我们需要在content组件中,将我们拿到的组件的属性显示出来。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>弹出1 2 3</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
render:function(){
return <p>{this.props.selectName}</p>;
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"],
selectName:'',
};
},
handleSelect:function(event){
this.setState({selectName:event.target.value});
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={option}>{this.state.names[option]}</option>)
};
return <div>
<select onChange={this.handleSelect}>
{options}
</select>
<Content selectName={this.state.selectName}></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.5在我做这个例子的时候,由于书写错误,导致6.4中弹出的是选项的角标,注意看for循环里面的修改。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
render:function(){
return <p>{this.props.selectName}</p>;
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"],
selectName:'',
};
},
handleSelect:function(event){
this.setState({selectName:event.target.value});
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={this.state.names[option]}>{this.state.names[option]}</option>)
};
return <div>
<select onChange={this.handleSelect}>
{options}
</select>
<Content selectName={this.state.selectName}></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.6修改子组件,在content里面添加了一个getInitialState,里面返回了一个text,在render里面添加了一个textarea,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
getInitialState:function(){
return {
text: "replay To:"+this.props.selectName,
};
},
render:function(){
return <div>
<textarea placeholder="请输入..."></textarea>
</div>
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"],
selectName:'',
};
},
handleSelect:function(event){
this.setState({selectName:event.target.value});
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={this.state.names[option]}>{this.state.names[option]}</option>)
};
return <div>
<select onChange={this.handleSelect}>
{options}
</select>
<Content selectName={this.state.selectName}></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.7给content添加一个handleChange函数,在getInitialState里面添加一个inputText,给textarea绑定handleChange函数,将我输入的内容赋值给inputText。页面无变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
getInitialState:function(){
return {
text: "replay To:"+this.props.selectName,
inputText:"",
};
},
handleChange:function(){
this.setState({inputText:event.target.value});
},
render:function(){
return <div>
<textarea onChange={this.handleChange} placeholder="请输入..."></textarea>
</div>
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"],
selectName:'',
};
},
handleSelect:function(event){
this.setState({selectName:event.target.value});
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={this.state.names[option]}>{this.state.names[option]}</option>)
};
return <div>
<select onChange={this.handleSelect}>
{options}
</select>
<Content selectName={this.state.selectName}></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.8增加了handleSubmit事件,把我们text和inputText里面的内容输出到控制台。render里面新增一个button,并且给他绑定handleSubmit函数,注意button事件为onClick,不是onChange.可以打开控制台看看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
getInitialState:function(){
return {
text: "replay To:"+this.props.selectName,
inputText:"",
};
},
handleChange:function(){
this.setState({inputText:event.target.value});
},
handleSubmit:function(){
console.log(this.state.text + "\n" + this.state.inputText);
},
render:function(){
return <div>
<textarea onChange={this.handleChange} placeholder="请输入..."></textarea>
<button onClick={this.handleSubmit}>submit</button>
</div>
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"],
selectName:'',
};
},
handleSelect:function(event){
this.setState({selectName:event.target.value});
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={this.state.names[option]}>{this.state.names[option]}</option>)
};
return <div>
<select onChange={this.handleSelect}>
{options}
</select>
<Content selectName={this.state.selectName}></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>6.9上面那个实力有错误,我们需要修改一下。父组件中,会把select内容传递给selectName,没有问题。在子组件content里面,由于使用了getInitialState函数,当我们父组件select再次发生变化的时候,getInitialState不会再次调用,导致我们的replay to 后面没有内容,所以我们需要将它放在console里面,也就是最后。我们在getInitialState里面移除了text,把它放在最后使用它的位置。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script>
<script type="text/jsx">
//子组件
var Content=React.createClass({
getInitialState:function(){
return {
//由于这里不会更新,所以我们下拉选人的时候,控制台没有报,我们修改一下
//text: "replay To:"+this.props.selectName,
inputText:"",
};
},
handleChange:function(){
this.setState({inputText:event.target.value});
},
handleSubmit:function(){
//把计算的部分放到我们要用到的地方,要不输出的时候,不是我们最新的。
console.log("replay To: "+this.props.selectName+ "\n" + this.state.inputText);
},
render:function(){
return <div>
<textarea onChange={this.handleChange} placeholder="请输入..."></textarea>
<button onClick={this.handleSubmit}>submit</button>
</div>
},
});
//父组件
var Comment = React.createClass({
getInitialState:function(){
return {
names:["Tim","John","Hank"],
selectName:'',
};
},
handleSelect:function(event){
this.setState({selectName:event.target.value});
},
render:function(){
var options=[];
for(var option in this.state.names){
options.push(<option value={this.state.names[option]}>{this.state.names[option]}</option>)
};
return <div>
<select onChange={this.handleSelect}>
{options}
</select>
<Content selectName={this.state.selectName}></Content>
</div>
},
});
React.render(<Comment></Comment>,document.body);
</script>
</body>
</html>
React学习笔记-8-属性和状态详解的更多相关文章
- IP地址和子网划分学习笔记之《IP地址详解》
2018-05-03 18:47:37 在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. ...
- 零拷贝详解 Java NIO学习笔记四(零拷贝详解)
转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...
- react.js 从零开始(四)React 属性和状态详解
属性的含义和用法: 1.属性的含义. props=properties 属性:一个事物的性质和关系. 属性往往与生俱来,不可以修改. 2. 属性的用法. <Helloworld name=??? ...
- Java学习笔记 线程池使用及详解
有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...
- 学习笔记——Maven pom.xml配置详解
POM的全称是“ProjectObjectModel(项目对象模型)”. pom.xml详解 声明规范 <projectxmlns="http://maven.apache.org/P ...
- linux命令学习笔记(25):linux文件属性详解
Linux 文件或目录的属性主要包括:文件或目录的节点.种类.权限模式.链接数量.所归属的用户和用户组. 最近访问或修改的时间等内容.具体情况如下: 命令: ls -lih 输出: [root@loc ...
- IOS学习笔记37——ViewController生命周期详解
在我之前的学习笔记中讨论过ViewController,过了这么久,对它也有了新的认识和体会,ViewController是我们在开发过程中碰到最多的朋友,今天就来好好认识一下它.ViewContro ...
- [读书笔记]C#学习笔记八:StringBuilder与String详解及参数传递问题剖析
前言 上次在公司开会时有同事分享windebug的知识, 拿的是string字符串Concat拼接 然后用while(true){}死循环的Demo来讲解.其中有提及string操作大量字符串效率低下 ...
- 学习笔记——Maven settings.xml 配置详解
文件存放位置 全局配置: ${M2_HOME}/conf/settings.xml 用户配置: ${user.home}/.m2/settings.xml note:用户配置优先于全局配置.${use ...
随机推荐
- 【Codeforces235C】Cyclical Quest 后缀自动机
C. Cyclical Quest time limit per test:3 seconds memory limit per test:512 megabytes input:standard i ...
- 文档分享-Activiti 5.16 用户手册
今天在翻看工作流相关的网页的时候,在开源中国上http://www.oschina.net/question/915507_149175发现activiti的中文文档:http://www.mossl ...
- sift特征源码
先贴上我对Opencv3.1中sift源码的注释吧,虽然还有很多没看懂.先从detectAndCompute看起 void SIFT_Impl::detectAndCompute(InputArray ...
- 自己动手编写spring IOC源码
前言:对于spring IOC概念不是很了解的朋友可以阅读我上一篇博客--轻松理解spring IOC(这两篇博客也是由于我的个人原因导致现在才发布,惭愧啊).通过这篇博客的理解之后,相信大家会对sp ...
- [Java] JSP笔记 - 自定义标签
自定义标签的创建步骤: 自定义标签的四大功能: 自定义标签的类结构: 在 1.0 中呢, 可以将 <body-content> 的值设置为 JSP, 2.0中则不允许在自定义标签体中出现j ...
- T-SQL 关闭数据库所有连接
原文引用自: http://www.cnblogs.com/kissazi2/p/3462202.html 下面给出一种删除数据库活动连接的方式.将下面代码段中的"--修改一下"处 ...
- 共有31款PHP 图形/图像处理开源软件(转)
详情点击:http://www.oschina.net/project/lang/22/php?tag=141&os=0&sort=view PHP 图像处理库 Grafika Gra ...
- nGrinder安装指南
NGrinder 由两个模块组成,其运行环境为 Oracle JDK 1.6 nGrinder controller web 应用程序,部署在Tomcat 6.x 或更高的版本 nGrinder A ...
- 实战动态PDF在线预览及带签名的PDF文件转换
开篇语: 最近工作需要做一个借款合同,公司以前的合同都是通过app端下载,然后通过本地打开pdf文件,而喜欢创新的我,心想着为什么不能在线H5预览,正是这个想法,说干就干,实践过程总是艰难的,折腾了3 ...
- Apache服务器安装过程及问题的解决(for windows system32bit)
在使用Hbuilder设计网站时,在制作本站搜索时,用到了Php文件,而Hbuilder的内置web服务器不支持php的解析, 所以需要安装配置外部服务器,有多个选择,我安装的apache服务器,并遇 ...