教程参考自啊B的这个视频 用于构建用户界面的JavaScript库。(只关注视图,只管界面的呈现)。 是一个将数据渲染为HTML视图的开源JavaScript库。
全程JavaScript XML。XML早期用于存储和传输数据,后期被JSON代替。类似如下图
{}
)引入;style={{color:'red',fontSize:'20px'}}
这样,变量加引号,有横杆的变量名用小驼峰写法;表达式 | 语句(代码) |
---|---|
一个表达式会产生一个值,可以放在任何一个需要值的地方 | 控制代码走向,没有值 |
a | if(){} |
a+b | for(){} |
demo(1) | switch(){case:xxxx} |
arr.map() | |
function test() {} |
不用使用index作为遍历的key。
用来实现局部功能效果的代码和资源的整合。复用编码,简化项目编码,提高运行效率。
class Person {
constructor(name,age) {
this.name = name;
this.age = age;
}
// 类中可以直接写赋值语句
// 给类的实例对象添加一个属性,名字为val,值为1
val = 1
// 类中的一般方法
speak() {
// speak方法放在了哪里 ————类的原型对象上,供实例使用
// 通过Person实例调用speak时,speak中的this就是Person实例
console.log("我叫${this.name},我年龄是${this.age}");
}
}
class Student extends Person {
constructor(name, age, grade) {
// 必须在最开始调用
super(name, age);
this.grade = grade;
}
// 重写
speak() {
console.log("我叫${this.name},我年龄是${this.age},正在读${this.grade}");
}
// 独有方法
study() {
// study方法放在了哪里 ————类的原型对象上,供实例使用
// 通过Student实例调用study时,study中的this就是Student实例
console.log("Study");
}
}
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
// 类中所定义的方法,在局部定义了严格模式
speak() {
console.log();
}
}
const p = new Person("Name",1);
p.speak();// 通过实例调用study方法
const x = p.speak;
x();
更改实例中的this指向对象,例如
person.speak.call({a:1,b:2});
// 传过去的值就会是那个对象
类名就是组件名
// 必须继承React.Component React内置类
// 必须有render
// 必须有返回值
class ComponentName extends React.Component {
render() {
// render放在ComponentName的原型对象上,供实例使用
// render中的this——组件实例对象 <=> 实例对象
return (<h1>Hello</h1>)
}
}
// 渲染组件到页面
ReactDOM.render(<ComponentName/>, document.getElementById('idName'))
// React解析组件标签,找到了组件
// React发现组件是类定义的,随后new出该类的实例,并通过该实例调用到原型上的render方法
// 将render返回的虚拟DOM转化为真实DOM,随后呈现在页面中
人状态影响行为;
组件状态驱动页面展示。
同样可以用在JSX中,但是在JSX中主要推荐第三种。
const a = [1,3,5,7,9]
const b = [2,4,6,8,10]
console.log(...a); // 展开一个数组: 1 3 5 7 9
let c = [...a, ...b]// 连接数组
// 在函数中使用
function sum(...numbers) {
return numbers.reduce((per, cur) => {
return per + cur
})
}
let person = {name:"a" ,age:18}
// 复制对象
let person2 = {...person};
console.log(...person)// 报错
// 合并
let p3 = {...person,name:"C"}
let arr = [1,2,3,4,5]
// 初级应用 求和求积
console.log(arr.reduce(a,b) => a + b))// 15
console.log(arr.reduce(a,b) => a*b))// 120
// 计算数组中每个元素的出现次数
let arr = ['name','age','long','short','long','name','name']
let arrResult = arr.reduce((pre,cur) =>{
console.log(pre,cur)
if(cur in pre){
pre[cur]++
}else{
pre[cur] = 1
}
return pre
},{})
console.log(arrResult)//结果:{name: 3, age: 1, long: 2, short: 1}
// 数组去重
let arrResult = arr.reduce((pre,cur) =>{
if(!pre.includes(cur)){
pre.push(cur)
}
return pre;
},[])
console.log(arrResult)//结果:["name", "age", "long", "short"]
// 对象属性求和等
let person = [
{
name: 'xiaoming',
age: 18
},{
name: 'xiaohong',
age: 17
},{
name: 'xiaogang',
age: 19
}
]
let result = person.reduce((a,b) =>{
a = a + b.age;
return a;
},0)
console.log(result)//结果:54
类通过static关键字定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。可以参照static - MDN。
class ClassWithStaticMethod {
static staticProperty = 'someValue';
static staticMethod() {
return 'static method has been called.';
}
}
console.log(ClassWithStaticMethod.staticProperty);
// output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// output: "static method has been called."
class Weather extends React.Component {
// 构造器只调用了一次
constructor(props) {
super(props);
// React官方要求对象
// 初始化状态
this.state = {key1: val1, key2: val2}
// 右侧第一个this是组件实例对象
// bind生成一个新的函数,并且改变this的指向
// 给自身一个functionName
// 解决functionName this指向问题
this.functionName = this.functionName.bind(this)
}
// render调用了 1+n 次
// 1是初始化那次
// n是状态更新的次数
render() {
// 读取状态
const {key1, key2} = this.state
// React基本给js所有on开头的方法都做了重写,换成小驼峰
return (
Str{key1 ? "true" : "false"}
)
}
// 不是通过实例调用的
// 点几次调用几次
functionName() {
// 作为onClick的回调,所以不是通过实例调用的,是直接调用
// 类中的方法默认开启了局部的严格模式,所以functionName中的this为undefined
// 获取原值
const key1 = this.state.key1;
// 严重注意:状态不可直接更改,要借助一个内置的API去更改
// 直接更改,错误写法 => this.state.key1 = !key1;
// 严重注意:状态必须通过setState进行更新,且更新是合并例如下边这样
// 如果只给一个key1,只会替换key1的,不会影响到其他的。
this.setState({key1: !key1})
}
}
ReactDOM.render(,document.getElementById('idName'))
// 简写方式
class Weather extends React.Component {
// 初始化状态
this.state = {key1: val1, key2: val2}
render() {
const {key1, key2} = this.state
return (
Str{key1 ? "true" : "false"}
)
}
// 箭头函数没有自己的this,它会找外层this作为自己的this
// 自定义方法(赋值语句的形式 + 箭头函数)
functionName = () => {
const key1 = this.state.key1;
this.setState({key1: !key1})
}
}
ReactDOM.render(,document.getElementById('idName'))
P19结束。
Props是只读的。
通过标签传值到组件,就类似于Vue中的父子组件传值
class Component extends React.Component {
// 构造器是否接收props,是否传递给super,取决于是否希望在构造器中通过this范围props
// 类中构造器能省则省
remder() {
return (
11
)
}
}
// 批量传值
// ES6 扩展运算符(展开运算符)
// 批量传递标签属性(props)
// 对传递的标签进行类型限制
// 设置默认值
// 设置是否必填
// function改为func
function Person(props) {
const {key1, key2} = props
return (
相当于原生的ID,标识自己。
发生事件的元素就是要操作的元素,可以省略ref。
Vue中的this.$refs.refName.function();
字符串的ref存在一些效率问题。
class Demo extends React.Component {
render() {
return(
提示
// onBlur失去焦点
)
}
showData = () => {
// 解构赋值
const {input1} = this.refs
alert(input1.value)
}
showData2 = () => {
// 解构赋值
const {input2} = this.refs
alert(input2.value)
}
}
回调函数:
class Demo extends React.Component {
render() {
return(
this.input1 = c}/>
提示
// onBlur失去焦点
this.input2 = c} onBlur={this.showData2}/>
)
}
showData = () => {
const {input1} = this
alert(input1.value)
}
showData2 = () => {
const {input2} = this
alert(input2.value)
}
}
如果ref回调函数是以内联函数形式定义的,在更新过程中它会被执行两次,第一次传入参数null,第二次传入才是对应的Node。这是因为在每次渲染的时会创建一个新的实例,所以React清空旧的ref并且设置新的。通过ref的回调函数定义成class的绑定函数可以避免上述问题。
class Demo extends React.Component {
state = {isHot: true}
showData = () => {
const {input1} = this
alert(input1.value)
}
changeWeather = () => {
const {isHot} = this.state;
this.setState({isHot:!isHot})
}
saveInput = (c) => {
this.input1 = c;
console.log("@",c)
}
render() {
const {isHot} = this.state
return(
)
}
}
class Demo extends React.Component {
// React.createRef条用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”
myRef = React.createRef()
showData = () => {
const {current} = this.myRef
alert(current.value)
}
render() {
return(
提示
)
}
}
P31结束
class Demo extends React.Component {
// 创建容器
myRef = React.createRef()
showData = () => {
alert(this.myRef.current.value)
}
// event 发生事件的事件对象
showData2 = (event) => {
alert(event.target.value);
}
render() {
return(
提示
)
}
}
class Login extends React.component{
handleSubmit = (event) => {
event.preventDefault()// 阻止(表单提交)默认事件
const {username, password} = this
}
// 页面类所有输入类的DOM,现用现取
render(){
return(
登录
)
}
}
像是手写了Vue的双向绑定。
class Login extends React.component{
// 初始化状态
state = {
username:"",
password:""
}
// 提交表单
handleSubmit = (event) => {
event.preventDefault()// 阻止(表单提交)默认事件
const {username, password} = this.state
alert(username,password)
}
// 保存用户名
demo = (event) => {
console.log(event.target.value)
this.setState({username:event.target.value})
}
render(){
return(
登录
)
}
}
saveFromData就是高阶函数,如果符合下边两个规范中的任何一个,那就是高阶函数
new Promise(() => ())
(() => {})
arr.map
通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的编码形式。
function sum(a,b,c){
return a+b+c;
}
res = sum(1,2,3)
// 函数柯里化
function sum(a){
return(b)=>{
return(c)=>{
return a+b+c
}
}
}
res = sum(1)(2)(3)
// 如下例子
let a = 'name'
let obj = {}
obj[a] = 'tom' // 外加方括号给对象新增属性
console.log(obj)// {name:"tom"}
// 生命周期回调函数 <==> 生命周期钩子函数 <==> 生命周期函数 <==> 生命周期钩子
class Life extends React.Component {
state = {opacity:1}
// 卸载一个组件
death = () => {
ReactDom.unmountComponentAtNode(document.getElementById('test'))
}
// 类似于vue中的mounted
// 组件挂完后调用
componentDidMount(){
this.timer = setInterval(() => {
let {opacity} = this.state
opacity -= 1
if(opacity <= 0){
opacity = 1
}
this.setState({opacity})
},200)
}
// 组件将要卸载
componentWillUnmount(){
// 清除定时器
clearInterval(this.timer);
}
render() {
// 如果写在这里,修改state触发render,无限调用了
/* setInterval(() => {
let {opacity} = this.state
opacity -= 1
if(opacity <= 0){
opacity = 1
}
this.setState({opacity})
},200)*/
return (
String
隐去
)
}
}
class Count extends React.Component{
// 构造器
constructor(props){
super(props)
console.log("Count-constructor")
this.state = {count:0}
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
add = () => {
const {count} = this.state
this.setState = {{count:count + 1}}
}
update = () => {
this.forceUpdate()
}
// 组件将要挂载的钩子
componentWillMount() {
console.log("Count-componentWillMount")
}
// 组件将挂载完毕的钩子
componentDidMount() {
console.log("Count-componentDidMount")
}
// 卸载组件
componentWillUnmount(){
console.log("Count-componentWillUnmount")
}
componentWillReceiveProps(){
}
// 组件是否应该被更新
// 类似阀门一样的东西,是否允许更新
// 不写,默认返回true
// 如果写了函数,不给返回值,会报错,一定要有返回值
shouldComponentUpdate(){
console.log("Count - shouldComponentUpdate");
return true / false;
}
// 组件将要更新
componentWillUpdate(){
console.log("Count - componentWillUpdate");
}
// 组件更新完毕
componentDidUpdate(){
console.log("Count - componentDidUpdate");
}
render(){
console.log("render")
const {count} = this.state
return(
)
}
}
class A extends React.Component{
state = {carName:"奔驰"}
changeCar = () => {
this.setState({carName:"奥拓"})
}
render(){
return(
A
)
}
}
class B extends React.Component{
componentWillReceiveProps(){
console.log("B——componentWillReceiveProps")
}
render(){
return(
B,:{this.props.carName}
)
}
}
到P48
虚拟DOM对比的最小力度是标签。如果标签里套标签,也还会逐层比较。
React / Vue中的key有什么作用?(key的内部原理是啥)
为什么遍历列表时,key最好不要用index。
虚拟DOM中key的作用
用index作为key可能会引发的问题:
如何选择key:
单页面应用
SPA应用 single page application
public:一般存储静态资源
src:
P52
一个路由就是一个映射关系,key为value,value可能是function或component。
HashRouter会出现#,Brower不会出现。
明确导航区、展示区。
<Demo/>
2. 路由组件:<Route path='/demo' component={Demo}/>
```都会展示出来
### 精准匹配与模糊匹配
两种情况:
1. navLink那边给多了,也就是到了子路径,route可以检测,例如navLink到`/home/a/b`,route的path为:`/hone`这样可以匹配
2. 反之则不行。
![](https://img.imgdb.cn/item/604b11a35aedab222ca8bf1f.jpg)
React用params多点
```# Redux(类似Vue中的Vuex)
1. Redux是一个专门用于做状态管理的JS库(不限于React使用)
2. 可以用在React、Angular、Vue等项目中,但基本与React配合使用
3. 作用:集中式管理React应用多个组件共享的状态
## 什么时候使用Redux
1. 某个组件的状态,需要让其他组件可以随时拿到;
2. 一个组件需要改变另一个组件的状态;
3. 总体原则:能不用就不用,如果不用的时候编码比较吃力才考虑使用。
![](https://img.imgdb.cn/item/604c41735aedab222c2ab260.jpg)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。