Castie!

正态分布, 优劣伴生

北冥有鱼,其名为鲲(kūn)。鲲之大,不知其几千里也;化而为鸟,其名为鹏。鹏之背,不知其几千里也;怒而飞,其翼若垂天之云。是鸟也,海运则将徙于南冥。南冥者,天池也。


北海若曰:“井鼃不可以语于海者,拘于虚也;夏虫不可以语于冰者,笃于时也;曲士不可以语于道者,束于教也。今尔出于崖涘,观于大海,乃知尔丑,尔将可与语大理矣。

Web 将项目快速迁移至React

最近在学习前端方面的知识, 粗浅的将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:

点击下方链接跳转!!

🌟 项目源码 请点这里🌟 »> 喜欢的朋友请点喜欢 »> 下载源码的同学请送下小星星 »> 有闲钱的壕们可以进行打赏 »> 小弟会尽快推出更好的文章和大家分享 »> 你的激励就是我的动力!!

最近的文章

Web PC项目快速适配移动端

昨天我们快速的将Vue的项目快速迁移到了React上来, 经过学习两个不同的框架发现, React更加适合复杂的需求以及更加适合我们这种移动端开发者的思维习惯.参考链接: Web 是时候用前端写个简历了! Web 前端项目要从基本布局开始 Web 简历一定要设计的美美的 Web 使用Vue代替陈旧的jQuery Web Vue项目速转.htm静态网页 Web 将项目快速迁移至React以下内容在上述文章基础上进行, 请事先查阅.在着手移动端之前, 我们先给之前的导航栏点击按...…

前端开发继续阅读
更早的文章

Web 使用webpack构建前端项目

好久没写技术博客了, 原因在于最近在学习前端方面的技术, 熟悉我的同学都知道, 之前我有使用Vue搭建了一个个人简历, 体验了一把最新的前端技术, 但之前我们使用的是vue-cli脚手架工具, 对于如何自己实现前端构建工具, 当下最为流行的就是webpack和gulp了, 之前一篇我们讲了gulp, 这一篇我们来好好讨论webpack.说起webpack, 想必做前端的同学肯定不会陌生, 其实之前我们使用gulp构建的时候, 也使用了webpack的打包技术, 其实gulp和webpa...…

前端开发继续阅读