React三大体系
1.React.js 用于web开发和组件的编写
2.ReactNative 用于移动端开发
3.ReactVR 用于虚拟现实技术的开发
React脚手架安装
npm install -g create-react-app
创建React项目
D: //进入D盘
mkdir ReactDemo //创建ReactDemo文件夹
cd ReactDemo //进入ReactDemo文件夹
create-react-app demo01 //用脚手架创建React项目
cd demo01 //等创建完成后,进入项目目录
npm start //预览项目,如果能正常打开,说明项目创建成功
项目根目录中的文件
先从进入项目根目录说起,也就是第一眼看到的文件(版本不同,可能稍有不同)
README.md :这个文件主要作用就是对项目的说明,已经默认写好了一些东西,你可以简单看看。如果是工作中,你可以把文件中的内容删除,自己来写这个文件,编写这个文件可以使用Markdown的语法来编写。
package.json: 这个文件是webpack配置和项目包管理文件,项目中依赖的第三方包(包的版本)和一些常用命令配置都在这个里边进行配置,当然脚手架已经为我们配置了一些了,目前位置,我们不需要改动。如果你对webpack了解,对这个一定也很熟悉。
package-lock.json:这个文件用一句话来解释,就是锁定安装时的版本号,并且需要上传到git,以保证其他人再npm install 时大家的依赖能保证一致。
gitignore : 这个是git的选择性上传的配置文件,比如一会要介绍的node_modules文件夹,就需要配置不上传。
node_modules :这个文件夹就是我们项目的依赖包,到目前位置,脚手架已经都给我们下载好了,你不需要单独安装什么。
public :公共文件,里边有公用模板和图标等一些东西。
src : 主要代码编写文件,这个文件夹里的文件对我们来说最重要,都需要我们掌握。
public文件夹介绍
这个文件都是一些项目使用的公共文件,也就是说都是共用的,我们就具体看一下有那些文件吧。
favicon.ico : 这个是网站或者说项目的图标,一般在浏览器标签页的左上角显示。
index.html : 首页的模板文件,我们可以试着改动一下,就能看到结果。
mainifest.json:移动端配置文件,这个会在以后的课程中详细讲解。
src文件夹介绍
这个目录里边放的是我们开放的源代码,我们平时操作做最多的目录。
index.js : 这个就是项目的入口文件,视频中我们会简单的看一下这个文件。
index.css :这个是index.js里的CSS文件。
app.js : 这个文件相当于一个方法模块,也是一个简单的模块化编程。
serviceWorker.js: 这个是用于写移动端开发的,PWA必须用到这个文件,有了这个文件,就相当于有了离线浏览的功能。
入口文件的编写
在src目录下面 新建文件夹index.js
写入下面4行代码
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(<App />,document.getElementById('root'))
上面的代码,我们先引入了React两个必要的文件,然后引入了一个APP组件,目前这个组件还是没有的,需要一会建立。然后用React的语法把APP模块渲染到了root ID上面.这个rootID是在public\index.html文件中的。
app组件的编写
import React,{Component} form 'react'
class App extends Component{
render(){
return (
<div>
Hello JSPang
</div>
)
}
}
export default App;
import React, {Component} from 'react'
可以写成
import React from 'react'
const Component = React.Component
JSX简介
JSX就是Javascript和XML结合的一种格式。React发明了JSX,可以方便的利用HTML语法来创建虚拟DOM,当遇到<,JSX就当作HTML解析,遇到{就当JavaScript解析.
比如我们写一段JSX语法
<ul className="my-list">
<li>JSPang.com</li>
<li>I love React</li>
</ul>
比如我们以前写一段代码JS代码:
var child1 = React.createElement('li', null, 'JSPang.com');
var child2 = React.createElement('li', null, 'I love React');
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
组件和普通JSX语法区别
这个说起来也只有简单的一句话,就是你自定义的组件必须首写字母要进行大写,而JSX是小写字母开头的。
这个也算是一个比较重要的知识点吧。
新建组件
我们新建组件的时候,只需要把入口文件index.js的<App/>组件换成我们新建的组件就可以了。
组件外层包裹原则
这是一个很重要的原则,
import React,{Component} from 'react'
class Xiaojiejie extends Component{
render(){
return (
<div>
<div><input /> <button> 增加服务 </button></div>
<ul>
<li>头部按摩</li>
<li>精油推背</li>
</ul>
</div>
)
}
}
export default Xiaojiejie
比如上面的代码,我们去掉最外层的div就会报错,因为React要求必须在一个组件的最外层进行包裹。
Fragment标签讲解
加上最外层的DIV,组件就是完全正确的,但是你的布局不需要最外层的标签的时候,我们就使用<Fragment>标签
要想使用<Fragment>,需要先进行引入
import React,{Component,Fragment } from 'react'
然后把最外层的div标签换成<Fragment>标签 代码如下
import React,{Component,Fragment } from 'react'
class Xiaojiejie extends Component{
render(){
return (
<Fragment>
<div><input /> <button> 增加服务 </button></div>
<ul>
<li>头部按摩</li>
<li>精油推背</li>
</ul>
</Fragment>
)
}
}
export default Xiaojiejie
这时候你再去浏览器的Elements中查看,就回发现已经没有外层的包裹了
响应式设计和数据的绑定
React不建议你直接操作DOM元素,而是要通过数据进行驱动,改变界面中的效果。React会根据数据的变化,自动的帮助你完成界面的改变。所以在写React代码时,你无需关注DOM相关的操作,只需要关注数据的操作就可以了(这也是React如此受欢迎的主要原因,大大加快了我们的开发速度)。
现在的需求是增加小姐姐的服务项,就需要先定义数据。数据定义在Xiaojiejie组件中的构造函数里constructor。
//js的构造函数,由于其他任何函数执行
constructor(props){
super(props) //调用父类的构造函数,固定写法
//这里的this.state就相当于vue里面的data
this.state={
inputValue:'' , // input中的值
list:[] //服务列表
}
}
在 React中的数据绑定和Vue中几乎一样,也是采用字面量(我自己起的名字)的形式,就是使用{}来标注,其实这也算是js代码的一种声明。比如现在我们要把inputValue值绑定到input框中,只要写入下面的代码就可以了。其实说白了就是在JSX中使用js代码
<input value={this.state.inputValue} />
绑定事件
这时候你到界面的文本框中去输入值,是没有任何变化的,这是因为我们强制绑定了inputValue的值。如果要想改变,需要绑定响应事件,改变inputValue的值。比如绑定一个改变事件,这个事件执行inputChange()(当然这个方法还没有)方法。
<input value={this.state.inputValue} onChange={this.inputChange} />
事件的绑定需要重新定义this的指向
react改变值需要使用this.setState方法
更改上面的代码如下
<input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
这步做完,我们还需要加入setState方法,改变值。代码如下:
inputChange(e){
// console.log(e.target.value);
// this.state.inputValue=e.target.value;
this.setState({
inputValue:e.target.value
})
}
列表数据化
现在的列表还是写死的两个<li>标签,那要变成动态显示的,就需要把这个列表先进行数据化,然后再用javascript代码,循环在页面上。
我们先给上节课的list数组增加两个数组元素,代码如下:
constructor(props){
super(props) //调用父类的构造函数,固定写法
this.state={
inputValue:'jspang' , // input中的值
//----------主要 代码--------start
list:['基础按摩','精油推背']
//----------主要 代码--------end
}
}
有了数据后,可以在JSX部分进行循环输出,代码如下:
render(){
return (
<Fragment>
<div>
<input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button> 增加服务 </button>
</div>
<ul>
{
this.state.list.map((item,index)=>{
return <li>{item}</li>
})
}
</ul>
</Fragment>
)
}
//循环数据的写法
{
this.state.list.map((item,index)=>{
return <li>{item}</li>
})
}
扩展运算符 ... 三个点
list:[...this.state.list,this.state.inputValue]
这里需要说的市...这个是ES6的新语法,叫做扩展运算符。意思就是把list数组进行了分解,形成了新的数组,然后再进行组合。这种写法更简单和直观,所以推荐这种写法。
循环的时候我们需要绑定key值
在需要循环的标签上面加上key={index+item}
加上item的意思是防止index的重复
数组下标的传递
如果要删除一个东西,就要得到数组里的一个编号,这里指下标。传递下标就要有事件产生,先来绑定一个双击事件.代码如下:
onclick={this.deleteItem.bind(this,indx)}
deleteItem(index){
console.log(index)
}
正式删除数据
获得了数据下标后,删除数据就变的容易起来.先声明一个局部变量,然后利用传递过来的下标,删除数组中的值.删除后用setState更新数据就可以了.
//删除单项服务
deleteItem(index){
let list = this.state.list
list.splice(index,1)
this.setState({
list:list
})
}
其实这里边是有一个坑的,有的小伙伴肯定会认为下面的代码也是正确的.
deleteItem(index){
this.state.list.splice(index,1)
this.setState({
list:this.state.list
})
}
记住React是禁止直接操作state的,虽然上面的方法也管用,但是在后期的性能优化上会有很多麻烦,所以一定不要这样操作.这也算是我React初期踩的比较深的一个坑,希望小伙伴们可以跳坑
JSX中的class陷阱
在src目录下面写上style.css
然后在页面中引入 import './style.css'
在页面中加入类名中要写className而不是class
引入子组件
引入子组件的时候只需要
import XiaojijieItem from './XiaojiejiItem'
然后在页面中写入
<XiaojiejieItem/>
父组件向子组件传值
这里只介绍最实用的,最快速的上手方法。就是使用组件属性的形式父组件给子组件传值。比如:我们在<XiaojiejieItem>组件中加入content属性,然后给属性传递{item},这样就完成了父组件向子组件传值。
<XiaojiejieItem content={item} />
现在值已经顺利的传递了过去,这时候可以通过this.props.xxx的形式进行接受,比如传递过来的值,可以用如下代码进行接收。
import React, { Component } from 'react'; //imrc
class XiaojiejieItem extends Component { //cc
render() {
return (
<div>{this.props.content}</div>
);
}
}
export default XiaojiejieItem;
父组件向子组件传递内容,靠属性的形式传递
子组件向父组件传递数据
React有明确规定,子组件时不能操作父组件里的数据的,所以需要借助一个父组件的方法,来修改父组件的内容。
这里我们说一下this的指向 绑定
我们可以在constructor里面提前绑定this
constructor(props){
super(props)
this.handleClick=this.handleClick.bind(this)
}
子组件调用父组件的方法
将富组件的方法用属性的方法传递
然后在子组件里面操作
<ul>
{
this.state.list.map((item,index)=>{
return (
<XiaojiejieItem
key={index+item}
content={item}
index={index}
//关键代码-------------------start
deleteItem={this.deleteItem.bind(this)}
//关键代码-------------------end
/>
)
})
}
</ul>
传递后直接在子组件里面使用
handleClick(){
this.props.deleteItem(this.props.index)
}
本文章纯属学习笔记
引用于技术胖网站文章,如有出入请看原文
www.jspang.com