客户端高性能组件化框架React简介、特点、环境搭建及常用语法
明天就是除夕了 简介React是这两年非常流行的框架 React达到了5w8+的star(1w+就很了不起了) 感兴趣的同学,给大家设置一个传送门:Github-JavaScript-most stars React并不难,还是挺容易上手的 传统页面从服务器获取数据,显示到浏览器上,用户输入数据传入服务器 总之就是Facebook对市场上所有JS-MVC框架都不满意,认为都不适合大规模应用 MVC科普一下MVC
简单的理解一下 这里我要特别说明一下,虽然介绍了MVC 框架特点React它具有以下特点
环境搭建我选择使用webpack搭建环境 module.exports = {
entry: {
index: './src/js/entry.js'
},output: {
path: './static/dist/',publicPath: 'http://localhost:8080/static/dist/',filename: '[name].js'
},module: {
loaders: [
{
test: /.js$/,loader: 'babel',query: {
presets: ['react','es2015']
}
},{
test: /.less$/,loader: 'style!css!less'
}
]
}
}
这里的关键就是除了要安装 全部依赖模块在这里 "devDependencies": {
"babel-core": "^6.22.1","babel-loader": "^6.2.10","babel-preset-es2015": "^6.22.0","babel-preset-react": "^6.22.0","css-loader": "^0.26.1","less": "^2.7.2","less-loader": "^2.2.3","react": "^15.4.2","react-dom": "^15.4.2","style-loader": "^0.13.1","webpack": "^1.14.0","webpack-dev-server": "^1.16.2"
}
JSX简单说一下React的JSX语法是个神马东西 return (
<div>hehe<div>
)
这就是JSX代码,它是React提供的语法糖 如果使用JS代码也可以,不过官方推荐使用JSX JSX语法结构说的通俗一点就是HTML、JS混写 这样的语法结构是怎样解析的呢?其实并不神奇
不理解不要慌,看了下面就懂了 渲染到页面终于写到语法正题了 var React = require('react');
var ReactDom = require('react-dom');
ReactDom.render()是react最最基本的方法 <div id="root"></div>
现在页面中什么也没有 ReactDom.render(
<h1>Demo</h1>,document.getElementById('demo')
);
第一个参数是要插入的组件(不过我们这里插入了一个DOM节点) 页面中出现了“Demo” 实际上react将我们的节点插入到了div节点的内部 组件化React的一大特点就是组件化
组件生成React.createClass()就是用于将代码封装成组件的方法 var App = React.createClass({
render: function(){
return (
<p>This is a component...</p>
)
}
});
这个方法参数是一个对象
所以各位,下面的写法都是不对的 //错误的写法
var app = React.createClass({
render: function(){
return <p>This is a component...</p>
}
})
//错误的写法
var App = React.createClass({
render: function(){
return (
<p>This is a component...</p>
<p>This is also a component...</p>
)
}
});
组件两边加括号的目的,是为了防止JavaScript自动分号机制产生问题 组件渲染生成的组件要想渲染到页面 ReactDom.render(
<App></App>,document.getElementById('root')
);
组件要写成标签的形式 组件特性为了加以区分,我把标签的属性叫组件特性 var App = React.createClass({
render: function(){
return <p name="demo">This is a component...</p>;
}
});
ReactDom.render(
<App></App>,document.getElementById('root')
);
还要注意两个特例
因为他们是JavaScript的保留字 如果想要为组件添加内联样式,可以这样写 var App = React.createClass({
render: function(){
var styles = {
color: '#fff',backgroundColor: '#000'
}
return <p className="demo" style={styles}>This is a component...</p>; // <--
}
});
ReactDom.render(
<App></App>,document.getElementById('root')
);
声明了一个styles对象 组件属性this.props组件的属性同样可以像html一样添加 var App = React.createClass({
render: function(){
return <p>name:{this.props.name} age:{this.props.age}</p>;
}
});
ReactDom.render(
<App name="payen" age="20"></App>,document.getElementById('root')
);
了解了这个,我们可以做一个小练习 var data = ['Mr.A','Mr.B','Mr.C'];
可以将这个数组成为组件属性 var List = React.createClass({
render: function(){
return (
<ol>
{
this.props.data.map(function(item,index){
return <li key={1000 + index}>{item}</li>;
})
}
</ol>
)
}
});
ReactDom.render(
<List data={data}></List>,document.getElementById('root')
);
还要注意 这里我就使用了1000加上索引的形式添加了key值 this.props.children通常组件的属性与this.props对象中的属性是一一对应的 ReactDom.render(
<List data={data}>
<span>Mr.D</span>
<span>Mr.E</span>
</List>,document.getElementById('root')
);
我们发现页面中并没有什么变化,但浏览器也没有报错 var data = ['Mr.A','Mr.C'];
var List = React.createClass({
render: function(){
console.log(this.props.children);
return (
<ol>
{
this.props.data.map(function(item,index){
return <li key={1000 + index}>{item}</li>;
})
}
{
this.props.children
}
</ol>
)
}
});
ReactDom.render(
<List data={data}>
<span>Mr.D</span>
<span>Mr.E</span>
</List>,document.getElementById('root')
);
如此页面中就显示出了子节点 这个this.props.children很奇怪,它有三种类型值
(可以在控制台上输出验证) var data = ['Mr.A','Mr.C'];
var List = React.createClass({
render: function(){
return (
<ol>
{
this.props.data.map(function(item,index){
return <li key={1000 + index}>{item}</li>;
})
}
{
React.Children.map(this.props.children,function(child){
return <li>{child}</li>
})
}
</ol>
)
}
});
ReactDom.render(
<List data={data}>
<span>Mr.D</span>
<span>Mr.E</span>
</List>,document.getElementById('root')
);
组件验证组件的属性可以接受任何值,数字、字符串、函数、对象什么都可以 var data = ['Mr.A','Mr.C'];
var App = React.createClass({
propTypes: {
data: React.PropTypes.array
},render: function(){
return (
<div>{this.props.data}</div>
)
}
});
ReactDom.render(
<App data={data}></App>,document.getElementById('root')
);
这里我期望的data属性值为array数组类型 详细见React中文官网:Prop 验证 组件嵌套还记得React单向数据流的特点么 var data = ['Mr.A',index){
return <li key={1000 + index}>{item}</li>;
})
}
</ol>
)
}
});
var App = React.createClass({
render: function(){
return (
<div>
<List data={this.props.data}></List>
</div>
)
}
});
ReactDom.render(
<App data={data}></App>,document.getElementById('root')
);
所呈现的DOM结构 生命周期生命周期不难理解
关于这些API更详细的信息 组件状态上面提到了this.state,和我们之前介绍的this.props一样重要 组件交互在此之前我们需要了解的就是React的事件系统 React的事件处理器会传入虚拟事件对象的实例(一个对浏览器本地事件的跨浏览器封装) 详细支持事件见中文官网:事件系统-支持的事件 现在我们要来实现这样一个简单的功能 先来实现结构与样式 var App = React.createClass({
render: function(){
return (
<div>
<button>点击</button>
<PopUp></PopUp>
</div>
)
}
});
var PopUp = React.createClass({
render: function(){
var styles = {
position: 'absolute',left: '40px',top: '40px',width: '100px',height: '100px',backgroundColor: '#f40'
}
return (
<div className="popup" style={styles}></div>
)
}
})
ReactDom.render(
<App/>,document.getElementById('root')
);
首先我们先来实现第一个功能:点击按钮出现弹框 var App = React.createClass({
getInitialState: function(){
return {
open: false
}
},buttonHandler: function(){
this.setState({
open: true
});
},render: function(){
return (
<div>
<button onClick={this.buttonHandler}>点击</button>
<PopUp open={this.state.open}></PopUp>
</div>
)
}
});
var PopUp = React.createClass({
render: function(){
var styles = {
position: 'absolute',backgroundColor: '#f40'
}
if(this.props.open){
styles.display = 'block';
}else{
styles.display = 'none';
}
return (
<div className="popup" style={styles}></div>
)
}
})
ReactDom.render(
<App/>,document.getElementById('root')
);
第一个功能实现了,再来看第二个 var App = React.createClass({
getInitialState: function(){
return {
open: false
}
},popupHandler: function(){
this.setState({
open: false
});
},render: function(){
return (
<div>
<button onClick={this.buttonHandler}>点击</button>
<PopUp open={this.state.open} handler={this.popupHandler}></PopUp>
</div>
)
}
});
var PopUp = React.createClass({
render: function(){
var styles = {
position: 'absolute',backgroundColor: '#f40'
}
if(this.props.open){
styles.display = 'block';
}else{
styles.display = 'none';
}
return (
<div className="popup" style={styles} onClick={this.props.handler}></div>
)
}
})
ReactDom.render(
<App/>,document.getElementById('root')
);
用一句话来总结一下,那就是数据都交给父级来管理 获取真实DOM节点我们已经知道了 还是通过一个小例子来解释 var Input = React.createClass({
getInitialState: function(){
return {
val: ''
}
},changeHandler: function(){
this.setState({
val: this.refs.node.value
});
},render: function(){
return (
<div>
<input type="text" ref="node" onChange={this.changeHandler}/>
<p>{this.state.val}</p>
</div>
)
}
});
ReactDom.render(
<Input/>,document.getElementById('root')
);
我为input标签设置了ref值为node 获取真实DOM节点还有一个不常用的方法 <input type="text" ref={function(dom){this._node = dom}.bind(this)} onChange={this.changeHandler}/>
向ref属性中添加一个匿名函数 changeHandler: function(){
this.setState({
val: this._node.value
});
}
还要注意的一点是
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |