目录
1、JSX 简介
通过上一篇博客的 +1 个小应用,我们能体会到,和 Vue 相比代,用 React 写一个这么小的应用比较麻烦,而且代码比较混乱。接触过 Vue 的开发者应该知道,Vue 有两个构建版本,如果单独使用非完整版其实和上述用 React 实现 +1 的小应用相比并不会有多大优势,也就多一个视图自动刷新的便捷性。
但是 Vue 非完整版可以配合 vue-loader,这使得开发人员可在 .vue 文件中写 <template><script><style>,这些内容最终会被 vue-loader 变成一个构造选项或组件,既可满足用户使用体积小,又能提高开发人员的效率。那 React 有什么类似 vue-loader 的加载器或插件,以提高开发人员的体验 ?— 那就是 JSX,JSX 是 JavaScript 的扩展,它就是弥补 React 代码相对混乱的问题。
React 提供了 JSX 来提高开发人员的体验,和 Vue 相似,开发人员只需要写一些 <template><script><style> 代码,剩下的就交给 jsx-loader,它会将这些开发人员写的条例清晰的代码编译成 React.createElement(...) 形式的代码。早些年间会使用 jsx-loader,但是近几年它被 babel-loader 取代了,而 babel-loader 被 webpack 内置了,所以 React 的开发者不需要安装任何东西。那这个玩意怎么使用呢?
2、如何引入 babel
1.1、通过 BootCND 引入 babel:
引入 babel.min.js 后,需要在每次写 JavaScript 时把 <script>改成<script type="text/babel'">,babel 会自动将 babel 类型的代码进行转译(可以理解为翻译),下面我们结合上 babel 重新实现 +1 的小应用。
<div id="root"></div>
<script src="https://cdn.bootcss.com/react/16.10.2/umd/react.development.js"></script>
<script src="https://cdn.bootcss.com/react-dom/16.10.2/umd/react-dom.development.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
<script type="text/babel"> //babel.js回去翻译这段babel代码,对其解析成js并塞入script对babel标签进行替换
let num = 0;
const App = () => ( //App 必须是一个函数,不然手动刷新视图会出问题
<div className="red"> //不需要 React.createElement('div', {className: 'red'}, [n, React.createElement()])
{n} //变量使用 {} 包裹起来即可
<button
onClick={() => {
num += 1;
render(); //变量改变后,需要手动刷新视图
}}
>
+1
</button>
</div>
);
const render = () => ReactDOM.render(<App />, document.querySelector("#root"));
render(); //这里的 <App /> 和 App()类似,现在就可以通过组件的形式对其进行调用了
</script>
结合上 babel-loader 之后代码简介了不少,所有的标签都可以用 html 标签写,如果你需要插入 js 变量或函数,就用 {} 包裹起来,相比之前创建便签需要使用 React.createElement() 的方式简单太多了。现在和 Vue 相比起来好像还简单了不少,因为所有的东西都是 JavaScript 原有的,而 Vue 要实现变量还需要 data 属性,实现点击函数还需要 v-on 指令。
但是这种 BootCDN 的方式不太推荐,这是忠告。永远不要再生产环境使用这种 BootCDN 的方式,因为效率太低了,而且它要在用户的机器上下载一个 babel.min.js,它还要在浏览器端把 JSX 翻译成 JS,为什么不在 build 的时候做呢?
1.2、使用 create-react-app 的方式
这个 React 的 create-react-app 命令行和 Vue 的 VueCLI 是同一性质的东西,安装及创建项目的方式如下:
yarn global add create-react-app //或者npm,由于内容比较大推荐使用 yarn
create-react-app ProjectName //类似于 Vue 的 vue create ProjectName
//创建完成之后可以到项目目录中运行 yarn start 命令,可以看到 React 的网页就说明项目创建成功了
通过 create-react-app 创建的项目目录可能会比较多,为了方便学习可以将 index.js 之外的文件都删掉:
<div id="root"></div> //index.html
//App.js
import React from 'react'
const App = () => { //虽然是js文件,但却可以写babel代码
return (
<div>App组件</div> //babel语法内其实还是调用了React.createElement(),所以需要引入React
)
}
export default App
//index.js 文件
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.js'
ReactDOM.render(<App />, document.getElementById('root')); //yarn start 可看到 hi 页面
上述代码我们可以注意到,在 App.js 文件中写的确实 babel 的代码,这是因为 webpack 让 JS 默认走 babel-loader。
- className 属性。在创建组件的过程中,如果一个标签有 class 属性,则需要写 className="red" 代码,原因是我们写的 jsx 语法最终需要被 bebel-loader 转义成 js,js 中的代码是通过 React.createElement('div', {className:'red'}, [n]) 的方式创建组件的。
- 插入变量。标签里面的所有 JS 代码都要用 { } 包裹起来.,如果你需要变量 n,那么就用 { } 把 n 包起来,如果你需要对象,那么就要用 { } 把对象包起来,如 { {name:'erha'} }。
- 在创建组件的过程中,内部需要 return 时,一定在 return 后面加上 () 。
3、现在和 Vue 进行对比
Vue 非完整版有 v-loader 的帮助,可以将 html 转义成 render 函数,而 React 有了 babel-loader 的帮助,也可以在 js 文件中写 html 标签了,现在看来二者在开发的便捷性上不相上下。比如我们可以通过一个 if-else 的例子来分析一下:
//Vue
<template>
<div>
<div v-if="n%2===0">n是偶数</div>
<span v-else>n是奇数</span>
</div>
</template>
//React
const Component = () => {
return ( //这个括号千万不能丢了
<div>
{ n%2===0 ? <div>n是偶数</div> : <span>n是奇数</span> } //js 语法用 {} 包裹
</div>
)
}
//React
const Component = () => {
const inner = n%2===0 ? <div>n是偶数</div> : <span>n是奇数</span>
return (
<div>
{ inner } //由此可见,React更加灵活,只要是 js代码,怎么写都可以
</div>
)
}
结论:Vue:只能用 Vue 提供的 v-if/v-else 语法写条件判断,但是条例会非常清晰。React:只要是 JavaScript 代码,想怎么写就怎么写,非常灵活,但是条例可能不如 Vue 清晰。再比如循环语句在两种框架中的写法对比:
//在Vue里可以遍历数组和对象
<template>
<div>
<div v-for="(n, index) in numbers" :key="index">
下标{{index}},值为{{n}}
</div>
</div>
</template>
//React
const Component =(props) => {
return (
<div>
{ props.numbers.map((n,index) => {return <div>下标{index} 值为{n} )}
</div>
)
</div>)