1.简介:
1.用于动态构建用户界面的JavaScript库(只关注与视图)
2.由FaceBook开源
3.采用组件化模式,声明式编码,提高开发效率及组件复用率
4.在React Native中可以使用React语法进行移动端开发
5.使用虚拟DOM+优秀的diffing算法,尽量减少与真实DOM的交互
1.1.原生DOM的缺点
1.原生JavaScript操作DOM频繁,效率低(DOM-api操作UI)
2.使用JavaScript直接操作DOM,浏览器会进行大量的重绘重排
3.原生JavaScript没有组件化编码方案,代码复用率低
1.2React高效的原因
1.使用虚拟(virtual)DOM,不总是直接操作页面真实DOM
2.DOM Diffing算法,最小化页面重绘
1.3关于虚拟DOM
1.虚拟DOM就是一个普通的object对象(一般对象)
2.虚拟DOM比较"轻",真实DOM比较重,因为虚拟DOM在React内部使用,无需真实DOM的那么多属性
3.虚拟DOM最终会被react转化为真实DOM,呈现在页面上
2.jsx
1.全称:JavaScript XML
2.react 定义的一种类似于XML的js扩展语法:js+XML本质是React.createElement(component,props,…children)方法的语法糖。
3.作用:用来简化创建虚拟DOM
3.1写法 var VDOM = <h1> Hello JSX! </h1>
3.2注意,他不是字符串,也不是html/xml标签
3.3注意,它最终产生的就是一个js对象
2.1.jsx语法规则
1.定义虚拟dom时,不要写引号
2.标签中混入js表达式时要用{}
表达式与js语句的区别,
2.1表达式:会产生一个值,可以放在任何需要值的地方
① a //一个变量
②a+b //一个算数表达式
③demo(1) //函数调用得到确认的值
④arr.map() //map函数获得一个新数组
⑤json对象
2.2语句:
①if(){}
②else{}
③for(){}
④switch(){}
3.样式的类名指定不要用class,要用className
4.内联样式,要用style={{key:value}}的形式去写,外层花括号,表示js的代码,内层花括号表示是一个对象
5.虚拟dom只能有一个根标签
6.标签必须闭合
7.标签首字母:
①若小写字母开头,则将该标签转为html同名元素,若HTML中无该标签对应的同名元素,则报错
②若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错
2.2babel.js的作用
1.浏览器不能直接解析jsx代码,需要babel转译为纯js的代码才能运行
2.只要用了jsx,都要加上type=“text/babel”,声明需要babel来处理
3. 渲染虚拟DOM元素
1.语法:ReactDOM.render(virtualDOM,containerDOM);
2.作用:将虚拟DOM元素渲染到页面中的真实容器DOM中显示
3.参数说明:
a.参数1:纯js或jsx创建的虚拟dom对象
b.参数2:用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
4.hello,React
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello,React</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 先引入react核心库 -->
<script src="./js/react.development.js"></script>
<!-- 才能引入react-dom,用于支持react操作DOM -->
<script src="./js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="./js/babel.min.js"></script>
<script type="text/babel"> //此处一定要写babel
// 1.创建虚拟DOM
const VDOM = <h1> Hello,React </h1> //此处一定不要写引号,因为不是字符串而是虚拟dom
// 2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
创建虚拟DOM不能有引号,并且只能有一个跟标签
如果多行:
const VDOM = (<h1 id="title">
<span> Hello,React </span>
</h1>)//此处一定不要写引号,因为不是字符串而是虚拟dom
小案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom库,用于支持react操作dom -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 模拟一些数据
const data = ['Angular','React','Vue'];
// 1.创建虚拟dom
const VDOM = (
<div style={{border:'1px solid #ccc',width:'300px'}}>
<h1>前端js框架列表</h1>
<ul>
{
data.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
</div>
)
// 2.将虚拟DOM渲染到页面
ReactDOM.render(VDOM,document.getElementById('test'));
</script>
</body>
</html>
虚拟DOM中多个列表,必须有不同的key值,否则报错
5.创建组件
组件分为函数式组件和类式组件
5.1函数式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建函数式组件
function MyCompontent(){
console.log(this); //undefined 是babel开启了严格模式
return <h2>我是用函数定义的组件(适用于简单组件) </h2>
}
// 2.渲染组件到页面
ReactDOM.render(<MyCompontent/>,document.getElementById('test'));
// 执行ReactDOM.render(<MyComponent/>,document.getElementById('test')) 之后
// 1.React解析组件标签,找到了MyComponent组件
// 2.发现组件是使用函数定义的,随后调用该函数
// 将返回的虚拟DOM转为真实DOM,随后呈现在页面中
</script>
</body>
</html>
5.2类式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建类式组件
class MyComponent extends React.Component{
render(){
console.log('render中的this:',this);
// render是放在哪里的?-——MyComponent的原型对象上,供实例使用
// render中的this是谁 ———MyComponent的实例对象, <=> MyComponent组件实例对象
return <h2>我是用类定义的组件,适用于复杂组件的定义</h2>
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'));
// 执行ReactDOM.render(<MyComponent/>,document.getElementById('test')) 之后
// 1.React解析组件标签,找到了MyComponent组件
// 2.发现组件是使用类定义的,随后new出来该类的实例
// 并通过该实例调用到原型上的render方法
// 3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中
</script>
</body>
</html>
类:
1.类中的构造器不是必须写的,要对实例进行一些初始化的操作时,如添加指定属性时,才写
2.如果A类继承了B类,且A类中写了构造器,那么A类构造器中的super必须要调用
3.类中所定义的方法,都是放在了类的原型对象上,供实例去使用
6.js中类的基本知识
6.1类的声明和使用
<script>
// 创建一个Person类
class Person{
// 构造器方法
constructor(name,age){
// 构造器中的this指的谁,——类的实例对象
this.name = name;
this.age = age;
}
// 一般方法
speak(){
// speak方法放在了哪里? ————放在了类的原型对象上,供实例使用
// 通过Person实例调用speak时,speak中的this就是Person实例。
console.log(`我叫${this.name},我年龄${this.age}`);
}
}
// 创建一个Person的实例对象
const p1 = new Person('tom',19);
const p2 = new Person('jerry',10);
console.log(p1);
console.log(p2);
p1.speak();
p2.speak();
</script>
6.2类的继承
<script>
// 创建一个Person类
class Person {
// 构造器方法
constructor(name, age) {
// 构造器中的this指的谁,——类的实例对象
this.name = name;
this.age = age;
}
// 一般方法
speak() {
console.log(`我叫${this.name},我年龄${this.age}`);
}
}
// 创建一个Student类,继承于Person类
class Student extends Person{
constructor(name,age,grade){
super(name,age); //共有的属性通过super来构造,super写在最前面
this.grade = grade;
}
// 重写从父类继承过来的方法
speak(){
console.log(`我叫${this.name},我年龄${this.age},我读的是${this.grade}`);
}
study(){
// 通过Student实例调用study时,study中的this就是Student的实例
console.log('我很努力的学习');
}
}
const s1 = new Student('小张',15,'高一');
console.log(s1);
s1.speak(); //我叫小张,我年龄15,我读的是高一
s1.study(); //我很努力的学习
</script>
6.3类中直接写赋值语句
<script>
class Car{
constructor(name,price){
this.name = name;
this.price = price;
this.wheel = 4;
}
// 类中可以直接写赋值语句,如下代码的含义是:给Car的实例对象添加一个属性,名为a,值为1;
a=1;
// run = function(){
// console.log(this);
// console.log('跑起来');
// }
run = ()=>{
//此时this为Car的实例对象,箭头函数this,会去寻找上下文中的内容
console.log(this);
console.log('跑起来');
}
}
const c1 = new Car('帕拉梅拉',199);
const c2 = new Car('捷豹F-type',299);
console.log(c1);
console.log(c2);
c1.run();
c2.run();
</script>
由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值
6.4bind
<script>
// bind改变this的指向,并返回一个新函数
function demo(){
console.log(this);
}
demo(); //window对象
const x = demo.bind({a:1,b:2});
x(); //{a:1,b:2}
</script>
6.5类中局部开启严格模式
<script>
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
speak(){
// speak放在哪里,————Person的原型对象上,供实例使用
// 通过Person实例调用speak,speak中的this就是Person实例
console.log(this); //Person对象
}
}
const p1 = new Person('tom',18);
p1.speak(); //通过实例调用speak方法
const x = p1.speak;
x(); //直接调用 //undefined
// 类中局部开启了严格模式
</script>