前情回顾:React技术栈 --》plugin与JSX语法使用 ## Day2_亦世凡华、的博客-CSDN博客
一、在JSX中书写JS代码
书写方法
在上文说到在React项目中启用JSX语法,那么如何在JSX中写JS代码呢?
这里一开始会先const一个常量,然后再把常量引入到ReactDOM中,能不能直接把HTML代码写入ReactDOM.render()里面呢?显然是可以的。代码执行过程中遇到
那么如何通过一个变量来替换固定的123呢?简单,只需要定义一个变量就行
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
let a = 10;
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>{a}</div>,document.getElementById('app'))
这就有点像Vue里面的插件表达式了,不过Vue中引入变量名称需要{{ }}俩个大括号。 当然这是最基本的,JSX语法中也可以渲染很多东西,像字符串、布尔值等。
import React from 'react'
import ReactDOM from 'react-dom'
let str = 'hello world';
let bool = true;
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
{str}
<hr />
{bool ? '条件为真':'条件为假'}
</div>,document.getElementById('app'))
那么如何为属性绑定值呢?去掉引号加上括号和变量即可,什么情况下需要使用 {} 呢?当我们需要在 JSX 控制的区域内,写JS表达式,则需要把JS代码写到{}中。
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
let title = '标题';
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
<p title={title}>这是p标签</p>
</div>,document.getElementById('app'))
那么如何渲染JSX元素和元素数组呢?在JSX中渲染元素直接const一个标签并放入JSX中即可。
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
const h1 = <h1>我是一个h1标签</h1>
const arr = [
<h1>这是h1</h1>,
<h2>这是h2</h2>
]
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
{h1}
{arr}
</div>,document.getElementById('app'))
那么如何将普通字符串数组转为jsx数组并渲染到页面上呢? (俩种方式)
定义一个空数组来存放名称标签 [方案1]
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
const arrStr = ['喜羊羊','懒洋洋','沸羊羊','慢羊羊','灰太狼'];
const newArr = [];
arrStr.forEach(item => {
const temp = <h5>{item}</h5>
newArr.push(temp)
})
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
{newArr}
</div>,document.getElementById('app'))
这里介绍一下JS中map函数方法,方案2就借用map方法来实现。
const arrStr = ['喜羊羊','懒洋洋','沸羊羊','慢羊羊','灰太狼'];
//数组中的map方法,map中必须写return数组
const result = arrStr.map(item => {
return item + '~~~'
})
console.log(result);
定义一个空数组来存放名称标签 [方案2] 推荐
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
const arrStr = ['喜羊羊','懒洋洋','沸羊羊','慢羊羊','灰太狼'];
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
{arrStr.map(item=>{
return <h3>{item}</h3>
})}
//如果箭头函数右侧只有一行代码,花括号是可以省略的,花括号省略是不需要return函数的。
//所以也可以这样书写
//{arrStr.map(item=> <h3>{item}</h3> )}
</div>,document.getElementById('app'))
注意特点
1.虽然我们把数组通过JSX语法渲染到页面上,但存在一个问题,如下
警告提示提醒我们,在React中,需要把 key 添加给 被 forEach 或 map 或 for 循环直接控制的元素。以方案2举例,警告消失。
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
const arrStr = ['喜羊羊','懒洋洋','沸羊羊','慢羊羊','灰太狼'];
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
{arrStr.map(item => <h3 key={item}>{item}</h3>)}
//如果循环的对象外层还有元素,是要把key给到外层元素的,否则会报错
{arrStr.map(item => <div key={item}><h3>{item}</h3></div>)}
</div>,document.getElementById('app'))
2.在jsx中的元素添加class类名:需要使用className来代替class;htmlFor替换label中的for属性
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
<p class="111">这是p标签</p>
<label for="222">这是label标签</label>
</div>,document.getElementById('app'))
因为class和for在JS中都是关键字,有特定含义的,为了区分JSX使用其它关键字来代替
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
<p className="111">这是p标签</p>
<label htmlFor="222">这是label标签</label>
</div>,document.getElementById('app'))
3.在JSX创建DOM的时候,所有的子节点,必须有唯一的根元素进行包裹。
4.在JSX语法中,标签必须成对出现,如果是单标签,则必须自闭和。
二、React中创建组件
一、第一种创建组件的方式
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
function Hello(){ //组件的首字母必须大写,不然会被当作普通标签处理,没有意义
//在组件中 必须返回一个合法的 JSX 虚拟DOM元素;return一个 null 表示此组件为空什么都不会渲染
return <div>这是animal组件</div>
}
const cat = {
name:'加菲猫',
age:'4',
gender:'雄'
}
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
123
{/* 直接把组件名称以标签的形式丢掉页面上即可 */}
<Hello name={cat.name} age={cat.age} gender={cat.gender}></Hello>
</div>,document.getElementById('app'))
这里借用React插件查看,我们的属性已经写入页面中,这里我们是使用React17中的render方式,提醒我们要用React18root方式,这里暂时忽略,后期会讲到。因为属性都会在props中,所以我们传入形参的时候,最好是传入props,这样才有语义。
注意:不论是Vue还是React,组件中的props永远都是只读的;不能被重新赋值,否则报错。
//第一种创建组件的方式
function Hello(props){
//在组件中 必须返回一个合法的 JSX 虚拟DOM元素;return一个 null 表示此组件为空什么都不会渲染
//不论是Vue还是React,组件中的props永远都是只读的;不能被重新赋值
props.name = '张小凡'
console.log(props);
return <div>这是animal组件---{props.name}---{props.age}---{props.gender}</div>
}
一、ES6中展开运算符的使用
何为展开运算符?展开运算符可以把对象或数组里面的属性展开放到另一个对象或数组身上。根据上文提到的cat的属性,我们可以这样写,一样达到的效果,而且更简便
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
123
{/* 直接把组件名称以标签的形式丢掉页面上即可 */}
{/* <Hello name={cat.name} age={cat.age} gender={cat.gender}></Hello> */}
<Hello {...cat}></Hello>
</div>,document.getElementById('app'))
在比如举个例子:这么就很方便处理多个数据
var a1 = {
name:'小王',
age:'30',
sex:'男'
}
var a2 = {
...a1,
address:'北京'
}
console.log(a2);
二、将组件抽离为单独的jsx文件
正常我们讲,虽然React也是属于js的,但js中又有js代码,又有组件的jsx语法代码,有点混乱,所以一般我们会和Vue一样,将组件抽离出来单独放到一个文件夹中。便于代码的书写和处理。
因为所有的源代码都要放在src下,所以我们新建文件夹components,在该文件夹下存放组件。
注意 .jsx后缀名的文件如果想被正常解析,需要确保webpack.config.js里面加入如下命令
接下来就可以将组件一个个进行抽离,单独放在一个文件里。这里写入Hello.jsx文件中。
//必须要导入React不然会报错
import React from "react"
//创建组件
function Hello(props){
return <div>这是animal组件</div>
}
//必须要把组件暴露出去,才能使用
export default Hello
//也可以以这样写
//export default function Hello(props){
// return <div>这是animal组件</div>
//}
而在index.js文件中要想使用组件的话,也是需要导入的。
//导入 Hello 组件
//默认,如果不做单独配置的话,不能省略 .jsx后缀名
import Hello from './components/Hello.jsx'
后缀名问题:如果想省略后缀名的话,可以这样做。打开webpack.config.js,并在导出的配置对象中新增如下节点。即可不写后缀名也不会报错的,可以了解一下,适合自己的就是最好的。
路径问题:在React中导入组件你可能会见到像 @ 这样的符号在路径的开头,这里的@符号 ,表示项目根目录中的 src 这一层目录,只要加了@就指定在哪一文件目录下,比较方便,如何适合自己并喜欢的话可以去配置一下,如下, 这样导入组件也确实方便。
import Hello from '@/components/Hello'
二、ES6中class类使用的简单介绍
使用class关键字来创建组件,class是属于ES6中的新特性,学习之前应该先了解一下ES6吧
一、实例属性和静态属性
//用function创建对象
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
const p1 = new Person('张小凡',18,'男')
//通过new出来的实例,访问到的属性,叫做【实例属性】
console.log(p1);
//通过构造函数直接访问到的属性,叫做【静态属性】
Person.boys = '小男孩';
console.log(p1.boys); //undefined
console.log(Person.boys); //小男孩
//用class创建对象
class Animal{
/* constructor(){} 这是类中的构造器,每一个类中都有一个构造器,
如果我们程序员没有手动指定构造器,那么可以认为类内部有个隐形的看不见的
空的构造器,类似于 constructor(){}
*/
//构造器的作用:每当new这个类的时候,必然会优先执行构造器里面的代码
constructor(name,age){
//实例属性
this.name = name;
this.age = age;
}
// 在 class内部,通过 static 修饰的属性,就是静态属性
static animal = '加菲猫';
}
const p2 = new Animal('加菲猫',4);
console.log(p2);//实例属性
console.log(Animal.animal);//animal是Animal的静态属性
二、实例方法和静态方法
//用function创建对象
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
const p1 = new Person('张小凡',18,'男')
//实例方法
Person.prototype.say = function (){
console.log('这是Person的实例方法');
}
p1.say();
//静态方法
Person.turn = function(){
console.log('这是Person的静态方法');
}
// p1.turn(); 报错
Person.turn();
//用class创建对象
//注意1:在class的{ }区间内,只能写 构造器、静态方法和静态属性、实例方法
//注意2:class内部关键字,还是用原来的配方实现的;所以说我们把class关键字称为语法糖
class Animal{
constructor(name,age){
this.name = name;
this.age = age;
}
static animal = '加菲猫';
shape1(){
console.log('这是Animal的实例方法');
}
static shape2(){
console.log('这是Animal的静态方法');
}
}
const p2 = new Animal('加菲猫',4);
p2.shape1();
Animal.shape2();
三、子类继承父类
我们在编程过程中,可能会遇到许多要写重复的代码,如下
class Boys{
constructor(name,age){
this.name = name;
this.age = age;
}
}
const p1 = new Boys('张三',18);
console.log(p1);
class Girls{
constructor(name,age){
this.name = name;
this.age = age;
}
}
const p2 = new Girls('李四',18);
console.log(p2);
两个类都有重复的姓名年龄,如何简便书写,优化代码的简洁度呢?这里讲到了继承。我们可以把子类中相同的代码放到父类身上,然后再子类继承父类,这样便简便了许多重复代码的书写。
class People{
constructor(name,age){
this.name = name;
this.age = age;
}
//添加一个实例方法,打招呼
sayHello(){
console.log('你好');
}
}
//在class类中,可以使用 extends 关键字,实现子类继承父类
//语法:class 子类 extends 父类
class Boys extends People{
}
const p1 = new Boys('张三',18);
console.log(p1);
p1.sayHello();
class Girls extends People{
}
const p2 = new Girls('李四',18);
console.log(p2);
p2.sayHello();
四、class构造器中super函数的使用说明
承接上文,继承就是父类的东西就是子类的,但子类的东西不是父类的,所以这里我在子类中传入一个构造器,没有书写任何东西,请看结果。
class Boys extends People{
constructor (){
}
}
如图报错提醒我们丢失了super()函数。什么是super?super是一个函数,而且它是父类的构造器,子类中的super其实就是父类中constructor构造器的一个引用;为什么要调用super?因为如果一个子类通过extends关键字继承了父类,那么,在子类的constructor构造函数中必须优先调用一下super()
class Boys extends People{
constructor (){
super();
}
}
调用之后为什么p1实例的name和age都变成undefined了呢?因为我们在调用super()的时候,并没有传入name和age。当你new一个类,必然会用new这个类里面的构造器,所以我们要把参数传入到构造器中,又因为构造器里面只有super(),所以应该把参数传入super中,才能调用父类。
class Boys extends People{
constructor (name,age){
super(name,age);
}
}
什么情况下要用到super()呢? 当子类通过extends继承父类的时候,那么子类里面的构造器应该要先调用一下super(),因为super()调用的是父类的构造器。
五、class中为子类挂载独有的实例属性和实例方法
在子类中,可能每个子类都有它们独有的特点,正因为独有所以不能放到父类当中去。举例:
class Girls extends People{
constructor (name,age,white){
super(name,age)
//语法规范:在子类中,this只能放到super之后使用
this.white = white
}
}
假设白是girls子类中独有的属性,所以在传参时只需在构造器中传入并this这个属性就行。
后期文章会单独讲解ES6语法规范,今天就提到这。
三、第二种创建组件的方式
class关键字创建组件最基本的组件结构:
//如果要使用 class 定义组件,必须让自己的组件继承自React.Component
class 组件名称 extends React.Component{
//在组件内部必须有render函数,render函数的作用,是渲染 当前组件所对应的 虚拟DOM元素
render(){
//render 函数中,必须返回合法的JSX虚拟DOM结构
return <div>这是 class 创建的组件</div>
}
}
//1.导入包
import React from 'react'
import ReactDOM from 'react-dom'
//class关键字创建组件
class People extends React.Component{
//render函数的作用,是渲染 当前组件所对应的 虚拟DOM元素
render(){
return <div>这是 People 组件</div>
}
}
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
{/* 这里的People标签,其实就是上文所讲到的People类的一个实例对象 */}
<People></People>
</div>,document.getElementById('app'))
在 class 关键字创建的组件中,如果想使用外界传递过来的参数,不需接收,直接通过this.props.***访问即可。
//class关键字创建组件
class People extends React.Component{
render(){
return <div>
这是 People 组件
{/* 注意:在class组件内部,this表示当前组件的实例对象 */}
{this.props.name}
</div>
}
}
const user = {
name:'张三',
age: 18,
sex:'男'
}
//3.将创建好的虚拟DOM渲染到页面上去
ReactDOM.render(<div>
<People name={user.name} age={user.age} sex={user.sex}></People>
</div>,document.getElementById('app'))
嗯~ , 差不多就这些了,剩下的内容下期在补充。
原创不易,呜呜~,看到这还不点赞加收藏?
版权归原作者 亦世凡华、 所有, 如有侵权,请联系我们删除。