React:
专门构建于用户界面的js库(顶多它是mvc中的v层框架)
核心思想,通过数据操作视图。
官方(推荐使用)脚手架:create-react-app
中文网:https://react.docschina.org/
难点:英文、webpack
背景:react 是 Facebook 出品,背景大、生态比较丰富(pc、安卓、ios都适用)
相对vue来说只是写法不一样,思想都类似的,代码相对vue来说要多一点点。基本上都是原生,自己写的功能多一些。
声明式:
比如:
let a = 100;//变量声明
function fn(){} //函数声明
react通过声明一个类(函数)来创建UI的
1. class Person{} (类的申明方式有:状态、this、生命周期。推荐用这种方式申明)
2. function(){}
安装 create-react-app :
npx create-react-app my-app (my-app 自己起的文件名)
cd my-app
npm start / yarn start
create-react-app (官方推荐使用的脚手架)
React 全家桶
react 、 react-router-dom 、 redux(mobx) 、 第三方UI库antd 、 react-native(移动应用) 、 开发原生APP
react:(学习的内容)
jsx语法
state
props
数据的通信
使用:
View Code
import React from 'react'; //主要的库 import ReactDOM from 'react-dom'; //把jsx转成能够让浏览器识别的工具 //热更新 if(module.hot){ module.hot.accept(); } /* 挂在组件。(根节点的挂载) *** ReactDOM.render()是个方法。三个参数: 第一个参数: 模板、组件 第二个参数: 挂载的根节点 第三个参数: 挂载完成之后触发的回调函数 */ ReactDOM.render( <div>你好,世界!!!! <input // defaultValue = {'123'} value = {'456'} onChange = {()=>{ }} /> </div>, document.getElementById('root'), ()=>{ console.log('挂载成功') } );
1.引包 react 、react-dom
2.ReactDOM.render(
<div> xxx </div>,
document.getElementById('root'),
()=>{
挂载成功之后的代码
}
);
3.热更新:(可用可不用)
if(module.hot){
module.hot.accept();
}
*** ReactDOM.render()是个方法。三个参数:
第一个参数:
模板、组件 (所有的模板顶层只能够有一个标签 , jsx语法)
第二个参数:
挂载的根节点
第三个参数:
挂载完成之后触发的回调函数
jsx -> javascript + xml 一种js和自定义写法的混合模式
jsx 语法主要是为了更好的读、写模板或者组件。
jsx 语法浏览器是不识别的,通过babel的方式吧jsx转成浏览器识别的代码(babel : www.babeljs.cn)。
在react中,写<div></div>,其实就等同于写了一个 React.createElement('div',children:[],'click','active')
jsx规则:
1.遇到样式中的 class ,直接变成className
2.标签必须闭合 (/),特别是单标签要注意
3.{}
*1)里面放js代码,可以运行(运算) 比如:{console.log(1+'1')}
*2)默然帮你展开数组
[1,2,3] - > 1 2 3
[<li />,<li />]如果数组中的值为组件(列表),那么一定要给列表中的每一项加key(key:一个唯一的值),为了优化
3)注释 {// 或者 /*2/}
*4)可以申明函数,但不能直接调用
5)value={a} 赋值某个元素的属性
6)设置style={{'200px',height:'200px',...}} 花括号包着一个对象
4.表单元素设置默认值(value='xxx')的时候会报错,因为它认为input为一个受限的组件。value值是动态就会操作数据(value就一定会变化),会变化,就一定要有事件(onChange),所以才会报错。
比如:<input value="1"/> 报错
两种方式解决:
1.给表单元素加上事件(onChange)(受控组件,官方推荐使用)
<input
value = {a}
onChange = {()=>{
}}
/>
2.定义默认值的时候就使用 defaultValue (非受控组件)
<input
defaultValue = '123'
/>
5.<img src={require('./images/地址.png')} alt=""/> 用img引入图片的时候,要包{require('地址')}的方式
* 循环数据渲染的时候,引入图片地址会出现无法加载的问题:
解决:
1. src={require(""+地址)},括号中放 地址+空字符串。并且图片要在同级目录下,也就是不能出现 ../
2. 把相同的绝对路径写在 字符串里 --> src={require(" ../相同的路径/xxx "+地址)} 。此时可以出现 ../
6.用 ref 来快速找到DOM元素
1)给元素绑定 ref <div ref = "a" > </div>
2)用 this.refs.a 来获取相对应的元素。
定义组件的方式:(参考课件:2019-01-15_React -> app -> arc -> index3.js )
View Code
import React from 'react'; //主要的库 import ReactDOM from 'react-dom'; //把jsx转成能够让浏览器识别的工具 //热更新 if (module.hot) { module.hot.accept(); } //组件:申明一个类。***一定要注意:类的首字母要大写(App)。 //组件在挂在的时候,会先执行construction,只会执行一次,然后经过几个钩子函数之后,走到render, //只要数据发生变化,就再次执行render,而construction 是不会再改变 class App extends React.Component { constructor(props){ super(props); //super的作用: 1.传参 2.拿this console.log(props) } render(){ //普通的render中的return上面写逻辑,return下面是UI let {aaa,bbb,ccc} = this.props return( <div> <h1>组件</h1> <div>{aaa}{bbb}{ccc}</div> </div> ) } } //组件的申明:可以是个类,还可以是一个函数 function Ppa(){ return( <div> <h1>组件2</h1> </div> ) } /* 属性中如果有两个重复的,后面会把前面的覆盖 ...[a,b,c] ...{a:'1',b:2,} */ ReactDOM.render( <div> {/* <App aaa='你好' bbb='世界' ccc={[1,2,3]} /> */} <App {...{ aaa:'hello', bbb:'word', ccc:[4,5,6] }}/> <Ppa/> </div>, document.getElementById('root'), );
class App extend React.Component{}
或者:
在import React,{Component} from 'react'; 引 Component
class App extend Component{ //推荐使用class,类名首字母要大写
render(){
<div>
<h1>组件1</h1>
</div>
}
}
还可以用:
function Ppa(){
return(
<div>
<h1>组件2</h1>
</div>
)
}
写方法的时候,如果不对函数做处理,事件函数中的this指向undefined
解决方案:
1.使用create-app (推荐使用这种)
click = () => {} //把匿名箭头函数赋值给click
2.bind,this
click(){}
constructor(){
this.click = this.click.bind(this)
}
3.
click(){}
<button
onClick={this.click.bind(this)}
>
4.
click(){}
<button
onClick={(e,i)=>this.click(e)}
>
state 状态
操作状态中的数据,就能操作视图
constructor(){
this.state={xx:oo}
}
操作数据不能直接使用this.state.xx=oo
***只能通过this.setState()去修改你的状态
this.setState(对象(就是你state的数据),()=>{当操作完数据之后的回调函数}) (推荐使用这种)
this.setState(函数(prev)=>{return {num:prev.num+1}},()=>{当操作完数据之后的回调函数})
props数据之间的通信:(单向数据流)
父级传子级:
传递数据在组件身上使用属性的绑定
推荐使用:
<App {...{
xxx:'hello',
bbb:'word',
ccc:[4,5,6]
}}/>
子组件接收
this.props.xxx
//以上知识点的综合应用(小todu)之 app.js(父级)
import React, { Component } from 'react';
import ReactDom from 'react-dom';
import List from './list';
class App extends Component {
constructor(props) {
super(props);
/*
state 等同于 Vue中的data:
data() {
return {
}
}
*/
this.state = {
val: '',
arr: ['第一个li']
};
}
/*
改变数据状态使用 this.setState()
*/
change = (ev) => {
this.setState({
val: ev.target.value
})
}
keyup = (ev) => {
if (ev.keyCode === 13) {
let { arr, val } = this.state;
arr.push(val)
this.setState({ arr ,val:''});
}
}
render() {
let { val, arr } = this.state;
let list = arr.map((e, i) => { //循环产生一堆<li> </li>
return <List {...{ //map方法会返回一个新数组[<li></li>,<li></li>,...],map方法一定要return,jsx的{}会自动展开数组
key: i, //尽量保证key的值是唯一的
val: e //val和key是固定写法,val是<li>的innerText
}} />
});
return (
<div className='App'>
<input
value={val}
onChange={this.change}
onKeyUp={this.keyup}
/>
<ul>
{list}
</ul>
</div>
);
}
}
export default App;
//子组件 (list.js)
import React, {Component} from 'react' class List extends Component{ render(){ return( <li>{this.props.val}</li> //接收父级的数据 ); } } export default List;
获取元素
1. 给元素标记 ref
<input type="text" ref="username" onChange={this.showThis}/>
2. 获取
console.log(this.refs.username.value)