react笔记
创建一个项目
npm install -g create-react-app // 全局安装脚手架
create-react-app react-01 // 新建一个项目
npm start
快捷定义组件
- 安装组件后,快捷命令 rcc :类式组件 rfc:函数式组件
axios开启代理
- 在package.json中新增
{
proxy:"http:192.168.2.107:8080"
}
如何开启服务运行项目打包后的dist包
- 全局安装 serve
npm i serve -g
- serve 文件夹名
serve dist
父子组件传值
- 父传子:子组件this.props接收
- 子传父:父组件定义方法接收参数,将方法传给子组件;子组件在合适时机调取改方法并传参
// 父组件
class App extends Component {
addList = (item) => { // 1.定义方法
}
render() {
return (
<div>
<Add addList={this.addList} /> // 2.传递方法
</div >
);
}
}
// 子组件
export default class Add extends Component {
add = (e) => {
if (e.keyCode == 13) {
this.props.addList(e.target.value) // 3.调用方法
}
}
render() {
return (
<div>
<input type="text" placeholder='新增' onKeyUp={this.add} />
</div>
)
}
}
任意组件通信——订阅发布机制
- 安装库
npm i pubsub-js
- 需要接收信息的组件订阅消息
import PubSub from 'pubsub-js'
export default class Foot extends Component {
componentDidMount() { // 组件渲染完成创建订阅 (消息名字,收到消息回调(消息名字,数据))
this.sub = PubSub.subscribe('getData', (name, data) => {
console.log(name, data)
})
}
componentWillUnmount() {
PubSub.unsubscribe(this.sub) // 组件卸载前取消订阅
}
render() {
return (
<div></div>
)
}
}
- 发送数据的组件在合适实际发布订阅消息
import PubSub from 'pubsub-js'
export default class Add extends Component {
add = (e) => {
PubSub.publish('getData', e.target.value) // 发布订阅消息
}
render() {
return (
<div>
<input type="text" placeholder='新增' onKeyUp={this.add} />
</div>
)
}
}
spa 单页面应用(vue、react)
git提交代码报错
报错信息:Git: husky > pre-commit (node v14.16.1)
错误原因:项目中使用了husky, 这个会在你git commit的时候先执行里面的严谨模式, 对代码进行检查, 有error就会终止提交
git commit前检测husky与pre-commit
- 解决方法
git commit -m "提交页面备注 绕过eslint检查" --no-verify
table添加序号
{
title: '序号',
render: (text, record, index) => {
return (
`${(searchParam.pageIndex || 1 - 1) * (searchParam.pageSize) + (index + 1)}`//当前页数减1乘以每一页页数再加当前页序号+1
)
}
},
普通方法中this的指向
- 方法里this指向window
- 但是当开启局部严格模式,this就指向undefined
- class类中方法自动开启严格模式,所以类中的方法如果不是实例调用,this是undefined;若是实例调用则指向实例对象
- bind可以改变this指向为传进去的参数,并且返回一个新的函数
function qu() {
console.log('this', this)
}
qu() // 打印 undefined
let qu1 = qu.bind(window) // 改变了this指向
qu1() // 打印 window对象
class类中可以写什么——赋值语句
- constructor构造器
- 方法
- 变量赋值 例如
a = 1
class Car {
a = 1, //直接变量赋值,代表给实例添加一个属性
}
const car = new Car()
console.log(22, car) //{a:1}
…展开运算符使用
- 只能展开数组,不能展开对象
- 可用于合并数组
let arr1 = [1, 2, 3, 4]
let arr2 = [6, 7, 8, 9]
console.log(...arr1) // 1 2 3 4
console.log([...arr1, ...arr2]) //合并数组 [1, 2, 3, 4, 6, 7, 8, 9]
- 可用于接收所有参数为数组
function sum(...v) {
console.log(v) //[1, 2, 3, 4]
return v.reduce((s, c) => {
return s + c
})
}
let ss = sum(1, 2, 3, 4)
console.log(ss) // 10
- 可用于克隆一个对象,类似深拷贝,并且可以修改或添加新属性
- 可用于合并对象,属性名相同的会被覆盖,不同的会新增
let obj1 = {
name: 'rose',
age: 18
}
let obj2 = {
name1: 'jack',
age1: 13
}
let obj = { ...obj1 }
console.log(obj) // 类似深拷贝 {name: 'rose', age: 18}
console.log({ ...obj1, name: 'sunny', sex:'1' }) // 克隆并修改属性 {name: 'sunny', age: 18 , sex:'1'}
console.log({ ...obj1, ...obj2 }) // 合并对象 {name: 'rose', age: 18, name1: 'jack', age1: 13}
对象的键名取变量 【】
let obj = { name:'张三' } // {name: '张三'}
let name = 'key';
obj = { [name] : '张三'} // obj[name] = '张三'
console.log(obj) // {key: '张三'}
连续解构赋值并取别名
let obj = {
a: { b: 1 }
}
let { a: { b } } = obj //连续解构,直接拿到b
console.log(b)
let { a: { b: data } } = obj // 变量取别名 变量:别名
console.log(data)
虚拟DOM中key 的作用
- key 是虚拟 DOM 对象的标识,可提高页面更新渲染的效率。
- 当状态中的数据发生变化时,React 会根据新数据生成新的虚拟 DOM ,接着对新旧虚拟 DOM 进行 Diff 比较,规则如下:
旧虚拟 DOM 找到和新虚拟 DOM 相同的 key: 若内容没变,直接复用真实 DOM;若内容改变,则生成新的真实 DOM,替换页面中之前的真实DOM
旧虚拟 DOM 未找到和新虚拟 DOM 相同的 key:根据数据创建新的真实 DOM ,渲染到页面
使用 index 作为 key 可能引发的问题:
- 若对数据进行逆序添加、逆序删除等破坏顺序的操作,会进行没有必要的真实 DOM 更新。界面效果没问题,但效率低下。
- 如果结构中包含输入类的DOM(如 input 输入框) ,则会产生错误的 DOM 更新。
- 若不存在对数据逆序添加、逆序删除等破坏顺序的操作,且没有输入类DOM,使用index则没有问题。
在input上绑定enter键回车事件,并清空input
- 绑定onKeyUp方法
- 在参数e中,e.keyCode代表每个键的键码,e.target.value代表输入的值
- 单选框的值是 e.target.checked
export default class Add extends Component {
add = (e) => {
console.log(e.target.value, e.keyCode) // 13
e.target.value = '' // 清空input
}
render() {
return (
<div>
<input type="text" placeholder='新增' onKeyUp={this.add} />
</div>
)
}
}
根据id匹配来修改、删除、新增数组,统计数组选中的个数
state = {
list: [
{ id: 1, value: '吃饭', checked: true },
{ id: 2, value: '睡觉', checked: false },
{ id: 3, value: '打豆豆', checked: false }
]
}
addList = (item) => {
let { list } = this.state
this.setState({
list: [{ id: list.length + 1, value: item, checked: false }, ...list] // 1.数组前边新增一条数据
})
}
delList = (id) => {
let { list } = this.state
this.setState({
list: list.filter(item => item.id != id) // 2.删除数组某一项,根据id匹配
})
}
changeList = (id, checked) => {
let { list } = this.state
this.setState({
list: list.map(item => { // 3. 修改数组某一项的checked属性值,根据id匹配
if (item.id === id) {
return { ...item, checked } //原理:合并对象,属性名相同会覆盖
} else {
return item
}
})
})
}
getNum = () => {
let { list } = this.state
let num = list.reduce((pre, item) => { // 4.统计选中的个数,reduce(回调(累计值,当前项), [初始值])
return pre + (item.checked ? 1 : 0)
}, 0)
return num
}
数组的循环some、find、filter、map比较
- some 判断数组这种是否有符合条件的项
- find 返回第一个符合条件的项
- filter 返回所有符合条件的的项集合
[1,2,3,4].some(item=>item>2) // true
[1,2,3,4].find(item=>item>2) // 3
[1,2,3,4].filter(item=>item>2) // [3, 4]
[{type:'ss1',id:1},{type:'ss2',id:2},{type:'ss3',id:3}].map(item=>item.type) // ['ss1', 'ss2', 'ss3']