您的位置:首页 > Web前端 > React

学习 React(jsx语法) + es2015 + babel + webpack

2016-07-13 22:03 976 查看
视频学习地址:

http://www.jtthink.com/course/play/575


官方地址

https://facebook.github.io/react/


[b]神坑:[/b]

0、【Youneedtospecify'babel-loader'insteadof'babel'.】。解决方案:webpack中的loader:"babel-loader",不要简写为:loader:"babel"

1、每次this.setState都会重新初始化getInitialState中的参数

2、createClass的命名必须以大写开头如,var[b]MySelect[/b]=React.createClass,这里如果定义为myselect就会出错

3、render方法的第一个参数[b]return[/b],html代码的第一行必须和return同一行,剩下的才可以换行,也就是不能让return孤零零的占据一行,或者用括号将html代码括起来

4、如果你是Linux或者mac系统,在执行工具如babel/webpack时记得加上权限(sudo)

5、.babelrc文件中的缩进非常有讲究,必须是两个空格。不讲究也没关系。反正是用webpack来代替.babelrc文件的配置的

6、Html的for属性必须改为htmlFor,class属性必须改为className

7、引入组件必须使用如下形式:import{Mysearch}from'./header.js'

8、和vue很相似。render函数中return的(jsx)Html,最外层必须包含一个div。也就是说不能同时return两个同级的div

html环境搭建(前期学习使用,后期废弃)

<!DOCTYPEhtml>
<html>
<metacharset='utf-8'>
<head>
<title></title>
<scriptsrc="http://cdn.bootcss.com/react/15.0.0/react.min.js"></script>
<scriptsrc="http://cdn.bootcss.com/react/15.0.0/react-dom.min.js"></script>
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
</head>
<body>

</body>
</html>


demo1渲染

<scripttype="text/babel">
ReactDOM.render(
<h1>Hello,world!</h1>,
document.getElementById('example')
);
</script>


[b]demo2循环[/b]

<scripttype="text/babel">
varnav_li=[
<li><ahref='#'>最新电影</a></li>,
<li><ahref='#'>最新评论</a></li>
];
ReactDOM.render(
<ul>{nav_li}</ul>,
document.getElementById('navbar')
)
</script>

<scripttype="text/babel">
varnav_li=['最新电影','最新评论'];
ReactDOM.render(
<ul>
{
nav_li.map(function(item){
return<li><ahref='#'>{item}</a></li>;
})
}
</ul>,
document.getElementById('navbar')
)
</script>


[b]demo3:绑定事件[/b]

<scripttype="text/babel">
varaa=function()
{
alert("123");
}

varnav_li=['最新电影','最新评论'];
ReactDOM.render(
<ul>
{
nav_li.map(function(item){
return<li><ahref='#'onClick={function(){alert('123')}}>{item}</a></li>;
          return<li><ahref='#'onClick={aa}>{item}</a></li>;
})
}
</ul>,
document.getElementById('navbar')
)
</script>


[b]demo4:组件化(重头戏)[/b]

varNavLI=React.createClass({
myFunc:function(){alert("123")},
render:function()
{
return<ul>
<li><ahref='#'onClick={this.myFunc}>最新电影</a></li>
<li><ahref='#'>最新评论</a></li>
</ul>
}
})

ReactDOM.render(
<NavLI/>,
document.getElementById('navbar')
)


[b]demo5:嵌套组件、递归属性(this.props.XXX),注意!!HTML的class在这里是className[/b]

varNavBar=React.createClass({
myFunc:function(){alert("123")},
render:function()
{
return<ul>
<li><ahref='#'onClick={this.myFunc}>最新电影</a></li>
<li><ahref='#'>最新评论</a></li>
<li><SearchTextSearchText_abc={this.props.SearchText_abc}/></li>
</ul>
}
})

varSearchText=React.createClass({
render:function()
{
return<inputtype="text"placeholder="请输入文字"className={this.props.SearchText_abc}/>
}
})

ReactDOM.render(
<NavBarSearchText_abc="Lee"/>,
document.getElementById('navbar')
)


[b]demo6:AJAX实战,在success后必须重新绑定this指针[/b]

#js代码
varMoviesList=React.createClass
({
getInitialState:function()
{
return{
movie:[]
}
},
componentDidMount:function()
{
$.ajax
({
url:"http://zhaohong.com",
success:function(data)
{
data=JSON.parse(data);
console.log(data);
this.setState({movie:data});
}.bind(this)//将AJAX中的this的指针更换为当前对象
})
},
render:function()
{
//console.log("我是reander",this.state.movie);
varmyli=this.state.movie.map(function(item)
{
console.log(item);
return<li>{item.moiveName}</li>
});
return<ul>{myli}</ul>
}
})

ReactDOM.render(
<ul>
<MoviesList/>
</ul>,
document.getElementById('moiveList')
)

#php代码

header("Access-Control-Allow-Origin:*");
$arr=array();
$arr[0]["moiveName"]="美国队长3内战";
$arr[1]["moiveName"]="X战警3天启";
$arr[2]["moiveName"]="大鱼海棠";

$arr[0]["id"]="1";
$arr[1]["id"]="2";
$arr[2]["id"]="3";

$arr[0]["info"]="奥创纪元之后,全球政府联合颁布法令,管控超能力活动。对这条法令的不同态度,使复仇者阵营一分为二,钢铁侠和美国队长各据一方,其他复仇者则不得不做出自己的选择,最终引发前任盟友间的史诗大战。";
$arr[1]["info"]="该片故事以20世纪80年代为背景,讲述了古老强大的第一个变种人天启在埃及醒来,他想统治并改变这个世界,而引发一系列变种人大战的故事";
$arr[2]["info"]="所有人类的灵魂都是海里一条巨大的鱼,出生的时候从海的此岸出发,在路途中,有时相遇,有时分开,死的时候去到海的彼岸,之后变成一条沉睡的小鱼,等待多年后的再次出发,这个旅程永远不会结束,生命往复不息。十六岁生日那天,居住在“神之围楼”里的一个名叫椿的女孩变作一条海豚到人间巡礼,被大海中的一张网困住,一个人类男孩因为救她而落入深海死去。为了报恩,为了让人类男孩复活,她需要在自己的世界里,历经种种困难与阻碍,帮助死后男孩的灵魂——一条拇指那么大的小鱼,成长为一条比鲸更巨大的鱼并回归大海";
exit(json_encode($arr));



[b]demo7:移除组件、移除时的事件[/b]

varNavBar=React.createClass({
myFunc:function(){alert("123")},
myRemove:function(){ReactDOM.unmountComponentAtNode(document.getElementById('navbar'))},
render:function()
{
return<ul>
<li><ahref='#'onClick={this.myFunc}>最新电影</a></li>
<li><ahref='#'onClick={this.myRemove}>最新评论</a></li>
<li><SearchTextSearchText_abc={this.props.SearchText_abc}/></li>
</ul>
},
componentWillUnmount:function(){
alert("我被移除了");
}
})


[b]demo8:Input设置value属性时的问题、由于value是React的保留字段,当对Input书写该属性的时候,会造成input只读。需要配合state+onChange+e.target.value来实现正常input[/b]

varSearchText=React.createClass
({
getInitialState:function()
{
return{
title:"请输入文字"
}
},
myChange:function(e)
{
varv=e.target.value;
this.setState({title:v});
},
render:function()
{
return<inputtype="text"placeholder="请输入文字"value={this.state.title}onChange={this.myChange}className={this.props.SearchText_abc}/>
}
})




[b]Demo9:引入组件,注意label的for属性必须改为htmlFor[/b]

#index.js
varReact=require("react")
varReactDOM=require("react-dom")
import{Mysearch}from'./header.js'

ReactDOM.render(
<Mysearch/>,
document.getElementById('Header')
)

#header.js
varReact=require("react")
varMysearch=React.createClass({
render:function()
{
return(
<divclassName="comm_list_temp">
<divclassName="comm_input">
<ul>
<liclassName="oneline"><labelhtmlFor="min_sales">模板名称:</label>
<inputtype="text"value=""name=""className="nomore"/>
<buttontype="button"className="redbuttonflml-10">搜索</button>
<buttontype="reset"className="whitebuttonflml-10">重置</button>
</li>
</ul>
</div>
</div>
)
}
})

exports.Mysearch=Mysearch;


[b]正片开始,前方高能[/b]

安装babel以及各种插件(es2015/react/react-dom/react解析)

(神坑:文件夹如果也叫react,那么你在npminit时的项目命名千万别和react重名(默认会是你的文件夹名),当然包括其他组件名和框架名都要避免。否则会报错)

安装nodejshttp://nodejs.cn/
安装babel
npminstallbabel-cli-g

安装webpack
npminstallwebpack-g

安装插件(在命令行使用的时候,记得先整合成一行)
npminstall
babel-core
babel-preset-react
babel-preset-es2015
babel-preset-stage-0
react
react-dom
webpack
babel-loader
css-loader
style-loader
webpack-dev-server
html-webpack-plugin
url-loader
--save-dev


webpack.config.js


varHtmlWebpackPlugin=require('html-webpack-plugin');
varwebpack=require('webpack');
varpath=require("path");

module.exports={
entry:{
app:['./src/js/index.js']
},
output:{
path:path.resolve(__dirname,"build/js"),
filename:'[name].js'//最终打包生成的文件名
},
devServer:{
historyApiFallback:true,
hot:true,
inline:true,
progress:true,
port:9091//这个端口你可以自定义
},
module:{
loaders:[
{
test:/\.js|jsx$/,//是一个正则,代表js或者jsx后缀的文件要使用
loader:'babel',
query:{
presets:['es2015','react','stage-0']//必须先安装babel-preset-es2015和babel-preset-react
}
},
{
test:/\.css$/,
loaders:['style','css'],//必须先安装css-loader和style-loader
      },
{
test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader:'url',
query:{
limit:10000,
name:'./build/img/[name].[hash:7].[ext]'
}
},
{
test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader:'url',
query:{
limit:10000,
name:'./build/fonts/[name].[hash:7].[ext]'
}
}    
    ]
  },
plugins:[
//动态将上面编译好的js文件导入到以下html文件中并且生成到指定目录
newHtmlWebpackPlugin({
template:__dirname+'/src/tpl/index.html',
filename:__dirname+'/build/tpl/index.html',
hash:true,
inject:"body",
chunks:['common','app']
}),
    //提取出公共的代码
newwebpack.optimize.CommonsChunkPlugin({
name:"common",//对应entry的对象名称
chunks:['app']
})
]  
}



使用webpack:


sudowebpack


[b]热编译[/b]

每次修改完代码都要手动在控制台中输入webpack是很变态的一件事,最好能每次保存js文件时自动编译。这就是热编译

但是,热编译是热编译、build是build(这里的build指的是在控制台单独使用webpack编译)、一定要区分开来各自的作用。

打开package.json加入

"scripts":{
  "start":"webpack-dev-server--hot--inline"
}


在根目录中新建test/index1.html[b](请务必注意以下代码的script引用规则)[/b]

<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<title>Document</title>
</head>
<body>
<divid="app"></div>

<!--#这个是必须加载的文件-->
<scriptsrc="http://localhost:9091/webpack-dev-server.js"></script>

<!--#这下面就是需要热编译的js,必须是webpack中输出的文件才有效-->
<scriptsrc="http://localhost:9091/common.js"></script>
<scriptsrc="http://localhost:9091/app.js"></script>

</body>
</html>


打开控制台

#开启热编译
npmstart


打开网页:localhost:9091/test/index1.html

当修改该页面引入的js文件时。就会自动编译

注意,这个热编译插件,他是将编译的js放入内存中并且引入到指定的html中。所以并没有生成到build文件夹下,如果想生成还需要手动使用webpack命令

[b]开始React和第三方结合[/b]

React-bootstrap的学习:http://react-bootstrap.github.io/components.html#navbars

npminstallreact-bootstrap--save-dev


页面引入css:

<linkhref="https://cdn.bootcss.com/bootstrap/3.3.6//css/bootstrap.min.css"rel="stylesheet">


js

constReact=require('react');
constReactDOM=require('react-dom');

varNav=require('react-bootstrap').Nav;
varNavItem=require('react-bootstrap').NavItem;
varNavDropdown=require('react-bootstrap').NavDropdown;
varMenuItem=require('react-bootstrap').MenuItem;
varNavbar=require('react-bootstrap').Navbar;

letMyNav=React.createClass({
render:function()
{
return<Navbar>
<Navbar.Header>
<Navbar.Brand>
<ahref="#">React-Bootstrap</a>
</Navbar.Brand>
</Navbar.Header>
<Nav>
<NavItemeventKey={1}href="#">Link</NavItem>
<NavItemeventKey={2}href="#">Link</NavItem>
<NavDropdowneventKey={3}title="Dropdown"id="basic-nav-dropdown">
<MenuItemeventKey={3.1}>Action</MenuItem>
<MenuItemeventKey={3.2}>Anotheraction</MenuItem>
<MenuItemeventKey={3.3}>Somethingelsehere</MenuItem>
<MenuItemdivider/>
<MenuItemeventKey={3.3}>Separatedlink</MenuItem>
</NavDropdown>
</Nav>
</Navbar>
}
})

ReactDOM.render(<MyNav/>,document.getElementById('demo'));


编译即可看到结果

React-amazeui(PC端)的学习:http://amazeui.org/react/getting-started

npminstallamazeui-react--save-dev

npminstallbabel-preset-stage-0

npminstallbabel-plugin-transform-object-rest-spread


.babelrc

{
"presets":["es2015","react","stage-0"],
"plugins":['transform-object-rest-spread']
}


index.js(demo1)

constReact=require('react');
constReactDOM=require('react-dom');
constAMUIReact=require('amazeui-react');

varprops={
title:'AmazeUI',
link:'#title-link',
data:{
left:[
{
link:'#left-link',
icon:'home'
}
],
right:[
{
link:'#right-link',
icon:'bars'
}
]
},
onSelect:function(nav,e){
e.preventDefault();
console.log('你点击了',nav);
//dosomething
}
};

ReactDOM.render(<AMUIReact.Header{...props}/>,document.getElementById('demo'));


index.js(demo2)

constReact=require('react');
constReactDOM=require('react-dom');
constAMUIReact=require('amazeui-react');
constPanel=AMUIReact.Panel;

letMyPanel=React.createClass({
render:function()
{
return<div>
<Panelheader="面板标题">
默认面板
</Panel>
<Panelheader="面板标题"amStyle="primary">
primary-面板
</Panel>
<Panelheader="面板标题"amStyle="secondary">
secondary-面板
</Panel>
<Panelheader="面板标题"amStyle="success">
success-面板
</Panel>
<Panelheader="面板标题"amStyle="warning">
warning-面板
</Panel>
<Panelheader="面板标题"amStyle="danger">
danger-面板
</Panel>
</div>
}
})

ReactDOM.render(<MyPanel/>,document.getElementById('demo'));


amazeuitouch(移动端):http://t.amazeui.org/#/docs?_k=4cmux8

#下载
npminstall--save-devamazeui-touch

sudonpminstallreact-router--save-dev

#根据错误提示和amazeui-touch下的.babelrc文件中的内容,下载如下内容

sudonpminstallbabel-preset-stage-0

sudonpminstallbabel-plugin-transform-object-assign--save

sudonpminstallbabel-plugin-add-module-exports--save-dev

sudonpminstalltransform-object-rest-spread

#这个是根据错误提示加入的

sudonpminstallreact-addons-css-transition-group--save-dev

sudonpminstallbabel-preset-stage-0--save-dev#注意要在.babelrc和webpack.config.js的配置位置中加入stage-0才行


为了更好的配合编译,推荐将webpack.config.js中的entry配置为如下示例。

在html中只需要加载如下两个Js:

<scriptsrc="http://localhost:9898/webpack-dev-server.js"></script><!--固定写法,不同的只是端口号-->
<scripttype="text/javascript"src='main.js'></script>  <!--按需配置,按需加载-->


并且注意,热编译的html必须在根目录。

entry:{
//代表入口(总)文件,可以写多个。
main:['./src/main.js'],
user:['./src/login.js']
},


html

<!DOCTYPEhtml>
<htmllang="en">
<head>
<title>Document</title>
<metacharset="utf-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="description"content="">
<metaname="keywords"content="">
<metaname="viewport"content="width=device-width,initial-scale=1">
<title>AmazeUITouch</title>
<metaname="renderer"content="webkit">
<!--NoBaiduSiteapp-->
<metahttp-equiv="Cache-Control"content="no-siteapp">
<linkrel="alternateicon"type="image/png"href="i/favicon.png">
<linkrel="apple-touch-icon-precomposed"href="i/app-icon72x72@2x.png">
<metaname="apple-mobile-web-app-title"content="AMUIReact">
<metaname="apple-mobile-web-app-capable"content="yes">
<metaname="apple-mobile-web-app-status-bar-style"content="black">
<linkrel="stylesheet"href="https://npmcdn.com/amazeui-touch@1.0.0-beta.3/dist/amazeui.touch.min.css">
</head>
<body>
<divid="demo"></div>

<scriptsrc="http://localhost:9898/webpack-dev-server.js"></script>
<scripttype="text/javascript"src='index-webpack.js'></script>

</body>
</html>


demo1:

varReact=require('react');
varReactDOM=require('react-dom');
import{Button}from'amazeui-touch';

ReactDOM.render(
<Button>HelloWorld!</Button>,
document.getElementById('demo')
)


demo2:剥离引用(口述)

新建一个card.js,随意利用React.createClass创建一个类,命名为CardExample,然后exports.CardExample=CardExample;

在index.js中.其中react和react-dom不需要担心重复引用的问题,系统自动会判断

varReact=require('react');
varReactDOM=require('react-dom');
varcard=require('./card.js');

ReactDOM.render(
<card.CardExample/>,
document.getElementById('demo')
)


学习蚂蚁:http://ant.design/docs/react/introduce

npminstallantd


demo1

importReactfrom'react';
importReactDOMfrom'react-dom';
import'antd/dist/antd.css';
import{Table,Icon}from'antd';

constcolumns=[{
title:'Name',
dataIndex:'name',
key:'name',
render:text=><ahref="#">{text}</a>,
},{
title:'Age',
dataIndex:'age',
key:'age',
},{
title:'Address',
dataIndex:'address',
key:'address',
},{
title:'Action',
key:'action',
render:(text,record)=>(
<span>
<ahref="#">Action一{record.name}</a>
<spanclassName="ant-divider"/>
<ahref="#">Delete</a>
<spanclassName="ant-divider"/>
<ahref="#"className="ant-dropdown-link">
Moreactions<Icontype="down"/>
</a>
</span>
),
}];

constdata=[{
key:'1',
name:'JohnBrown',
age:32,
address:'NewYorkNo.1LakePark',
},{
key:'2',
name:'JimGreen',
age:42,
address:'LondonNo.1LakePark',
},{
key:'3',
name:'JoeBlack',
age:32,
address:'SidneyNo.1LakePark',
}];

ReactDOM.render(<Tablecolumns={columns}dataSource={data}/>,document.getElementById('app'));


demo2

importReactfrom'react';
importReactDOMfrom'react-dom';
import'antd/dist/antd.css';
import{DatePicker,message}from'antd';

classAppextendsReact.Component{
constructor(props){
super(props);
this.state={
date:'',
};
}
handleChange(date){
message.info('您选择的日期是:'+date.toString());
this.setState({date});
}
render(){
return(
<divstyle={{width:400,margin:'100pxauto'}}>
<DatePickeronChange={value=>this.handleChange(value)}/>
<divstyle={{marginTop:20}}>当前日期:{this.state.date.toString()}</div>
</div>
);
}
}

ReactDOM.render(<App/>,document.getElementById('app'));


demo3

importReactfrom'react';
importReactDOMfrom'react-dom';

import'antd/dist/antd.css';
import{Layout,Menu,Icon}from'antd';
const{Header,Sider,Content}=Layout;

classSiderDemoextendsReact.Component{
state={
collapsed:false,
};
toggle=()=>{
this.setState({
collapsed:!this.state.collapsed,
});
}
render(){
return(
<Layout>
<Sider
trigger={null}
collapsible
collapsed={this.state.collapsed}
>
<divclassName="logo"/>
<Menutheme="dark"mode="inline"defaultSelectedKeys={['1']}>
<Menu.Itemkey="1">
<Icontype="user"/>
<spanclassName="nav-text">nav1</span>
</Menu.Item>
<Menu.Itemkey="2">
<Icontype="video-camera"/>
<spanclassName="nav-text">nav2</span>
</Menu.Item>
<Menu.Itemkey="3">
<Icontype="upload"/>
<spanclassName="nav-text">nav3</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Headerstyle={{background:'#fff',padding:0}}>
<Icon
className="trigger"
type={this.state.collapsed?'menu-unfold':'menu-fold'}
onClick={this.toggle}
/>
</Header>
<Contentstyle={{margin:'24px16px',padding:24,background:'#fff',minHeight:280}}>
Content
</Content>
</Layout>
</Layout>
);
}
}

ReactDOM.render(<SiderDemo/>,document.getElementById('app'));


官方路由

学习地址:http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu

官方github:https://github.com/ReactTraining/react-router

下载:
$npminstall-Sreact-router


demo

constReact=require('react');
constReactDOM=require('react-dom');
import{Router,Route,hashHistory}from'react-router';

letTeacherForm=React.createClass({
render()
{
return<formid='TeacherForm'>
<h2>教师登录</h2>
<divclassName='control-groupinput-append'>
<inputtype='text'name='nickname'id='nickname'data-required='true'/>

<labelfor='nickname'className='add-on'><spanclassName='icon-asterisk'></span>Nickname</label>
</div>

<divclassName='control-groupinput-append'>
<inputtype='text'name='site'id='site'/>

<labelfor='site'className='add-on'>Site</label>
</div>

<divclassName='control-groupinput-append'>
<inputtype='text'name='age'id='age'data-requireddata-pattern='^[0-9]+$'/>

<labelfor='age'className='add-on'><spanclassName='icon-asterisk'></span>Age</label>
</div>

<divclassName='btn-group'>
<buttontype='submit'className='btnbtn-primary'>Send</button>

<buttontype='reset'className='btn'>Reset</button>
</div>
</form>
}
})

letStudentForm=React.createClass({
render:function()
{
return<formid='StudentForm'>
<h2>学生登录</h2>
<divclassName='control-groupinput-append'>
<inputtype='text'name='nickname'id='nickname'data-required='true'/>

<labelfor='nickname'className='add-on'><spanclassName='icon-asterisk'></span>Nickname</label>
</div>

<divclassName='control-groupinput-append'>
<inputtype='text'name='site'id='site'/>

<labelfor='site'className='add-on'>Site</label>
</div>

<divclassName='control-groupinput-append'>
<inputtype='text'name='age'id='age'data-requireddata-pattern='^[0-9]+$'/>

<labelfor='age'className='add-on'><spanclassName='icon-asterisk'></span>Age</label>
</div>

<divclassName='btn-group'>
<buttontype='submit'className='btnbtn-primary'>Send</button>

<buttontype='reset'className='btn'>Reset</button>
</div>
</form>
}
})

ReactDOM.render((
<Routerhistory={hashHistory}>
<Routepath="/"component={StudentForm}/>
<Routepath="t"component={TeacherForm}/>
<Routepath="s"component={StudentForm}/>
</Router>
),document.getElementById('form'));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: