关于react,sublime的常用插件
地址:http://www.cnblogs.com/erniu/p/5784319.html
数组的两个方法
//过滤
var arr=[1,2,3,4];
arr.filter(function(item){return item===1})
//[1] 返回,满足条件的新数组;
//遍历
var arr=comments.map(function(item,i){
return (
<li key={i} >//这里必须加个key 值,为了方便react查找,并无其他作用
<p className="userName">{item.userName}说:</p>
<p className="content">{item.content}</p>
<span>删除</span>
</li>
)
})
React 的优点
组件模式:代码复用和团队分工
虚拟 DOM:性能优势
移动端支持:跨终端
使用react的基本结构
<!DOCTYPE html>
<html>
<head>
//导入文件使用
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
// ** Our code goes here! **
</script>
</body>
</html>
上面代码有两个地方需要注意。首先,最后一个 <script> 标签的 type 属性为 text/babel 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel" 。
其次,上面代码一共用了三个库: react.js 、react-dom.js 和 Browser.js ,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。
ReactDOM.render()
ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
JSX 语法
- 遇到'<', 看成html
- 遇到'{', 看成js
- {变量}, 直接解析
- {arr}, 数组则展开里面所有的项
React 使用 JSX 语法,JavaScript 代码中可以写 HTML 代码.
let myTitle = <h1>Hello, world!</h1>;
JSX 语法解释
(1)JSX 语法的最外层,只能有一个节点。
// 错误
let myTitle = <p>Hello</p><p>World</p>;
HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 [JSX 的语法]它允许 HTML 与 JavaScript 的混写
var names = ['Alice', 'Emily', 'Kate'];
ReactDOM.render(
<div>
{
names.map(function (name) {
//name指数组里的每一个值;
//map是遍历数组的方法;
return <div>Hello, {name}!</div>
})
}
</div>,
document.getElementById('example')
);
JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员
var arr = [
<h1>Hello world!</h1>,
<h2>React is awesome</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
组件
React.createClass 方法就用于生成一个组件类,
1,组件类只能包含一个顶层标签,
2,组件类的第一个字母必须大写,
3,jsx语法中,class是关键字,需要写成className,才能设置样式
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
ReactDOM.render(
<HelloMessage name="John" />,
document.getElementById('example')
);
上面代码中,变量 HelloMessage 就是一个组件类。模板插入 <HelloMessage /> 时,会自动生成 HelloMessage 的一个实例(下文的"组件"都指组件类的实例)。所有组件类都必须有自己的 render 方法,用于输出组件。
注意,组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。
添加组件属性,有一个地方需要注意,就是 class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字
this.props.children
它表示组件的所有子节点
PropTypes 就是用来验证组件实例的属性是否符合要求
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
ReactDOM.render(
<MyTitle title='aaa' />,
document.getElementById('example')
);
上面的Mytitle组件有一个title属性。PropTypes 告诉 React,这个 title 属性是必须的,而且它的值必须是字符串。
getDefaultProps 方法可以用来设置组件属性的默认值。
var MyTitle = React.createClass({
getDefaultProps : function () {
return {
title : 'Hello World'
};
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
ReactDOM.render(
<MyTitle />,
document.body
);
获取真实的DOM节点
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref
属性
<div id="container"></div>
<script src="src/react.js"></script>
<script src="src/react-dom.js"></script>
<!-- 解析jsx语法 -->
<script src="src/browser.min.js"></script>
<script type="text/babel">
var container = document.getElementById('container');
//refenrence 引用
var MyComponent = React.createClass({
handleClick: function() {
//真实的DOM元素
var oTextInput = this.refs.myTextInput;
var button = this.refs.button;
button.style.background = 'blue';
oTextInput.focus();
oTextInput.style.background = 'red';
},
render: function() {
return (
<div>
<input type="text" ref="myTextInput" />
<input ref="button" type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
});
ReactDOM.render(
<MyComponent />,
container
);
</script>
上面代码中,组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref 属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。
需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取 this.refs.[refName] 属性。
React 组件支持很多事件,除了 Click 事件以外,还有 KeyDown 、Copy、Scroll 等
this.state
组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI
<div class="box"></div>
<script type="text/babel">
var Hello=React.createClass({
getInitialState:function(){//获取初始状态
return {
liked:true
}
},
handle:function(){
var liked=!this.state.liked;
//点击时,状态切换
this.setState({
liked:liked
})
},
render:function(){
//状态改变时,文本改变,
var text='like';
if(!this.state.liked){
text='don\'t like';
}
return <div onClick={this.handle}>
you {text} it,点击切换
</div>
}
})
ReactDOM.render(
<Hello></Hello>,
document.querySelector('.box')
)
</script>
input 通过改变状态,来获取input输入的值
<script type="text/babel">
var Input=React.createClass({
getInitialState:function(){
return {
text:'hello!'//设置input初始状态,
}
},
changeHandle:function(ev){
var value=ev.target.value;
this.setState({
text:value//改变状态,为输入的值
})
},
render:function(){
var text=this.state.text//获取状态
return (<div>
<input value={text} onChange={this.changeHandle}/>
<p>{text}</p>
</div>)
}
})
ReactDOM.render(
<Input></Input>,
document.querySelector('.box')
)
</script>
上面代码是一个 LikeButton 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。
由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。
通过state改变,来实时获取input输入的值
用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取
<div id="example"></div>
<script type="text/babel">
var Input = React.createClass({
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function () {
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
);
}
});
ReactDOM.render(<Input/>, document.getElementById('example'));
</script>
上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况,
react 练习实例
pubsub(发布者-订阅者模式)
- 导入
<script src="src/pubsub.js"></script>
js库
PubSub.publish('deleteItem',_id)//当事件发生时,发布事件;
在componentDidMount里面订阅事件
PubSub.subscribe('deleteItem',function(evName,_id){ 这里是回调函数,即监听到事件发生时,执行这部分})//发布事件;
学生信息列表,包括筛选,删除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css/bootstrap.css">
<script src="src/react.js"></script>
<script src="src/react-dom.js"></script>
<script src="src/browser.min.js"></script>
<!-- pub publish 发布
sub subscribe 订阅 -->
<script src="src/pubsub.js"></script>
</head>
<body>
<div class="student"></div>
<script type="text/babel">
var data=[
{name:"student1",gender:"女",age:18,height:165,weigth:45,_id:2},
{name:"student2",gender:"男",age:35,height:180,weigth:80,_id:0},
{name:"student3",gender:"女",age:22,height:171,weigth:60,_id:6},
{name:"student4",gender:"男",age:26,height:175,weigth:70,_id:1},
{name:"student2",gender:"女",age:18,height:170,weigth:50,_id:3},
{name:"student4",gender:"女",age:38,height:166,weigth:50,_id:4},
{name:"student3",gender:"男",age:30,height:175,weigth:65,_id:5}
];
var StudentItem=React.createClass({
deleteItem:function(){
var _id=this.props.item._id;
//触发deleteItem事件
PubSub.publish('deleteItem',_id)//发布事件
},
render:function(){
var item=this.props.item;
return (
<tr>
<td>{item.name}</td>
<td>{item.gender}</td>
<td>{item.age}</td>
<td>{item.height}</td>
<td>{item.weigth}</td>
<td><a href="javascript:;" onClick={this.deleteItem}>删除</a> </td>
</tr>
)
}
})
var StudentInfo=React.createClass({
render:function(){
var studentData=this.props.studentData;
return (
<table className="table table-bordered table-hover">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>身高(cm)</th>
<th>体重(kg)</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tb">
{
studentData.map(function(item,i){
return (
<StudentItem item={item}/>
)
})
}
</tbody>
</table>
)
}
})
var StudentApp=React.createClass({
getInitialState:function(){
return {
studentData:this.props.studentData,
gender:'all',
name:''
}
},
genderFilterHandle:function(ev){//选择不同性别,改变状态为相应的状态
this.setState({
gender:ev.target.value
})
},
nameFilterHandle:function(ev){//选择学生名字,改变状态为相应的状态
this.setState({
name:ev.target.value
})
},
//在真实的dom插入进文档时触发
componentDidMount:function(){
var self=this;//因为下面函数的this指向会改变,所以这里保存this;
//相当于监听事件发生,如果发生点击事件,则触发该事件,删除对应的项目;
//订阅事件
PubSub.subscribe('deleteItem',function(evName,_id){
var studentData=self.state.studentData;
studentData=studentData.filter(function(item){
return item._id!==_id;
});
//更新状态和刷新页面,
self.setState({
studentData:studentData
})
})
},
render:function(){
var studentData=this.state.studentData;
var gender=this.state.gender;
var name=this.state.name;
if(gender!=='all'){//判断性别
studentData=studentData.filter(function(item){
return item.gender===gender;//返回满足条件的数组
})
}
if(name!==''){//判断 名字是否为空
studentData=studentData.filter(function(item){
if(item.name.indexOf(name)!=-1){//数组包含输入的值,则返回相应数组;
return item;//返回满足条件的数组;
}
})
}
return (
<div className="container">
<h1>学员成信息表</h1>
<div className="bs-example">
<div className="form-group">
<label>按性别筛选</label>
<select className="form-control" onChange={this.genderFilterHandle}>
<option value="all">all</option>
<option value="男">男</option>
<option value="女">女</option>
</select>
</div>
<div className="form-group">
<label>按名字筛选</label>
<input type="text" className="form-control" placeholder="请输入名字" onChange={this.nameFilterHandle} />
</div>
</div>
<div className="table-responsive">
<StudentInfo studentData={studentData}/>
</div>
</div>
)
}
})
ReactDOM.render(
<StudentApp studentData={data} />,
document.querySelector('.student')
)
</script>
</body>
</html>