本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-05-26
JSX:在JS中可以混合写入HTML,用于简化React.createElement()
方法创建虚拟DOM。但是本质上还是转换成了React.createElement()
的形式,只是简化了开发人员的写法。
1、安装依赖
npm i babel-core babel-loader babel-plugin-transform-runtime -D
npm i babel-preset-env babel-preset-stage-0 -D # preset:语法
# 用来将jsx语法转换成React.createElement()的形式
npm i babel-preset-react -D
2、配置webpack.config.js
// 因为webpack只能打包处理.js文件 像.vue .png无法主动处理 所以需要配置第三方loader
module.exports= {
// ...
module: {
rule: [
{
test: /\.js|jsx$/, // 应用在哪些文件
use:'babel-loader', // 使用哪种loader 多个用数组表示
exclude:'/node_modules/' // 排除项
}
]
}
}
3、在项目根目录中创建babel.config.js
文件。
module.exports = {
"presets": ["env","stage-0","react"],
"plugins": ["transform-runtime"]
}
4.在index.js文件中使用,底层会被babel转换成React.createElement()
的形式
var myDiv = <div id="myDiv">这是一个div</div>
// 或者在render函数之中直接使用
ReactDOM.render(
<div>
hello wrold
</div>, document.getElementById('app'))
1、使用变量 用大括号包住
let a = 1;
let bool = true;
// 属性使用变量
let str = "这是一个title"
//使用元素
const myh1 = <h1>hello wrold</h1>;
// 使用元素数组
const arr = [
<h2>this is h2</h2>,
<h3>this is h3</h3>
]
ReactDOM.render(
<div>
{ a + 2 }
<hr/>
<p title={str}>{ bool ? '真' : '假' }</p>
<hr/>
{ myh1 }
<hr/>
{ arr }
</div>, document.getElementById('app'))
2、在jsx中使用for循环
const arr = ['111','222','333'];
//省略了return
ReactDOM.render(<div>
{
arr.map(item=><h1 key={item}> { item } </h1>)
}
</div>, document.getElementById('app'))
3、使用class属性 或者label标签的for属性时
// 为了避免关键字 应该这么使用 className代替class htmlFor代替for
ReactDOM.render(<div>
<p className="red">1111</p>
<label htmlFor="name"></label>
</div>, document.getElementById('app'))
1、第一种,直接创建
// 在组件构造函数中 使用props形参来接受 形参可以随意取名 但是建议使用props 组件名称首字符必须是大写
function Hello (props){
// 必须要有return 如果不想渲染任何东西也要return null
// 常规需要return一个合法的虚拟DOM元素
// props 都是只读的
// props.name = 'timo' 报错
return <div>hello world {props.name} say {props.hello}</div>
}
const dog = {
name: "旺财",
say: "wangwang"
}
// 在组件中传递数据
ReactDOM.render(<div>
<Hello name={dog.name} hello={dog.say}></Hello>
</div>, document.getElementById('app'))
// 使用...扩展运算符来简化
ReactDOM.render(<div>
<Hello {...dog}></Hello>
</div>, document.getElementById('app'))
// 这样写之后 就不能使用props.hello去接受 一定要使用props.say
2、第二种,抽离组件为单独的jsx文件
// ./src/components/Hello.jsx
// 在单独的组件文件中必须要导入React
import React from 'react'
export default function Hello (props) {
return <div>hello world {props.name} say {props.hello}</div>
}
// 在webpack.config.js中配置resolve可以省略后缀 和src别名
// {
// resolve:{
// extensions:['.js','.jsx'],
// alias:{
// '@':path.join(__dirname,'./src')
// }
// }
// }
// index.jsx 在使用的地方导入
import Hello from '@/components/Hello'
const dog = {
name: "旺财",
say: "wangwang"
}
ReactDOM.render(<div>
<Hello {...dog}></Hello>
</div>, document.getElementById('app'))
3、使用class创建组件 + 传值
// index.jsx
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
// render作用于渲染当前组件对应的虚拟DOM结构
// 在class中如果要使用传递过来的数据 不需要使用形参props
// 直接使用this.props.xxx
// this表示当前组件的实例对象
render(){
// 一定要有return
return <div>hello wrold {this.props.name}</div>
}
}
const obj = {
name: "aaa",
age: 10
}
ReactDOM.render(<div>
<App {...obj}></App>
</div>, document.getElementById('app'))
// 这里的App标签就相当于是App类的一个实例对象
4、创建组件的区别
// 使用class创建的组件有自己的私有数据和生命周期函数--有状态组件
// 使用function创建的组件 没有自己的私有数据和生命周期函数 -- 无状态组件
// 无状态组件会比有状态组件运行效率高一点 但是使用不多
class App extends Component {
constructor(){
super()
this.state = {
msg: '' // 相当于vue中的data(){return { msg:''}}
}
}
render(){
this.state.msg = 'hi' // 可以修改 但是props在哪都不能修改
return <div>
hello wrold {this.props.name}
<hr/>
{this.state.msg}
</div>
}
}
const obj = {
name: "aaa",
age: 10
}
ReactDOM.render(<div>
<App {...obj}></App>
</div>, document.getElementById('app'))
props
和state
之间的区别
import React,{ Component } from 'react'
import ReactDOM from 'react-dom'
class CmtList extends Component {
constructor() {
super()
this.state = {
list:[
{id:1,name:'zhangsan',age:18},
{id:2,name:'lisi',age:19},
{id:3,name:'wangwu',age:20},
]
}
}
render() {
return (
<div>
<h1>这是一个列表</h1>
{
this.state.list.map(item=><div key={item.id}>
<h1>{item.name}</h1>
<h2>{item.age}</h2>
</div>)
}
</div>
)
}
}
ReactDOM.render(<div>
<CmtList></CmtList>
</div>, document.getElementById('app'))
1、在上面的基础上进行抽离为父子组件
import React,{ Component } from 'react'
import ReactDOM from 'react-dom'
class CList extends Component{
render(){
return (
<div>
<h1>{ this.props.name}</h1>
<h2>{ this.props.age}</h2>
</div>
)
}
}
// 这里的CList 没有状态 可以使用无状态组件来提高运行效率 但是一般不用
// function CList (props) {
// // 需要使用形参props
// return (
// <div>
// <h1>{ props.name}</h1>
// <h2>{ props.age}</h2>
// </div>
// )
// }
class CmtList extends Component {
constructor(){
super()
this.state = {
list:[
{id:1,name:'zhangsan',age:18},
{id:2,name:'lisi',age:19},
{id:3,name:'wangwu',age:20},
]
}
}
render(){
return (
<div>
<h1>这是一个列表</h1>
{
this.state.list.map(item=><CList {...item} key={item.id}></CList>)
}
</div>
)
}
}
ReactDOM.render(<div>
<CmtList></CmtList>
</div>, document.getElementById('app'))
2、把子组件抽离出去 并使用样式
// CList.jsx
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
// 也可以使用一个样式对象的变量
const h2Style = { color:'grenen', fontSize:"20px" }
class CList extends Component{
render() {
// 行内样式不能像vue那样在template中直接使用 style="color:red;font-size:25px"
// 在jsx语法中 要使用双大括号包着 传递一个对象
// zIndex这种可以直接传数字
return (
<div>
<h1 style= {{ color:'red', fontSize:"25px", zIndex:1 }}>{ this.props.name }</h1>
<h2 style= { h2Style }> { this.props.age }</h2>
</div>
)
}
}
export default CList
// CmtList.jsx
import React,{ Component } from 'react'
import ReactDOM from 'react-dom'
import CList from '@/components/CList'
class CmtList extends Component {
constructor(){
super()
this.state = {
list:[
{id: 1, name: 'zhangsan', age:18},
{id:2, name:'lisi', age:19 },
{id:3, name: 'wangwu', age:20 },
]
}
}
render() {
return (
<div>
<h1>这是一个列表</h1>
{
this.state.list.map(item=><CList {...item} key={item.id}></CList>)
}
</div>
)
}
}
3、或者直接将样式对象抽离处理为一个js文件
// style.js
export default {
h1Style: {
color:"red"
},
h2Style: {
color:"green"
}
}
// CList.jsx
import React,{Component} from 'react'
import ReactDOM from 'react-dom'
import myStyle from './style.js'
class CList extends Component{
render(){
return (
<div>
<h1 style= {myStyle.h1Style}>{ this.props.name}</h1>
<h2 style= {myStyle.h2Style}>{ this.props.age}</h2>
</div>
)
}
}
export default CList
4、抽离为css来使用样式
a) 安装 loader
npm i style-loader css-loader -D
b) 配置webpack.config.js
module.exports = {
module:{
rules:[
// ...
{ test: /\.css$/, use: 'style-loader','css-loader'] }
// 从右到左调用loader进行处理
]
}
}
c) 使用
/* style.css */
@import './dist/antd.css'; /* 导入第三方样式 */
.h1Class {
color:"red",
font-size:"25px"
}
.h2Class {
color:"red",
font-size:"25px"
}
// CList.jsx
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './style.css'
// 在单个组件引入的样式表 也会变成全局的 因为样式没有模块作用域
class CList extends Component{
render(){
return (
<div>
<h1 className="h1Class">{ this.props.name}</h1>
<h2 className="h2Class">{ this.props.age}</h2>
</div>
)
}
}
export default CList
d) 使用模块化的css 类似于vue中的scope
// 配置webpack.config.js 中的module 给loader加参数?modules
// ?modules&[path]-[name]-[local]-[hash:5] 其他参数
// :global(.test){ color:'black' }
// 用global包起来的类会作用于全局不再被模块化
module.exports = {
module:{
rules:[
// ...
{ test: /\.css$/, use: ['style-loader','css-loader?modules'] }
// 从右到左调用loader进行处理
]
}
}
其他位置的修改
/* style.css */
.h1Class {
color:"red",
font-size:"25px"
}
.h2Class {
color:"green",
font-size:"20px"
}
#myH3 {
color:'blue'
}
// CList.jsx
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import cssObj from './style.css'
// 用变量来接受 定义的类 会出现在这个变量的属性上
// 实现私有化属性
// css模块化 只针对类选择器 和 ID选择器
// 引入第三方类
import bootstrapCss from 'bootstrap/dist/css/bootstrap.css'
// 但是引入第三方类 写法太麻烦
// 可以自己的样式表使用.scss来写 因为第三方的都是.css
// 给.scss配置模块化参数就行了
// 使用.scss需要安装 npm i sass-loader node-sass -D
// 然后配置webpack.config.js中module的rule
// {t est:/\.scss$/, use:['style-loader','css-loader','sass-loader'] }
class CList extends Component{
render() {
return (
<div>
<h1 className={cssObj.h1Class}>{ this.props.name}</h1>
<h2 className={cssObj.h2Class}>{ this.props.age}</h2>
<h3 id={cssObj.myH3}>Test !!!</h3>
<button className={[bootstrapCss.btn,bootstrapCss['btn-primary']].join(' ')}></button>
</div>
)
}
}
// 如果两个类 className = {cssObj.h1class + ' test'} 第二个类要加一个空格
// 或者 className = {[cssObj.h1class,'test'].join(' ')} 使用数组join方法
export default CList