一、关于react
-
虚拟DOM 让开发者专注于数据的处理,并且根据数据的变化去操作DOM(性能优化操作DOM)
-
用对象模拟DOM树
createElement('div',{className:'active',id:'box'},'四川')
{ tagName: 'div', attr: { className:'active', id:'box' children:[ { tagName: 'div', attr: {id:'div1'}, text:'数据' } ], text:'技术' }, }, 复制代码
-
生态
- react
- react-native 手机端
关于mvc
- 数据视图控制器
Model View Controller
- react专注于视图层(react不是mvc框架,是V层框架)
二、react安装
npx create-react-app 文件名
cd 文件名
npm start
- 在浏览器上查看:
三、react操作(hello world)
ReactDOM.render
有三个参数
- 参数1:结构
- 参数2:根元素,默认为root
- 参数3;渲染完之后的回调函数(一般用不到) 注意:参数之间用逗号隔开
import React from 'react';
import ReactDOM from 'react-dom';
// 目的:保存不刷新
if(module.hot){
module.hot.accept();
}
ReactDOM.render(
<div>hello world!</div>,
document.getElementById('root'),
()=>{
console.log('success!')
}
);
复制代码
关于JSX语法
JSX语法:可扩展的js语法,不是字符串也不是html
-
- 结构顶层只能有一个元素
// 例如:
<div>hello world!</div><div>123</div>
//会报错
<div>
<div>hello world!</div>
<div>123</div>
</div>
//不会报错
复制代码
-
- class必须写className
-
- 标签必须是闭合状态
<input type='text'/>
- 标签必须是闭合状态
-
- { }
- 可以执行JS语句
- 花括号内有数组默认展开
- 如果元素属性是一个变量需要花括号 src={obj.xx}
- 花括号中不能写for循环
-
- 受控组件与非受控组件
- 如果在表单元素上设置一个默认值(value / checked),该元素为受控组件(即无法输入其他内容)
- 解决方案:加default
<input type='text' defaultValue="hahaha"/>
<input type='checkbox' defaultChecked/>
四、react组件
- 组件化开发:高内聚 低耦合 降低开发成本
1)用class创建组件
import React from 'react';
import ReactDOM from 'react-dom';
if(module.hot){
module.hot.accept();
}
// 1) class创建组件
class App extends React.Component{
render(){
return (
<div>
<div>Hai Jess</div>
<div>Hai Alex</div>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
复制代码
2) 函数式创建组件
import React from 'react';
import ReactDOM from 'react-dom';
if(module.hot){
module.hot.accept();
}
// 2) 函数式创建组件
function App() {
return (
<div>
<div>Hai Jess</div>
<div>Hai Alex</div>
</div>
)
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
复制代码
五、状态status
在react中的所有数据,只要在status下的数据发生变化,就会让视图更新
复制代码
六、事件
// 组件必须的方法
onClick = {()=>{触发事件后的代码}}
// 自定义方法
myClick(){console.log(123)}
onClick = {this.myClick.bind(this)}
复制代码
修改事件函数的this
class App extends React.Component{
constructor(){
super();
this.state = {
list:[1,2,3,4]
}
}
myclick(){
let arr = this.state.list.concat();
arr.push(5);
this.setState({ list: arr });
}
render(){
return (
<div>
<button
onClick = {this.myclick.bind(this)}
>点击生成</button>
{
this.state.list.map((item,i)=><p key={i}>{item}</p>)
}
</div>
)
}
}
复制代码
七、父子组件传递
- 父组件上给子组件中绑定自定义属性,把数据放到自定义属性上
- 子组件中使用
this.props.zdy
去接收
//父组件
class App extends Component {
constructor() {
super();
this.state = {
arr: [11, 22, 33, 44, 55]
}
}
render() {
let {arr} = this.state;
let arr1 = arr.concat();
let list = arr1.map((item,i)=>{
return (
<List
{...{
text:item,
key:i,
a:123,
b:456,
c:789
}}
/>
)
})
return (
{/* <List data={this.state.arr}/> */}
<ul>{list}</ul>
)
}
}
//子组件
class List extends Component {
constructor(){
super();
this.state = {}
}
render(){
let {text,key,a,b,c} = this.props;
console.log(key);
return(
<li>{text}</li>
)
}
}
复制代码
数据的单向流动
react数据单向流:子父组件之间的通讯(数据传递)规则,原则:数据只能从父组件传递到子组件,而不能由子组件直接修改父组件的数据,数据属于谁谁才有资格去修改;
-
情况一: 父级的数据传到子级,数据本身还是父级的,如果用户操作子级要改变传递的数据,那么不能子级改,要让父级修改 父级要定义一个修改数据的方法,在传递数据的时候也一起传给子级 当触发子级行为的时候,子级去调用修改父级数据的方法,然后父级收到后 子级的修改,父级修改数据,当父级的数据发生变化时,又把最新的数据传给子级
-
情况二: 父级把数据给了子级,子级只想在触发子级的时候,子级的数据改变,父级数据不改变 也就是,父级通过自定义的方式传数据给子级,子级可以在constructor中接收到父级传递的数据(就一次),把父级传递的这个数据,变为 this.state,自己就拥有了父级的数据,并且修改自己的数据不会影响到父级