1.脚手架
npm i create-react-app -g //安装脚手架
create-react-app demo // 创建项目
cd demo //进入项目
npm start //启动项目
目录介绍:
my-app
- node_modules --npm包
- public --服务器目录
- favicon.ico --页面图标
- index.html --页面主入口
- manifest.json --页面配置文件
- src --项目源码
- App.css --根组件样式
- App.js --根组件模板
- App.test.js --根组件测试(删)
- index.css --全局css样式(删)
- index.js --脚本主入口(删)
- logo.svg --图片文件(删)
- serviceWorker.js --离线访问服务(删)
- .gitignore --git忽略文件配置
- package.json --npm配置
- package-lock.json --锁定安装时的包的版本号
- README.md --项目说明文档
- yarn.lock --yarn配置
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
src/App.js
function App() {
return (
<div className="App">
123
</div>
);
}
export default App;
2.JSX语法
import React from "react";
// 1.非表单元素:div span ... {变量}
// 2.媒体元素:img {变量}
// 3.条件渲染
// 4.列表渲染
var name = "妲己";
var name2 = "王昭君";
let price = 20;
let imgUrl =
"https://img2.baidu.com/it/u=1376319214,2872501189&fm=26&fmt=auto&gp=0.jpg";
let status = 1;
let isshow = false;
let arr = [
{ id: 1, title: "哈哈", con: "和越南总统对话", color: "red" },
{
id: 2,
title: "嘿嘿",
con: "银行卡被盗刷,银行应该负责赔偿",
color: "blue",
},
{ id: 3, title: "哈哈", con: "和越南总统对话", color: "pink" },
{
id: 4,
title: "嘿嘿",
con: "银行卡被盗刷,银行应该负责赔偿",
color: "orange",
},
{ id: 5, title: "哈哈", con: "和越南总统对话", color: "lime" },
{
id: 6,
title: "嘿嘿",
con: "银行卡被盗刷,银行应该负责赔偿",
color: "green",
},
];
/*
let elArr=[
<li>哈哈</li>,
<li>嘿嘿</li>
]*/
let elArr = arr.map((item) => {
return (
<li key={item.id}>
<h3>{item.title}</h3>
<p>{item.con}</p>
</li>
);
});
function DataBind() {
return (
<div>
{/* 1.{}可以绑定变量 */}
<div>name:{name}</div>
{/* 2.{} 可以绑定表达式 */}
<div>{status === 1 ? name : name2}</div>
{/* 3.{} 绑定方法 */}
<div>price:{price.toFixed(2)}</div>
{/* 4。属性绑定 {变量} */}
<img src={imgUrl} alt="" />
<div aa={name}>哈哈哈</div>
{/* 5.条件渲染 {三元表达式} ,如果什么都不出,写null */}
{status === 1 ? <button>是</button> : <button>否</button>}
{isshow ? <div>弹框</div> : null}
{/* 6.列表渲染 map */}
<ul>{elArr}</ul>
{/* 推荐在页面map */}
<ol>
{arr.map((item) => {
return (
<li key={item.id}>
<h3>{item.title}</h3>
<p>{item.con}</p>
</li>
);
})}
</ol>
{arr.length === 0 ? <div>暂无数据</div> : null}
{/* 7.注释 */}
{/* 8.如果标签比较多,就用()包一下 */}
{/* 9. 类名使用className,而不是class */}
<div className="red">测试样式</div>
{/* 10.动态类名 className={三元} */}
<ol>
{arr.map((item, index) => {
return (
<li className={index % 2 === 0 ? "red" : "blue"} key={item.id}>
{item.title}
</li>
);
})}
</ol>
{/* 11动态行间样式 style={json} */}
<ol>
{arr.map((item, index) => {
return (
<li style={{ color: item.color }} key={item.id}>
{item.title}
</li>
);
})}
</ol>
<div style={{ background: "red" }}>真好</div>
{/* 12. jsx中遇到了< 由html解析,遇到{ 由js解析 */}
</div>
);
}
export default DataBind;
3.组件
3.1组价注册
函数定义:
import React from "react"
function FunctionCreate(props){
console.log(props);
return (
<div className="box">
<h3>函数创建</h3>
<div>msg:{props.msg}</div>
</div>
)
}
export default FunctionCreate;
类定义:
import React, { Component } from "react";
class ClassCreate extends Component {
// 构造函数:要么不写,写了就得加super()
constructor() {
super();
this.name = "妲己";
this.state={
num:1
}
}
//渲染的函数
render() {
console.log(this);
return (
<div className="box">
<h3>类定义</h3>
<div>msg:{this.props.msg}</div>
</div>
);
}
}
export default ClassCreate;
3.2对比两种注册方式
1.类定义组件有state,函数定义没有;
2.类定义组件有生命周期函数,函数定义没有;
3.对于父组件传递的数据,类定义通过this.props接收,函数定义通过props接收;
4.类定义组件每一次调用都会创建一个实例对象,函数只是纯计算,返回html,效率角度考虑,函数更好一些。
3.3组件注册注意点:
// 1.组件名称首字母要大写
// 2.可以使用存在的标签的大写命名
// 3.中间有大写,不需要使用烤串写法
// 4.模板只能有1个根节点
4.事件处理
import React, { Component } from "react"
// 1.如何绑定事件
// 2.事件如何传参?
// 3.event对象如何获取?
// 4.阻止默认、阻止传播
// 5.捕获如何实现?
class Event extends Component {
fn() {
console.log("123");
console.log(this);
}
add(a, b) {
console.log(a + b);
}
//获取event
getEvent(e) {
console.log(e);
}
// 获取event
getEvent2(a, b) {
console.log(a, b);
}
yj(e) {
e.preventDefault()
console.log("右键了");
}
outerClick() {
console.log("outer click");
}
innerClick(e) {
e.stopPropagation()
console.log("inner click");
}
render() {
return (
<div className="box">
<h3>事件处理</h3>
{/* 1.如何绑定事件 */}
<div className="box">
<h4>1.如何绑定事件</h4>
{/* 箭头函数绑定不需要this */}
{/* bind 绑定第一个参数是调用该函数的对象,一般使用this */}
<button onClick={(e) => this.fn()}>箭头函数:点击执行fn</button>
<button onClick={this.fn.bind(this)}>bind:点击执行fn</button>
</div>
{/* 2.事件如何传参? */}
<div className="box">
<h4>2.事件如何传参?</h4>
{/* 箭头函数正常传 */}
{/* bind 的第2个实参传递给函数的第1个形参*/}
<button onClick={() => this.add(10, 20)}>箭头函数:10+20</button>
<button onClick={this.add.bind(this, 3, 10)}>bind:3+10</button>
</div>
{/* 3.event对象如何获取? */}
<div className="box">
<h4> 3.event对象如何获取?</h4>
{/* 箭头函数显示传参,箭头函数形参就是event */}
{/* bind 隐式传参:最后一位参数就是even,但是不写*/}
<button onClick={(e) => this.getEvent(e)}>箭头函数:获取event</button>
<button onClick={this.getEvent.bind(this)}>bind:获取event</button>
<button onClick={(e) => this.getEvent2(10, e)}>箭头函数:获取event</button>
<button onClick={this.getEvent2.bind(this, 10)}>bind:获取event</button>
</div>
{/* 4.阻止默认 e.preventDefault() 注意:return false不行*/}
<div className="redBox" onContextMenu={(e) => this.yj(e)}></div>
{/* 5.阻止传播 e.stopPropagation() */}
<div className="outer" onClick={() => this.outerClick()}>
<div className="inner" onClick={(e) => this.innerClick(e)}>阻止传播</div>
</div>
{/* 6.捕获 */}
<div className="outer" onClickCapture={() => this.outerClick()}>
<div className="inner" onClickCapture={(e) => this.innerClick(e)}>捕获</div>
</div>
</div>
)
}
}
export default Event
5.state
import React, { Component } from "react";
import Child from "./Child";
class State extends Component {
// 0.state是最小的UI状态集合
// 1.初始化state 在constructor中
// 2.取值 let { name, age, sex } = this.state;
// 3.如果state全部要传递给子组件,可以使用{...this.state} {...props}
/* 4.修改state:setState({新值})
4.1 直接修改state,数据会变,页面不会渲染
4.2 修改state应该使用setState(),setState()的调用会引起render的重新执行
4.3 render中千万不要调用setState(),否则陷入死循环
4.4 修改数组: 1取 2做 3放
4.5 修改json (1) 取 做 放 (2)...
4.6 this.setState()是异步的,如果想要使用setState()之后的新值,需要在回调函数中处理
*/
// 5.json和数组不能直接通过{}展示在页面,需要先JSON.stringify()
constructor() {
super();
this.state = {
name: "妲己",
age: 20,
sex: "女",
arr: [
{ id: 1, name: "哈哈" },
{ id: 2, name: "嘻嘻" },
{ id: 3, name: "嘿嘿" },
],
json: {
name: "赵丽颖",
sex: "女",
},
arr3:["赵丽颖","女","演员"],
num: 10,
num2: 11,
};
}
changeName(name) {
// 直接修改state,数据会变,页面不会渲染
// this.state.name = name;
// 修改state应该使用setState(),setState()的调用会引起render的重新执行
// render中千万不要调用setState(),否则陷入死循环
this.setState({
name: name,
});
}
//修改数组 1取 2做 3放
del(index) {
let { arr } = this.state;
arr.splice(index, 1);
this.setState({
arr: arr,
});
}
// 修改json (1) 取 做 放 (2)...
changeJsonName(name) {
/*
let { json } = this.state;
json.name = name;
this.setState({
json: json,
});*/
this.setState({
json: {
...this.state.json,
name,
},
});
}
// num++
add() {
// this.setState()是异步的,如果想要使用setState()之后的新值,需要在回调函数中处理
this.setState(
{
num: this.state.num + 1, //11
},
() => {
this.setState({
num2: this.state.num * this.state.num, //11*11
});
}
);
/*
axios().then(res=>{
this.setState({
arr:res.data.list
},()=>{
console.log(this.state.arr);
})
})*/
}
render() {
console.log("render is running ...");
/*
let name=this.state.name
let age=this.state.age
let sex=this.state.sex*/
let { name, age, sex, arr, json, num, num2,arr3 } = this.state;
return (
<div className="box">
<h3>state</h3>
<div>num:{num}</div>
<button onClick={() => this.add()}>++</button>
<div>num2:{num2}</div>
<hr />
<div>name:{this.state.name}</div>
<div>age:{this.state.age}</div>
<div>sex:{this.state.sex}</div>
<hr />
<div>name:{name}</div>
<div>age:{age}</div>
<div>sex:{sex}</div>
{/* 如果state全部要传递给子组件,可以使用{...this.state} */}
<Child {...this.state}></Child>
<button onClick={() => this.changeName("貂蝉")}>貂蝉</button>
<ul>
{arr.map((item, index) => (
<li key={item.id}>
{item.name} <button onClick={() => this.del(index)}>删除</button>
</li>
))}
</ul>
{/* <h3>{JSON.stringify(json)}</h3> */}
{/* <h3>{json}</h3> */}
<button onClick={() => this.changeJsonName("赵露思")}>赵露思</button>
================================================================
{/* 可以展示页面*********** */}
<h3>{arr3}</h3>
{/* arr数值套json不展示页面,需要转换{JSON.stringify(arr)}***************** */}
<h3>{arr}</h3>
<h3>{JSON.stringify(arr)}</h3>
<button onClick={() => this.changeJsonName("赵露思")}>赵露思</button>
</div>
);
}
}
export default State;
6.补充关于js 冒泡、阻止默认行为、事件的兼容性写法
冒泡的兼容性写法
可以用event.stopPropagation();方法来阻止冒泡,但是在IE下不支持此方法,但可以利用其event.cancelBubble属性设置为true阻止。
if(event.stopPropagation){
//ie不支持
event.stopPropagation();
}else{
//ie支持
event.cancelBubble = true;
}
阻止默认行为的兼容性写法
-
w3C标准的阻止默认行为的方法是preventDefualt()
-
IE中阻止事件的默认行为的属性是returnValue,为:true不阻止,false:阻止事件的默认行为
if (e.preventDefault) {
//w3c
e.preventDefault();
} else{
//ie
e.returnValue = false;
}
如果我们未通过addEventListener()函数来绑定事件的话,若要禁止默认事件,可以用return false; 但如果要用addEventListener()或者attachEvent()来绑定,就要用preventDefault()方法或者设置事件对象的returnValue属性。
注意:如果在jQuery中return false;相当于同时调用了event.stopPropagation()和event.preventDefault(),事件的默认行为不会被执行,事件也不会冒泡向上传递。
事件的兼容写法:
function getEvent(event){
//获取事件对象的兼容性写法
return event || window.event;
}