最近在学习前端方面的知识, 粗浅的将webpack和gulp的文档翻阅了一遍, 虽然之前有使用过Vue的经验, 但是就社区来说, 现在的主流还是React, 所以我也不免俗的进行学习, 为以后React Native的hybird架构的建设打好基础.
参考链接:
以下内容在上述文章基础上进行, 请事先查阅.
说到React, 最常听说的就是函数式编程, 和Vue推崇的模板有很大的差异, 这也是我们需要换个视角来研究的东西. 说道学习, 光是理论上的讲解真的不是我的学习方式, 说真的也学不进去, 所以我们还是通过实战来进行学习吧.
我们之前有通过Vue搭建的一个个人简历的页面, 为了学习使用React, 我们就将之前的Vue项目迁移到React上来, 并在迁移的途中看看如何来使用React.
create-react-app
首先我们需要一个先搭建一个开发环境, 上篇我们通过webpack搭建了一个最基础的开发环境, 但没有优化的webpack, 速度是很不理想的, 所以我们就直接使用facebook官方的脚手架create-react-app
来进行项目的环境搭建.
首先我们来看下文档 –> 官方文档
Quick Overview
npm install -g create-react-app
create-react-app my-app
cd my-app/
npm start
Then open http://localhost:3000/ to see your app.
When you’re ready to deploy to production, create a minified bundle with npm run build.
非常简单的终端命令后, 脚手架工具就帮我们搭建好了开发环境.
package.json
{
"name": "react-resume",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^15.6.2",
"react-dom": "^15.6.2"
"react-scripts": "1.0.13"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
但是我们在脚手架生成的项目中看不到webpack的配置…
react
不管了, 我们先进行开发起来, 我们先将Index骨架给搭好吧. 我们先来看看之前的Vue的写法, 并进行可选的复制.
Index.vue
<template>
<div>
<navigation></navigation>
<div class="odd">
<div class="content">
<home></home>
</div>
</div>
<div class="even">
<div class="content">
<projects></projects>
</div>
</div>
<div class="odd">
<div class="content">
<github></github>
</div>
</div>
<div class="articles">
<div class="content">
<articles></articles>
</div>
</div>
<div class="odd">
<div class="content">
<experience></experience>
</div>
</div>
<div class="contact">
<div class="content">
<contact></contact>
</div>
</div>
</div>
</template>
<script>
import navigation from './navigation'
import home from './home'
import projects from './projects'
import github from './github'
import articles from './articles'
import experience from './experience'
import contact from './contact'
export default {
data() {
return {
}
},
components: {
navigation,
home,
projects,
github,
articles,
experience,
contact
}
}
</script>
<style scoped>
.even {
width: 100%;
height: 600px;
background-color: #fafafa;
}
.odd {
width: 100%;
height: 600px;
background-color: #fff;
}
.articles {
width: 100%;
height: 1130px;
background-color: #fafafa;
}
.contact {
width: 100%;
height: 320px;
background-color: #fafafa;
}
.content {
margin: 0 auto;
width: 1000px;
height: inherit;
}
</style>
对应Vue, React我们生成Index.js及Index.css
Index.css
.even {
width: 100%;
height: 600px;
background-color: #fafafa;
}
.odd {
width: 100%;
height: 600px;
background-color: #fff;
}
.articles {
width: 100%;
height: 1130px;
background-color: #fafafa;
}
.contact {
width: 100%;
height: 320px;
background-color: #fafafa;
}
.content {
margin: 0 auto;
width: 1000px;
height: inherit;
}
Index.css仅仅是将vue中的css给抽取出来了而已, 我们再来看Index.js.
Index.js
import React, {Component} from 'react';
import CSSModules from 'react-css-modules';
import styles from './pc_Index.css';
import PCNavigation from './pc_navigation';
import PCHome from './pc_home';
import PCProducts from './pc_projects';
import PCGithub from './pc_github';
import PCArticles from './pc_articles';
import PCExperience from './pc_experience';
import PCContact from './pc_contact';
export default class PCIndex extends Component {
render() {
return (
<div>
<PCNavigation/>
<div className={styles.odd}>
<div className={styles.content}>
<PCHome/>
</div>
</div>
<div className={styles.even}>
<div className={styles.content}>
<PCProducts/>
</div>
</div>
<div className={styles.odd}>
<div className={styles.content}>
<PCGithub/>
</div>
</div>
<div className={styles.articles}>
<div className={styles.content}>
<PCArticles/>
</div>
</div>
<div className={styles.odd}>
<div className={styles.content}>
<PCExperience/>
</div>
</div>
<div className={styles.contact}>
<div className={styles.content}>
<PCContact/>
</div>
</div>
</div>
)
}
}
Index.js 我们通过模块化注入的方式进行, 但是我们发现这个模块化有问题啊, 还是造成了全局污染, 这时我们想到要去看看webpack的配置了, 可是项目中并没有webpack… 那怎么办… 一度陷入僵局, 我们再到脚手架工具的文档上看看吧…
借助文档
Limitations
Some features are currently not supported:
Server rendering.
Some experimental syntax extensions (e.g. decorators).
CSS Modules (see #2285).
Importing LESS or Sass directly (but you still can use them).
Hot reloading of components.
Some of them might get added in the future if they are stable, are useful to majority of React apps, don’t conflict with existing tools, and don’t introduce additional configuration.
找啊找, 我们居然看到居然不支持CSS Modules
, 尼玛是在逗我? 这个有那么难支持咩…
Philosophy
One Dependency: There is just one build dependency. It uses Webpack, Babel, ESLint, and other amazing projects, but provides a cohesive curated experience on top of them.
No Configuration Required: You don't need to configure anything. Reasonably good configuration of both development and production builds is handled for you so you can focus on writing code.
No Lock-In: You can “eject” to a custom setup at any time. Run a single command, and all the configuration and build dependencies will be moved directly into your project, so you can pick up right where you left off.
然后我们看到了这段, 最后一句, 你可以eject
, 并自定义配置, 但官方不推荐这样做… 你都完不成我想要的功能, 我还管你推不推荐… 幼稚…
npm run eject
好了, 我看到了一个config文件夹, 终于我们可以进行webpack的配置了,那我们应该如何配置呢?? 我们去看下react-css-modules
的文档.
webpack css-loader
CSS Modules is a specification that can be implemented in multiple ways. react-css-modules leverages the existing CSS Modules implementation webpack css-loader.
需要借助css-loader
, 我们再到css.loader中看看吧.. –> 文档
webpack.config.js
{
test: /\.css$/,
use: [
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
}
}
]
}
终于找到配置项了, 我们也到我们的webpack进行配置… 配置完成后, 总算模块化的事情算是告一段落了… 前端查文档真心麻烦… 文档都是散的… 坑啊~~
CSSModules
虽然搞定了css模块化, 但是这样的注入真的是蛋疼啊… 有没有什么更好的方法呢… 我们回到react-css-modules
的文档.
import React from 'react';
import styles from './table.css';
export default class Table extends React.Component {
render () {
return <div className={styles.table}>
<div className={styles.row}>
<div className={styles.cell}>A0</div>
<div className={styles.cell}>B0</div>
</div>
</div>;
}
}
我们目前使用的是这种方法, 注入的非常蛋疼….
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';
class Table extends React.Component {
render () {
return <div styleName='table'>
<div styleName='row'>
<div styleName='cell'>A0</div>
<div styleName='cell'>B0</div>
</div>
</div>;
}
}
export default CSSModules(Table, styles);
往下找, 然后我们就找到了这种优雅的方法, 可以直接使用css的字符串引入, 这个达到了我们的要求! 拍手👏.
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';
@CSSModules(styles)
export default class extends React.Component {
render () {
return <div styleName='table'>
<div styleName='row'>
<div styleName='cell'>A0</div>
<div styleName='cell'>B0</div>
</div>
</div>;
}
}
不知疲倦的我又往下翻查, 找到了这个更加优雅的方法, 使用decorator
, 这是ES7的语法, 想要使用我们需要加babel-plugin-transform-decorators-legacy
这个插件.
npm i babel-plugin-transform-decorators-legacy --save
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
"plugins":["transform-decorators-legacy"]
},
},
我们安装完成后到webpack中配置一下, 就可以用啦.
Index.js
import React, {Component} from 'react';
import CSSModules from 'react-css-modules';
import styles from './pc_Index.css';
import PCNavigation from './pc_navigation';
import PCHome from './pc_home';
import PCProducts from './pc_projects';
import PCGithub from './pc_github';
import PCArticles from './pc_articles';
import PCExperience from './pc_experience';
import PCContact from './pc_contact';
@CSSModules(styles)
export default class PCIndex extends Component {
render() {
return (
<div>
<PCNavigation/>
<div styleName="odd">
<div styleName="content">
<PCHome/>
</div>
</div>
<div styleName="even">
<div styleName="content">
<PCProducts/>
</div>
</div>
<div styleName="odd">
<div styleName="content">
<PCGithub/>
</div>
</div>
<div styleName="articles">
<div styleName="content">
<PCArticles/>
</div>
</div>
<div styleName="odd">
<div styleName="content">
<PCExperience/>
</div>
</div>
<div styleName="contact">
<div styleName="content">
<PCContact/>
</div>
</div>
</div>
)
}
}
这样我么就非常优雅的完成了这个CSS模块化的问题了, 还是花了些功夫.
但是我们如何进行一个dom绑定多个样式呢??
@CSSModules(styles, {allowMultiple: true})
多加一个参数即可, 虽然文档不是很推荐, 但是用户需求大于天不是吗…
迁移
搞定了上面最麻烦的CSS模块化后, 我们的迁移也变得顺风顺水, 基本没有遇到什么问题, 会使用Vue的同学迁移到React上也不是什么难事.
Vue
<template>
<div class="column">
<div class="column-block">
<div class="column-list">
<div class="row" v-for="article in articles">
<a :href="article.href"></a>
</div>
</div>
<div class="column-title">
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
}
},
props: {
articles: Array,
name: String
}
}
</script>
React
import React, {Component} from 'react';
import CSSModules from 'react-css-modules';
import styles from './pc_column.css';
@CSSModules(styles)
export default class PCColumn extends Component {
render() {
const rows = this.props.articles.map((article, index) => (
<div styleName="row" key={index}>
<a href={article.href}>{article.name}</a>
</div>
))
return (
<div styleName="column">
<div styleName="column-block">
<div styleName="column-list">
{rows}
</div>
<div styleName="column-title">
{this.props.name}
</div>
</div>
</div>
)
}
}
特意找了个明显有差异的对比, 我们能够看到Vue的重心在模板的渲染, 使用v-for这种语法糖. 而React是比较适合我们平时的编程习惯的, 也就是代码注入.
展示
整个迁移的过程比较顺畅, 原因之一也是页面相对简单, 学习到的东西是CSSModules这块的配置问题, 解决了这个问题后, 迁移也就变得非常容易了.
但是作为前端小白来说, 这仅仅是对于前端项目的浅显的学习, 要学习的东西还很多, 继续加油吧.
About:
🌟 项目源码 请点这里🌟 »> 喜欢的朋友请点喜欢 »> 下载源码的同学请送下小星星 »> 有闲钱的壕们可以进行打赏 »> 小弟会尽快推出更好的文章和大家分享 »> 你的激励就是我的动力!!