react 详细解析学习笔记
React的介绍:
React来自于Facebook公司的开源项目
React 可以开发单页面应用 spa(单页面应用)
react 组件化模块化 开发模式
React通过对DOM的模拟(虚拟dom),最大限度地减少与DOM的交互 (数据绑定)
react灵活 React可以与已知的库或框架很好地配合。
react 基于jsx的语法,JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面, html js混写模式
搭建React开发环境之前的准备工作。
1、必须安装nodejs 注意:安装nodejs稳定版本
2、安装cnpm用cnpm替代npm
地址:http://npm.taobao.org/
安装cnpm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
3、用yarn替代npm
yarn的安装:
第一种方法:参考官方文档https://yarn.bootcss.com/
第二种方法:cnpm install -g yarn 或者 npm install -g yarn
搭建React开发环境
第一种方法(老-现在推荐):
https://reactjs.org/docs/create-a-new-react-app.html
1、必须要安装nodejs 注意:安装nodejs稳定版本 nodejs版本:v8.11.2 npm版本:v5.6.0
2.安装脚手架工具 (单文件组件项目生成工具) 只需要安装一次
npm install -g create-react-app / cnpm install -g create-react-app
3.创建项目 (可能创建多次)
找到项目要创建的目录:
create-react-app reactdemo
4.cd 到项目里面
cd reactdemo
npm start yarn start运行项目
npm run build yarn build 生成项目
第二种方法(新-未来推荐):
https://reactjs.org/docs/create-a-new-react-app.html
1、必须要安装nodejs 注意:安装nodejs稳定版本 nodejs版本:v8.11.2 npm版本:v5.6.0
2.安装脚手架工具并创建项目
找到项目要创建的目录执行:
npx create-react-app reactdemo
4.cd 到项目里面
cd reactdemo
npm start 运行项目(调试)
npm run build 生成项目(发布)
npx介绍:
npm v5.2.0引入的一条命令(npx),引入这个命令的目的是为了提升开发者使用包内提供的命令行工具的体验。
详情:
http://www.phonegap100.com/thread-4910-1-1.html
npx create-react-app reactdemo这条命令会临时安装 create-react-app 包,命令完成后create-react-app 会删掉,不会出现在 global 中。下次再执行,还是会重新临时安装。
npx 会帮你执行依赖包里的二进制文件。
再比如 npx http-server 可以一句话帮你开启一个静态服务器
manifest.json 文件简介:
https://lavas.baidu.com/mip/doc/engage-retain-users/add-to-home-screen/introduction
允许将站点添加至主屏幕,是 PWA 提供的一项重要功能,当前 manifest.json 的标准仍属于草案阶段,Chrome 和 Firefox 已经实现了这个功能,微软正努力在 Edge 浏览器上实现,Apple 目前仍在考虑中
super关键字:
参考:http://www.phonegap100.com/thread-4911-1-1.html
Es6中的super可以用在类的继承中,super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。
1 class Person { 2 constructor (name) { 3 this.name = name; 4 } 5 } 6 class Student extends Person { 7 constructor (name, age) { 8 super(); // 用在构造函数中,必须在使用this之前调用 9 this.age = age; 10 } 11 }
为什么官方的列子里面写个super(props):
只有一个理由需要传递props作为super()的参数,那就是你需要在构造函数内使用this.props
那官方提供学习的例子中都是写成super(props),所以说写成super(props)是完全没问题的,也建议就直接这样写。
ReactJSX语法
JSX就是Javascript和XML结合的一种格式。React发明了JSX,可以方便的利用HTML语法来创建虚拟DOM,当遇到<
,JSX就当作HTML解析,遇到{
就当JavaScript解析.
1、所有的模板要被一个根节点包含起来,在render函数中return返回的只能包含一个顶层标签,否则也会报错
2、模板元素不要加引号
3、JSX基本语法规则,遇到HTML标签(以<开头),就用HTML规则解析;遇到代码块(以{开头),就用JS规则解析
4、绑定属性注意:
class 要变成 className
for 要变成 htmlFor
style属性和以前的写法有些不一样
<div style={{'color':'blue'}}>{this.state.title}</div>
<div style={{'color':this.state.color}}>{this.state.title}</div>
5、循环数据要加key
6、组件的构造函数中一定要注意 super
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象
1 constructor(props){ 2 super(props); /*用于父子组件传值 固定写法*/ 3 this.state={ 4 userinfo:'张三' 5 } 6 }
7、组件名称首字母大写、组件类名称首字母大写
8、react解析html
1 <div dangerouslySetInnerHTML={{__html: this.state.list.htmlStr}}> </div>
9、条件判断的四种写法
用三元表达式, 使用dom元素变量,直接调用函数,使用逻辑运算符,利用即时执行函数
1 class HelloWorld extends React.Component{ 2 render(){ 3 return <p>Hello { 4 (function(obj){ 5 if(obj.props.name){ 6 return obj.props.name; 7 }else{ 8 return "World"; 9 } 10 }(this)) 11 }</p> 12 } 13 }
Fragment标签
加上最外层的DIV,组件就是完全正常的,但是你的布局就偏不需要这个最外层的标签怎么办?比如我们在作Flex
布局的时候,外层还真的不能有包裹元素。这种矛盾其实React16已经有所考虑了,为我们准备了<Fragment>
标签。
在以类继承的方式定义的组件中,为了能方便地调用当前组件的其他成员方法或属性(如:this.state),通常需要将事件处理函数运行时的 this 指向当前组件实例。
引入方式:
import React,{Component,Fragment } from 'react'
然后把最外层的<div>
标签,换成<Fragment>
标签
setState
React是禁止直接操作state的,虽然上面的方法也管用,但是在后期的性能优化上会有很多麻烦
绑定事件处理函数this的几种方法:
第一种方法:
1 run(){ 2 alert(this.state.name) 3 } 4 <button onClick={this.run.bind(this)}>按钮</button>
第二种方法: 构造函数中改变
1 this.run = this.run.bind(this); 2 run(){ 3 alert(this.state.name) 4 } 5 <button onClick={this.run>按钮</button>
第三种方法:
1 run=()=> { 2 alert(this.state.name) 3 } 4 <button onClick={this.run>按钮</button>
React中的组件: 解决html 标签构建应用的不足。
获取表单的值
(获取点击的某个键的key值 e.keyCode)
1、监听表单的改变事件 onChange
2、在改变的事件里面获取表单输入的值 ref获取
3、把表单输入的值赋值给username this.setState({})
4、点击按钮的时候获取 state里面的username this.state.username
组件传值:
使用组件的好处:把公共的功能单独抽离成一个文件作为一个组件,哪里里使用哪里引入。
父子组件:组件的相互调用中,我们把调用者称为父组件,被调用者称为子组件
父子组件传值:
一,父组件给子组件传值
1.在调用子组件的时候定义一个属性 <Header msg='首页'></Header>
2.子组件里面 this.props.msg
说明:父组件不仅可以给子组件传值,还可以给子组件传方法,以及把整个父组件传给子组件。
记住一点:父组件向子组件传递内容,靠属性的形式传递。
父组件主动获取子组件的数据
1、调用子组件的时候指定ref的值 <Header ref='header'></Header>
2、通过this.refs.header 获取整个子组件实例
二,子组件给父组件传值:
defaultProps:父子组件传值中,如果父组件调用子组件的时候不给子组件传值,可以在子组件中使用defaultProps定义的默认值
propTypes:验证父组件传值的类型合法性,定义父组件给子组件传值的类型
1、引入import PropTypes from 'prop-types';
2、类.propTypes = {
name: PropTypes.string
};
都是定义在子组件里面
约束性和非约束性组件:
非约束性组:<input type="text" defaultValue="a" /> 这个 defaultValue 其实就是原生DOM中的 value 属性。
这样写出的来的组件,其value值就是用户输入的内容,React完全不管理输入的过程。
约束性组件:<input value={this.state.username} type="text" onChange={this.handleUsername} />
这里,value属性不再是一个写死的值,他是 this.state.username, this.state.username 是由 this.handleChange 负责管理的。
这个时候实际上 input 的 value 根本不是用户输入的内容。而是onChange 事件触发之后,由于 this.setState 导致了一次重新渲染。不过React会优化这个渲染过程。看上去有点类似双休数据绑定
react获取服务器APi接口的数据:
react中没有提供专门的请求数据的模块。但是我们可以使用任何第三方请求数据模块实现请求数据
1、axios https://github.com/axios/axios axios的作者觉得jsonp不太友好,推荐用CORS方式更为干净(后端运行跨域)
1、安装axios模块npm install axios --save / npm install axios --save
2、在哪里使用就在哪里引入import axios from 'axios'
3、看文档使用
1 Var api=''; 2 axios.get(api) 3 .then(function (response) { 4 console.log(response); 5 }) 6 .catch(function (error) { 7 console.log(error); 8 });
2、fetch-jsonp https://github.com/camsong/fetch-jsonp
1、安装 npm install fetch-jsonp --save
2、import fetchJsonp from 'fetch-jsonp'
3、看文档使用
fetchJsonp('/users.jsonp') .then(function(response) { return response.json() }).then(function(json) { console.log('parsed json', json) }).catch(function(ex) { console.log('parsing failed', ex) })
3、其他请求数据的方法也可以...自己封装模块用原生js实现数据请求也可以...
React生命周期函数:
组件加载之前,组件加载完成,以及组件更新数据,组件销毁。
触发的一系列的方法 ,这就是组件的生命周期函数
组件加载的时候触发的函数:
constructor 、componentWillMount、 render 、componentDidMount
组件数据更新的时候触发的生命周期函数:
shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate
你在父组件里面改变props传值的时候触发的:
componentWillReceiveProps
组件销毁的时候触发的:
componentWillUnmount
必须记住的生命周期函数:
*加载的时候:componentWillMount、 render 、componentDidMount(dom操作)
更新的时候:componentWillUpdate、render、componentDidUpdate
*销毁的时候: componentWillUnmount
react路由的配置:
1、找到官方文档 https://reacttraining.com/react-router/web/example/basic
2、安装 cnpm install react-router-dom --save
3、找到项目的根组件引入react-router-dom
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
4、复制官网文档根组件里面的内容进行修改 (加载的组件要提前引入)
<Router> <Link to="/">首页</Link> <Link to="/news">新闻</Link> <Link to="/product">商品</Link> <Route exact path="/" component={Home} /> <Route path="/news" component={News} /> <Route path="/product" component={Product} /> </Router>
exact表示严格匹配
实现js跳转路由:https://reacttraining.com/react-router/web/example/auth-workflow
1、要引入Redirect
2、定义一个flag
this.state = {
loginFlag:false
};
3、render里面判断flag 来决定是否跳转
if(this.state.loginFlag){
return <Redirect to={{ pathname: "/" }} />;
}
4、要执行js跳转
通过js改变loginFlag的状态
改变以后从新render 就可以通过Redirect自己来跳转
url模块来解析url地址 在react里面使用url模块需要安装url模块 cnpm install url --save
import url from 'url';
//获取get传值
console.log(url.parse(this.props.location.search,true));
var query=url.parse(this.props.location.search,true).query;
console.log(query)
未完待续。。。