react

在react学习中,需要安装两个包react@16.1.1 react-dom@16.1.1

react这个包是专门用来创建react组件、组件生命周期等等
react-dom里面主要封装了和DOM操作相关的包

cnpm i react@15.6.2 react-dom@15.6.2 -S

reactjs

在react中,不能直接像vue中手写HTML元素
https://reactjs.org 概述:一个javascript库、构建用户界面的
核心库只关注视图层

简介

react起源于Facebook的内部项目(Instagram)

React的核心思想:组件化(封装组件,复用组件)

声明式语法-----只需要知道怎么使用即可,不需要知道内部如何实现的

learn once write anywhere
学完ReactJs之后,可以使用基于ReactJs语法的ReactNative去做Android/ios开发

  • React简介
  1. React简介
    ●React起源于Facebook的内部项目,因为该公司对市场上所有JavaScript MVC框架。都不满意,就决定自
    己写一套,用来架设Instagram (照片交友)的网站。做出来以后,发现这东西很好用,就在2013年5月开
    源了,
    I
    ●Angular1 2009年谷歌MVC不支持组件化开发
    ●由于React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单,所以,越来越多的人开
    始关注和使用,认为它可能是将来Web开发的主流工具,
    ●清楚两个概念:
    。library (库) :小而巧的库,只提供了特定的API;优点就是船小好掉头,可以很方便的从-个库切换到
    另外的库:但是代码几乎不会改变;
    。Framework (框架) :大而全的是框架;框架提供了一整套的解决方案:所以,如果在项目中间,想切换
    到另外的框架,是比较困难的:

如何搭建ReactJs的开发环境

方案1:借助于命令行的方式
//安装工具create-react-app
npm install -g create-react-app
//创建一个my-app的基于ReactJs的项目
create-react-app my-app
//进入my-app目录
cd my-app/
//启动开发服务器
npm start
方案2:直接在普通的项目中,引入对应的文件:
引入了3个文件:
react.js-----核心文件
react-dom.js-----处理与DOM操作
browser.min.js----支持jsx语法

  • 创建一个组件
    是一个用来渲染视图的类,视图是可被反复使用的,带有特定功能
    var MyComponent = React.createClass({
    render: function () {
    return ;
    }
    });
    组件命名首字母大写
  • 复合组件
    在React中,并不是新的概念,其实是一个组件,只不过组件中包含其他的组件
  • awesome react
    参考:https://github.com/brillout/awesome-react-components

前端三大主流框架(Framework)

1.Angular.js:最早前端框架、
2.React.js:最流行的一门框架、设计优秀
3.Vue.js:最火的一门前端框架

react和vue.js都是基于组件化开发

  • Vue.js组件化方式
    通过.vue组件模板文件(浏览器不识别,需要编译成真正的组件)
    1.templateUI结构
    2.script业务逻辑和数据
    3.styleUI样式
  • 在vue中,有v-model指令来实现双向数据绑定
  • vue路由
    var router = new VueRouter({
    routes: [
    {path: ‘’, component: ‘’}
    ]
    });
  • router-link
  • router-view

模块化

从代码的角度分析问题,把业务逻辑分割到不同的模块中进行开发,方便代码的重用

组件化components

从UI的角度分析问题,把页面拆分多个小组件,随着我们的项目开发,组件会越来越多,能够方便我们快速得到一个完整的页面、方便UI元素组件的重用(组件是元素的集合体)

全部通过js实现组件化

好处:1.提高了代码的复用率
2.提高了代码的可读性、可维护性
3.提高了编码速度

  • 最基本的方式
    在react中,构造函数,就是一个最基本的组件
    function Hello() {
    return null;
    }
    function Hello() {
    return

123

  • react在解析所有标签的时候,是以标签的首字母来区分的,如果标签的首字母是小写,按照普通HTML标签来解析,如果首字母是大写,按照组件的方式去解析渲染
  • …对象----es6中的属性扩散,表示把对象的所有属性展开
  • function Hello(props) {}
    在组件中,如果想要使用外部传递过来的数据(只读),必须显示在构造函数参数列表中,定义props属性来接收;
    props.属性
  • 暴露组件export default Hello
    暴露组件的另一种方式:
    export default class Hello extends React.Component {
    constructor(props) {
    super(props);
this.state = {
        msg: "请输入您的身份信息",
        info: "湖北省"
    }
}
render() {
    return this.state.info;
}

}

export default function Hello(props) {
return props;
}

  • 另一种创建组件的方式通过es6的关键字class
  • class实现面向对象的新形式
    class Person {
    constructor(name, age) {
    this.name = name;
    this.age = age;
    }
    say() {
    console.log(“test”);
    }
    static info = ‘hello’;
    }
    class Chinese extends Person {
    constructor(color, language) {
    super(“老师”, 30);
    this.color = color;
    this.language = language;
    }
    }
    var p = new Person(“ls”, 28);
    var c = new Chinese(“red”, “韩语”);
    console.log©;
    c.say();
    console.log(Chinese.info);
  • 通过继承React.Component,使Hello成为一个组件
    class Hello extends React.Component {
    render() {
    return null;
    }
    }
    通过class实现组件,需要定义一个render函数(表示渲染哪些虚拟DOM元素并展示出来)
    class Hello extends React.Component {
    render() {
    return 123;
    }
    }
  • 在function定义组件中,如果需要使用props必须先定义,否则无法直接使用,但是,在class定义的组件中,可以直接使用this.props来直接访问
    class Hello extends React.Component {
    constructor(props) {
    super(props);
    }
    render() {
    return this.props.age;
    }
    }
  • this.state表示当前组件实例的私有数据对象
    class Hello extends React.Component {
    constructor(props) {
    super(props);
this.state = {
        msg: "请输入您的身份信息",
        info: "湖北省"
    }
}
render() {
    return this.props.age;
}

}

  • render() {
    /var arr = [];
    this.state.cmts.forEach(item => {
    arr.push(

{item.user}

  • );
    });/

return

{arr}

  • ;
    }

render() {
/var arr = [];
this.state.cmts.forEach(item => {
arr.push(

{item.user}

  • );
    });/
return <div>
        {this.state.cmts.map((item, i) => {
            return <div key={i}>

(唯一的key,必须定义,vue中通过:key="i"定义)

评论人:{item.user}


评论内容:{item.content}

  • ;
    })}
    ;
    }
  • 无状态组件和有状态组件的组合使用
    import React from ‘react’;
    function CommentItem(props) {
    return

评论人:{props.user}


评论内容:{props.content}

  • ;
    }

export default class CommentList extends React.Component {
constructor(props) {
super(props);

this.state = {
        cmts: [
            {user: '张三', content: '哈哈哈,沙发'},
            {user: '李四', content: '哈哈哈,板凳'},
            {user: '王五', content: '哈哈哈,凉席'},
            {user: '赵柳', content: '哈哈哈,砖头'},
            {user: '老王', content: '哈哈,楼下山炮'},
        ]
    }
}
render() {
    /*var arr = [];
    this.state.cmts.forEach(item => {
        arr.push(<h3>{item.user}</h3>);
    });*/

    return <div>
        {this.state.cmts.map((item, i) => {
            return <CommentItem key={i} user={item.user} content={item.content}></CommentItem>;或者
  	  return <CommentItem key={i} {...item}></CommentItem>;

        })}
    </div>;
}

}

  • 组件
    无状态组件—没有生命周期函数
    有状态组件----存在生命周期函数
  • 无状态组件
    没有this.state私有数据属性
    function Hello(props) {
    return props;
    }
  • 案例
    import React from ‘react’;
    export default function CommentItem(props) {
    return <div style={{border: ‘1px solid #ccc’, margin: ‘10px 0’, paddingLeft: 15}}>
    <h3 style={{color: ‘purple’, fontSize: 16}}>评论人:{props.user}
    <p style={{color: ‘red’, fontSize: 14}}>评论内容:{props.content}
    ;
    }
  • 有状态组件
    存在this.state私有数据属性,可读可写
    class Hello extends React.Component {
    constructor(props) {
    super(props);
    this.state = {

    }
    }
    render() {
    return this.state;
    }
    }

refs

通过ref找到真实的DOM节点

console.log(this.refs.input.value);

组件的本质就是视图

核心思想:封装组件、复用组件

props----属性

property

this.props.myname

props is immutable(不变的)

  • 属性传值
    var MyHeader = React.createClass({
    render() {
    return

{ this.props.myTitle }

  • ;
    }
    });
ReactDOM.render(
     <div>
        <MyHeader myTitle="hello"></MyHeader>
        <MyHeader myTitle="welcome"></MyHeader>
     </div>, document.querySelector('#app'));
  • 单向数据流
  • children属性
    this.props.children
    var myList = React.createClass({
    render() {
    return
  • { React.Children.map(this.props.Children, (child) => {
    return child;
    }) }
  • ;
    }
    });
ReactDOM.render(
    <div>
        <myList>
            <li>1</li>
            <li>2</li>
        </myList>
    </div>, document.querySelector('#app'));

父子组件传递属性和方法

<MyButton btnName=“注册” myClick={ this.handleRegister }>

调用方法:
return <input type=“button” value={ this.props.btnName } onClick={ this.props.myClick } />;

  • 子组件传参给父组件
    myClick() {
    this.props.myClick(‘张三’);
    },

借助于单向数据流

减少了业务的复杂度,降低了代码的维护成本

babel

是一个js的编译器,可以支持将typescript\es6\jsx, 转换为当前浏览器所支持的普通的js

虚拟DOM(Virtual Document Object Model)

VDOM
通过js实现模拟DOM
var p = {
tagName: ‘p’,
children: [
var p = {
‘p标签’
]
}

react内部已经为我们实现了虚拟DOM
虚拟DOM就是一种数据结构,由组件构成

  • 减少操作DOM的次数
    目的:为了实现页面中,DOM元素的高效更新
  • 什么是React中的虚拟DOM
    框架中的概念,是程序员用js对象来模拟页面上的DOM和DOM嵌套;
  • DOM的本质
    浏览器中的概念,用js对象来表示页面上的元素,并提供了操作DOM对象的API;

state

状态:在React中,任何会变化的数据,都要保存在状态中。

React支持将状态中的值动态绑定到视图:
React是可以将状态中的值绑定到视图,当状态中的值发生变化的时候,react框架会检测到这一变化,然后在合适的时间经过DOM diff算法,采用最优的效率来更新真实的DOM

  • 基本操作
    1.初始化
    getInitialState() {
    return {
    count: 0
    };
    }
    2.写状态(异步操作)
    this.setState({ count: 1 }, func);
    3.读状态
    this.state.count

lifecycle

生命周期
在React中,组件的分为3个阶段:mount、update、unmount

表单

  • 受控表单元素
    值不可改变
  • 非受控表单元素
  • defaultValue的使用
    存在默认值,可修改、添加值

<h1 style={{ opacity: 0.5 }}>

todoslist

参考:http://todomvc.com/

Diff算法

tree diff
component diff
element diff
DOM diff都是交给React框架处理

JSX语法

能够让我们在js文件中书写类似于html那样的代码、快速定义虚拟DOM结构(符合XML规范的JS语法)

cnpm i babel-preset-react@6.24.1 -D(开发环境中需要用到)

导包:
import React from ‘react’;
import ReactDOM from ‘react-dom’;

【“env”, “stage-0”, “react”】
{ 变量名 }

  • javascriptXML
    JavaScriptXML并不是一种新的语法,只不过是支持在js中编写HTML标记而已,reactJS在渲染元素时,是不允许直接返回多个要渲染的元素,要统一放在一个容器中,支持js运算的通过花括号{}的语法执行js运算
  • ReactDOM.render()
    //向指定的容器渲染元素
  • jsx语法要求只能有一个根元素
  • React.createElement(‘div’, {title: ‘this is a div’, id: ‘mydiv’}, ‘div元素’)至少接收三个参数
    var mydiv = React.createElement(‘div’, {title: ‘div的title属性----div’, id: ‘mydiv’}, ‘这是一个div’);
    var myH1 = React.createElement(‘h1’, null, ‘这是一个h1’);
    等价于:
    var myH1 = React.createElement(‘h1’, {}, ‘这是一个h1’);
  • ReactDOM.render(‘需要渲染的DOM元素’, ‘要渲染到页面上的哪个位置中’)
    ReactDOM.render(mydiv, document.getElementsByClassName(‘info’)[0]);
  • 在{}内部、可以书写符合js规范的代码、在jsx中,添加class属性必须写成className、为label标签添加for属性写成htmlFor
    key = {i}
  • 在jsx语法中,如果需要使用style属性,为jsx语法创建DOM元素,设置样式,不能像网页中那么写样式,而是使用js语法来写样式
    style样式规则:如果属性值单位是px,可以省略
    import React from ‘react’;
    export default function CommentItem(props) {
    return <div style={{border: ‘1px solid #ccc’, margin: ‘10px 0’, paddingLeft: ‘15px’}}>(外层{}表示要写js代码了,内层{}表示用一个js对象表示样式)

评论人:{props.user}


评论内容:{props.content}

  • ;
    }
  • 样式优化
  • 方式一
    import React from ‘react’;
    const divStyle = {border: ‘1px solid #ccc’, margin: ‘10px 0’, paddingLeft: 15};
    export default function CommentItem(props) {
    return
    <h3 style={{color: ‘purple’, fontSize: 16}}>评论人:{props.user}
    <p style={{color: ‘red’, fontSize: 14}}>评论内容:{props.content}
    ;
    }
  • 方式二
    import React from ‘react’;
    const inlineStyle = {
    divStyle: {margin: ‘10px 0’, paddingLeft: 15, border: ‘1px solid #ccc’},
    h3Style: {color: ‘purple’, fontSize: 16},
    pStyle: {color: ‘red’, fontSize: 14}
    };
    export default function CommentItem(props) {
    return

评论人:{props.user}


评论内容:{props.content}

  • ;
    }
  • 像input这样的单标签必须要闭合—“ / ”
  • 组件名称大写–切记

react项目的创建

1.运行cnpm i react react-dom -S安装包
2.导入相关包
3.创建虚拟DOM节点
4.渲染到页面

CSS模块化

1)import commentItem from ‘…/…/css/commentItem.css’;
2) {test: /.css$/, use: [‘style-loader’, ‘css-loader?modules’]},
(通过给css-loader添加参数modules,为css开启模块化)

css开启模块化之前,commentItem是个空对象,启用css模块化之后,所有类名都是私有的,如果想要把类名设置成全局的类,通过:global()包裹
:global(.box) {
color: red;
font-weight: 200;
text-align: center;
}

  • 让命名更符合规范
    1) {test: /.css$/, use: [‘style-loader’, ‘css-loader?modules&localIdentName=[name]_[local]-[hash:5]’]},
    (参数localIdentName–随机生成的class名称,name—css文件名称,local—文件内选择器的名称,hash–32位哈希码)
  • react组件内部的样式没有私有作用域
    通过webpack—css-loader可以让react组件内部样式具有私有作用域

组件的生命周期

“dependencies”: {
“jquery”: “^3.2.1”,
“prop-types”: “^15.6.0”,
“react”: “^16.1.1”,
“react-dom”: “^16.1.1”
},

https://github.com/brillout/awesome-react-components

  • 概念
    在组件创建、到加载到页面上运行、以及组件被销毁的过程中,总是伴随着各种各样的事件,这些在组件特定时期,触发的事件,统称为组件的生命周期
  • 组件生命周期分为三部分
    1)组件创建阶段(执行一次)
    componentWillMount、render、componentDidMount
    2)组件运行阶段
    componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate
    3)组件销毁阶段
    componentWillUnmount、
  • 使用defaultProps设置组件的默认值
    在react中,使用静态的defaultProps属性,来设置组件的默认属性值
    import React from ‘react’;
    export default class Counter extends React.Component {
    constructor(props) {
    super(props);
this.state = {
        
    }
}

static defaultProps = {
    initCount: 0
}

render() {
    return <div>
       <h1>这是count计数器</h1>
       <input type="button" value='+1'/>
       <hr/>
       <h3>当前的数量是:{this.props.initCount}</h3>
    </div>;
}

}

  • 使用propTypes做类型校验
    1.需要安装prop-types第三方包
    cnpm i prop-types@15.6.0 -S
    在v.15.*之前这个包还没有从react分离
    import PropTypes from ‘prop-types’;
    static propTypes = {
    initCount: PropTypes.number
    }
  • 介绍componentWillMount(UNSAFE_componentWillMount, 这是新的名称)函数
    componentWillMount() {
    this.myselfFunction();
    }
    render() {
    return

这是count计数器


当前的数量是:{this.props.initCount}

  • ;
    }
myselfFunction() {
    console.log("这是我自定义的函数");
}
  • 这个函数等同于vue中的created生命周期函数
  • 组件创建阶段的render函数
    将虚拟DOM渲染到内存中
  • 介绍componentDidMount函数
    虚拟DOM从内存渲染到页面
    componentDidMount() {
    console.log(document.querySelector(’#h3’));
    }
  • 这个函数等同于vue中的mounted生命周期函数
  • 改变this.state内的值
    btn.addEventListener(‘click’, () => {
    this.setState({
    count: this.state.count + 1
    });
    });
    箭头函数可以避免使用.bind(this);方法
    increment = () => {
    this.setState({
    count: this.state.count + 1
    });
    }
  • 使用react提供的事件绑定机制
  • 组件shouldComponentUpdate(nextProps, nextState) {}是否需要更新
    1.必须返回一个布尔值
    return false;
    2.false—不会继续执行生命周期函数,退回到运行状态,页面不会更新,但组件state会更新
    shouldComponentUpdate(nextProps, nextState) {(nextState是state最新的值,nextProps是初始值)
    return nextState.count % 2 === 0 ? true : false;
    }
  • 组件componentWillUpdate(UNSAFE_componentWillUpdate, 这是新名称)
    此时虚拟DOM和页面都是旧的
    react-----ref用法:

当前的数量是:{this.state.count}

componentWillUpdate() {
console.log(this.refs.h3.innerHTML);
}

componentWillUpdate() {
console.log(this.refs.h3.innerText);
}

  • componentDidUpdate
    componentDidUpdate(prevProps, prevState);
  • 介绍componentWillReceiveProps(UNSAFE_componentWillReceiveProps, 这是新名称)
    componentWillReceiveProps(nextProps) {
    console.log(this.props.pmsg, nextProps.pmsg);//这是父组件中的msg消息 点击测试
    (nextProps.pmsg是最新的消息)
    }

扩展

context特性
getChildContextTypes
前三个,后三个,后两个
一个方法、两个静态属性
----组件参数传递

父组件共享context对象:
getChildContext() {
return {
color: this.state.color
};
}

static childContextTypes = {
    color: PropsTypes.string
}

子孙组件只需:
render() {
return



<h5 style={{color: this.context.color}}>这是孙组件

;


}

static contextTypes = {
    color: PropsTypes.string
}

react-router-dom路由的基本使用

https://reacttraining.com/react-router/ 参考网站:其中网站选择web、手机APP选择native

cnpm i react-router-dom@5.0.1 -S

import React from ‘react’;
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from “react-router-dom”;
import Home from ‘./component/Home.jsx’;
import Movie from ‘./component/Movie.jsx’;
import About from ‘./component/About.jsx’;

export default class App extends React.Component {
constructor(props) {
super(props);

this.state = {

    }
}

render() {
    return <Router>
        <div>
            <h1>这是网站的APP根组件</h1>
            <hr/>
            <Link to="/home">首页</Link>  
            <Link to="/movie">电影</Link>  
            <Link to="/about">关于</Link>
            <hr/>
            <Switch>
                <Route path="/home">
                    <Home></Home>
                </Route>
                <Route path="/movie">
                    <Movie></Movie>
                </Route>
                <Route path="/about">
                    <About></About>
                </Route>
            </Switch>
        </div>
    </Router>;
}

}

  • HashRouter
    表示一个路由的根容器,所有路由有关的都包裹在该容器里面,一个网站使用一次HashRouter
    import React from ‘react’;
    import {
    HashRouter,
    Route,
    Link
    } from ‘react-router-dom’;
    import Home from ‘./component/Home.jsx’;
    import Movie from ‘./component/Movie.jsx’;
    import About from ‘./component/About.jsx’;
    export default class App extends React.Component {
    constructor(props) {
    super(props);
this.state = {

    }
}

render() {
    return <HashRouter>
        <div>
            <h1>这是网站的APP根组件</h1>
            <hr/>
            <Link to="/home">首页</Link>  
            <Link to="/movie">电影</Link>  
            <Link to="/about">关于</Link>
            <hr/>
            <Route path="/home" component={Home}></Route>
            <Route path="/movie" component={Movie}></Route>
            <Route path="/about" component={About}></Route>
        </div>
    </HashRouter>;
}

}

  • Route
    表示一个路由规则,
    属性:path、component、exact
    (path表示要匹配的路由,component表示要展示的组件)
    Route具有两种身份,一个是路由匹配规则、另一个是占位符(组件)
  • 匹配路由参数
    默认匹配规则是模糊匹配
    exact---------精确匹配
    /:type/:id----------匹配参数
  • 获取参数
    Movie ------- {this.props.match.params.type} — {this.props.match.params.id}
    import React from ‘react’;
    export default class Movie extends React.Component {
    constructor(props) {
    super(props);
this.state = {
        routeParams: props.match.params
    }
}

render() {
    return <div>
        Movie ------- {this.state.routeParams.type} --- {this.state.routeParams.id}
    </div>;
}

}

  • Switch组件使用
    使用类似switch…case
  • Link
    表示一个路由的链接
    属性:to
<Link to="/home">首页</Link>

UI框架—AntDesign

AntDesign组件------antd
参考网站:https://ant.design/index-cn

cnpm i antd@2.13.10 -S

  • 一般,第三方UI插件,他们的样式表文件都是以.css结尾,建议对scss和less文件进行模块化
  • 按需导入
    1.cnpm i babel-plugin-import@1.6.2 -D
    2.在.babelrc:
    “plugins”: [“transform-runtime”, [“import”, {“libraryName”: “antd”, “style”: “css”}]]
    3.import {
    DatePicker
    } from ‘antd’;
    4.render() {
    return

这是网站的APP根组件

  • 首页  
    电影  
    关于







    ;
    }
  • import { Spin, Alert } from ‘antd’;-----加载组件
  • 评分组件
    import { Rate } from ‘antd’;
    <Rate disabled defaultValue={this.props.rating.average / 2}>
  • 分页组件
    import { Spin, Alert, Pagination } from ‘antd’;
    <Pagination onChange={ this.pageChanged } defaultCurrent={this.state.nowPage} pageSize={this.state.pageSize} total={this.state.total}>
  • 返回按钮组件

es6—fetch–API

用来获取数据
基于Promise封装的,存在跨域问题

fetch(“http://vue.studyit.io/api/getlunbo”, {mode: “no-cors”}).then(res => {
console.log(res);
});

fetchJsonp(“请求的url地址”)
.then(response => res.json() )
.then(data => console.log(data))
//注意: 第一个.then 中获取到的不是最终数据,而是一个中间的数据流对象;
// 注意: 第一个 .then 中获取到的数据, 是一个 Response 类型对象;
// 注意: 第二个 .then 中,获取到的才是真正的 数据;

  • Make JSONP request like window.fetch
    cnpm i fetch-jsonp -S ---------解决跨域问题
    import fetchJSONP from ‘fetch-jsonp’;

借助缓存–完成图片加载

getImages(_url) {
if (_url !== undefined) {
let _u = _url.substring(7);
return ‘https://images.weserv.nl/?url=’ + _u;
}
}

<img className="img" src={this.getImages(this.props.images.small)} alt=""/>

编程式导航

通过this.props.history.push(’/movie/’ + this.state.movieType + ‘/’ + page);

reactnative

在推出ReactNative之前,React ReactJS React.js都是指的是用来进行前端开发的一个框架

在推出ReactNative之后,React分为两大块,一个是ReactJs, 一个是ReactNative
react-native init mytest

采用React语法(jsx、component、refs、state、props)写android和iOS

参考:reactnative.cn
https://github.com/kunyashaw https://github.com/facebook/react-native

调用ReactNative所封装的组件,来编写移动端的原生应用程序

搭建开发环境

方式一:create-react-native-app
全局安装create-react-native-app
npm install -g create-react-native-app
创建一个基于react-native的模板项目,名称叫my-app
create-react-native-app my-app
切换到my-app目录
cd my-app
启动开发服务器
npm start

方式二:react-native-cli
npm install -g react-native-cli
创建一个模板项目
react-native init my-app
启动开发服务器(配置连接服务器)
cd my-app
react-native start

使用弹性布局Flexbox布局

1.flexdirection
2.align items

webpack打包工具

合并(减少二次请求)、压缩(提高加载速度)、精灵图(减少二次请求)、图片的base64编码(和html一起下载)

解决各个包之间的复杂依赖关系,是前端的一个项目构建工具,它是基于Node.js开发

webpack@3.8.1 要打包的文件路径 打包好的输出文件路径
npm run dev

全局安装npm i webpack -g

可以处理js文件之间的相互依赖关系

处理js兼容问题

webpack.config.js

//入口entry(要打包的文件路径)和出口output(打包好的文件路径)
const path = require(‘path’);

module.exports = {
entry: path.join(__dirname, ‘./src/main.js’),
output:{
path: path.join(__dirname, ‘./dist’),
filename: ‘bundle.js’//指定输出的文件的名称
}
}

执行webpack。。。进行打包

path.resolve();
mode: ‘’ 设置环境

使用webpack-dev-server(@2.9.3)这个工具,来实现自动打包编译的功能

运行npm i webpack-dev-server@2.9.3 -D安装

webpack-dev-server
cnpm i webpack@3.8.1 -D

2.9.4

常用命令

“dev”: “webpack-dev-server --open --port 3000 --contentBase src --hot”

=》npm run dev

–open(打开浏览器)
–port 3000(修改端口号)
–contentBase src(修改根路径为src)
–hot(无刷新重载,打补丁)
–host 192.168.1.1

在webpack中带s的都是数组

  • webpack-dev-server命令的另外一种使用方式
    在webpack.config.js中设置:
    devServer: {
    contentBase: ‘src’,
    open: true,
    port: 3000
    }

借助工具实现页面也加载到内存

1.cnpm i html-webpack-plugin -D

生成一个内存的页面、追加bundle.js

2.30.1

js默认只能打包处理js类型的文件,无法处理其他非js类型的文件

第三方loader加载器

cnpm i style-loader@0.19.0 css-loader@0.28.7 -D(处理打包css文件)

import ‘./css/index.css’;

module: {
rules: [
{test: /.css$/, use: [‘style-loader’, ‘css-loader’]}(调用顺序从右至左)
]
}

cnpm i less-loader@0 -D第三方loader加载器

cnpm i less@1.5 -D

import ‘./css/index.less’;

{test: /.less$/, use: [‘style-loader’, ‘css-loader’, ‘less-loader’]}

cnpm i sass-loader@6.0.6 -D第三方loader加载器scss文件

npm i node-sass@4.6.0 -D
cnpm i node-sass@4.* -D

webpack3.x的版本与webpack-dev-server3.x 的版本不兼容。

{
“name”: “webpack-senior”,
“version”: “1.0.0”,
“description”: “”,
“main”: “webpack.config.js”,
“scripts”: {
“test”: “echo “Error: no test specified” && exit 1”,
“dev”: “webpack-dev-server --open --port 3000 --hot”,
“pub”: “webpack --config webpack.pub.config.js”
},
“keywords”: [],
“author”: “”,
“license”: “ISC”,
“dependencies”: {
“antd”: “^2.13.10”,
“jquery”: “^3.2.1”,
“prop-types”: “^15.6.0”,
“react”: “^15.6.2”,
“react-dom”: “^15.6.2”,
“react-router-dom”: “^5.0.1”
},
“devDependencies”: {
“babel-core”: “^6.26.0”,
“babel-loader”: “^7.1.2”,
“babel-plugin-import”: “^1.6.2”,
“babel-plugin-transform-runtime”: “^6.23.0”,
“babel-preset-env”: “^1.6.1”,
“babel-preset-react”: “^6.24.1”,
“babel-preset-stage-0”: “^6.24.1”,
“clean-webpack-plugin”: “^0.1.17”,
“css-loader”: “^0.28.7”,
“extract-text-webpack-plugin”: “^3.0.2”,
“file-loader”: “^1.1.5”,
“html-webpack-plugin”: “^2.30.1”,
“node-sass”: “^4.6.0”,
“optimize-css-assets-webpack-plugin”: “^3.2.0”,
“sass-loader”: “^6.0.6”,
“style-loader”: “^0.19.0”,
“url-loader”: “^0.6.2”,
“webpack”: “^3.8.1”,
“webpack-dev-server”: “^2.9.4”
}
}

module: {

rules: [
        {test: /\.css$/, use: ['style-loader', 'css-loader']},
        {test: /\.(png|gif|bmp|jpg)$/, use: 'url-loader?limit=5000'},
        {test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader']},
        {test: /\.jsx?$/, use: 'babel-loader', exclude: /node_modules/}
    ]
}

默认情况下,webpack无法处理css文件中的url地址,通过第三方模块进行处理

cnpm i url-loader@0.6.2 file-loader@1.1.5 -D(url-loader包内部依赖于file-loader,所以不需要配置file-loader)

{test: /.(png|gif|bmp|jpg|jpeg)$/, use: ‘url-loader?limit=5000’&name=[hash:8]-[name].[ext]},(?后面传参,当图片大小大于等于极限limit时不会转成base64字符串编码,name=[hash:8]-[name].[ext]打包后的文件名和扩展名还是原来的,【hash:8】表示生成哈希码从32位中截取8位)

hash(32位哈希值)

{test: /.(png|gif|bmp|jpg|jpeg)$/, use: ‘url-loader?limit=4981&name=images/[hash:8]-[name].[ext]’},

处理字体url-loader

{test: /.(eot|svg|ttf|woff|woff2)$/, use: ‘url-loader’}

在webpack中,默认只能处理一部分es6的新语法,一些更高级的es6语法或者es7语法,webpack是处理不了的,这时候,就需要借助于第三方的loader,来帮助webpack处理这些高级的语法

1.第一套包:cnpm i babel-core@6.26.0 babel-loader@7.1.2 babel-plugin-transform-runtime@6.23.0 -D
2.第二套包:cnpm i babel-preset-env@1.6.1 babel-preset-stage-0@6.24.1 -D

然后打开webpack配置文件:
添加配置:
{test: /.jsx?$/, use: ‘babel-loader’, exclude: /node_modules/},
(exclude除了,为了webpack打包时,不处理node_modules里面的js文件)

在项目根目录新建一个.babelrc的Babel配置文件,这个配置文件,属于json格式(符合json语法规范、不能写注释、字符串使用双引号)内容如下:
{
“presets”: [“env”, “stage-0”, “react”],
“plugins”: [“transform-runtime”]
}(preset—语法,plugin–插件)

取消webpack的严格模式

cnpm i babel-plugin-transform-remove-strict-mode -D

通过babel-plugin-transform-remove-strict-mode来取消

在.babelrc中:
{
“plugins”: [“transform-remove-strict-mode”]
}

配置文件和发布配置文件

webpack.config.js
webpack.pub.config.js

“dev”: “webpack-dev-server --open --port 3000”,(测试)
“pub”: “webpack --config webpack.pub.config.js”(发布publish)

发布前自动删除dist目录借助clean-webpack-plugin插件

cnpm i clean-webpack-plugin@0.1.17 -D

plugins: [
new htmlWebpackPlugin({
template: path.join(__dirname, ‘./src/index.html’),
filename: ‘index.html’
}),
new cleanWebpackPlugin([‘dist’])
],(填写需要清除的文件夹)

分离第三方包

bundle.js中中存放自己的代码,第三方包的代码抽离出来
entry: {
app: path.join(__dirname, ‘./src/main.js’),
vendors: [‘jquery’]
(填写需要分离的第三方包名称)
},

new webpack.optimize.CommonsChunkPlugin({
name: ‘vendors’,
//分离的第三方包
filename: ‘vendors.js’
//第三方包打包后的名称
})

optimize(优化)

压缩js代码

new webpack.optimize.UglifyJsPlugin({
compress: {
压缩js选项
warnings: false
//移除警告
}
}),
new webpack.optimize.DedupePlugin({
‘process.env.NODE_ENV’: ‘“production”’
//生产环境
})

压缩HTML页面

参考:html-minifier-github
new htmlWebpackPlugin({
template: path.join(__dirname, ‘./src/index.html’),
filename: ‘index.html’,
minify: {
collapseWhitespace: true,
//清除多余的空格
removeComments: true,
//移除注释
removeAttributeQuotes: true
//移除属性上的双引号
}
}),

抽取css文件

cnpm i extract-text-webpack-plugin@3.0.2 -D
借助extract-text-webpack-plugin插件
参考网站:github.com/webpack-contrib/extract-text-webpack-plugin

{
test: /.css$/,
use: extractTextPlugin.extract({
fallback: ‘style-loader’,
use: ‘css-loader’,
publicPath: ‘…/’
(指定抽取css时,自动添加…/)
})
},

压缩css文件(抽取出来的css文件)

通过:cnpm i optimize-css-assets-webpack-plugin@3.2.0 -D

const optimizeCssAssetsPlugin = require(‘optimize-css-assets-webpack-plugin’);

new optimizeCssAssetsPlugin()

webpack相关项目文件复制问题

如果需要复制一个原有项目,不要复制node_modules,其他的都复制到新的项目文件夹,然后shift右键打开命令行窗口输入cnpm i即可,项目复制成功

React与vue的对比

组件化方面
1.什么是模块化:是从代码的角度来进行分析的;把-些可复用的代码,抽离为单个的模块;便于项目的维护和
开发;
2.什么是组件化:是从UI界面的角度来进行分析的;把一些可服用的UI元素,抽离为单独的组件;便于项目
的维护和开发;
3.组件化的好处:随着项目规模的增大,手里的组件越来越多;很方便就能把现有的组件,拼接为-个完墅的页
面;
4. Vue是如何实现组件化的:通过.vue 文件,来创建对应的组件;
。template结构
。script
行为
。style
样式
5. React如何实现组件化:大家注意,React中有组件化的概念,但是,并没有像vue这样的组件模板文件;
React中,一切都是以S来表现的:因此要学习React, JS要合格; ES6 和ES7 (async 和await)要会用:

XMind: ZEN - Trial Version