ES6的使用

ES6

块级作用域

使用 let 定义的变量在大括号的外面是访问不到的

常量const 常量一旦赋值就不能再修改了

注意const限制的是不能给变量重新赋值,而变量的值本身是可以改变的,下面的操作是可以的

模板字符串

let desc = `${name} is ${age} old!`;

剩余操作符

剩余操作符可以把其余的参数的值都放到一个叫b的数组里面

 let rest = function(a,...b){
 console.log(a,b);
}
 rest(1,2,3);    

箭头函数

箭头函数简化了函数的的定义方式,一般以 “=>” 操作符左边为输入的参数,而右边则是进行的操作以及返回的值inputs=>output

[1,2,3].forEach(val => console.log(val)););

输入参数如果多于一个要用()包起来,函数体如果有多条语句需要用{}包起来
箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。 正是因为它没有this,从而避免了this指向的问题。

Babel的操作指南

Babel是一个通用的多用途JavaScript编译器

npm install babel-cli -g  

把ES6编译成 ES5

安装依赖的预设

$ npm install --save-dev babel-preset-es2015

修改.babelrc

{
    "presets": ["es2015"]
}

$ babel es6.js  这将把编译后的结果直接输出至终端

$ babel es6.js -o es5.js  加上-o参数 可以将结果写入到指定的文件

$ babel src -d lib 把一个目录整个编译成一个新的目录

vue概述

vue介绍

vue.js 是用来构建web应用接口的一个库

技术上,Vue.js 重点集中在MVVM模式的ViewModel层,它连接视图和数据绑定模型通过两种方式。实际的DOM操作和输出格式被抽象的方式到指令(Directives)和过滤器(Filters)

在哲学领域内,尽量让MVVM数据绑定API尽可能简单。模块化和可组合性也是重要的设计考虑。vue不是一个全面的框架,它被设计成简单的和灵活的。你可以用它快速原型,或混合和匹配与其他库定义前端堆栈。

Vue。js的API是参考了AngularJS、KnockoutJS Ractive.js Rivets.js。尽管有相似之处,我相信Vue.js提供一个有价值能够让你在现在的一些现有框架中舍取其价值

即使你已经熟悉其中的一些术语,建议您通过以下概念的概述,因为你的这些术语的概念可能在Vue.js的下文中有所不同

概念概述

ViewModel

一个对象,同步模型和视图. 在Vue.js中,ViewModels是实例化的Vue的构造器或者是它的子类

var vm = new Vue({ / options / })
这是主要的对象,你会与作为开发人员在使用Vue.js交互。更多细节请参阅Class: Vue.

View

用户看到的实际HTML / DOM

vm.$el // The View
当使用Vue.js时候,除了自己自定义的指令你几乎不会触碰到DOM的操作,当数据更新后视图的更新将会自动的触发,视图的更新可以很精确的到每一个testNode节点,他们也批处理和异步执行从而提供更好的性能。

Model

这是一个略微修改的Javascript对象

vm.$data // The Model
在Vue.js中,模型只是简单的Javascript对象,数据对象,你能够操控他们的属性和视图模型,观察他们的从而能获取通知后更改。Vue.js在data对象胡总用ES5的 getter/setter 把属性转化了,它允许直接操作而不需要脏检查。

data对象在适当的时候会产生突变,所以修改它与通过引用修改vm.$data是一样的效果。这也方便了多个ViewModel实例观察同一块数据。

技术细节请看Instantiation Options: data.

Directives

私有的HTML属性是告诉Vue.js做一些关于DOM的处理

<div v-text="message"></div>
这里的div元素有一个v-text的指令,值是message.意思是告诉Vue.js 保持这个div节点的内容与viewMode中的message属性同步

指令可以封装任意DOM操作。例如v-attr 操作一个属性元素,v-repeat克隆基于数组的一个元素,v-on附加事件监听,我们稍后讨论.

Components

在Vue.js,一个组件是一个简单的视图模型构造函数,通过Vue.component(ID, constructor)注册。通过一个关联的ID,可以嵌套另外的视图模型的模板的v-component指令。这种简单的机制使声明视图模型的重用和组合方式类似于Web组件,而不需要最新的浏览器或重型polyfills。通过将应用程序分解成更小的组件,其结果是一个高度解耦和可维护的代码库。更多细节,请参阅Composing ViewModels.

Flex弹性盒子布局

Flex布局

弹性盒子模型

  • 采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。
  • 它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。
主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;
交叉轴的开始位置叫做cross start,结束位置叫做cross end。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

使用flex水平垂直居中

  • 给父容器设置如下属性
    1
    2
    3
    4
    display: flex;
    flex-flow:row wrap;/*flex-direction和flex-wrap的复合写法*/
    justify-content: center;
    align-items:center;

容器的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
flex-direction:属性决定主轴的方向(即项目的排列方向)
值:row | row-reverse | column | column-reverse;
flex-wrap:如果一条轴线排不下,如何换行
值:nowrap | wrap | wrap-reverse;
flex-flow:属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
值:<flex-direction> || <flex-wrap>;
justify-content:属性定义了项目在主轴上的对齐方式。
值:flex-start | flex-end | center | space-between | space-around;
align-items:属性定义项目在交叉轴上如何对齐。
值: flex-start | flex-end | center | baseline | stretch;
align-content:属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
值: flex-start | flex-end | center | space-between | space-around | stretch;

项目的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
order:属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
flex-grow:属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-shrink:属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
flex-basis:属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
值:auto | flex-start | flex-end | center | baseline | stretch;

实现三栏布局

3

  • 给父容器添加属性

    1
    2
    3
    4
    5
    6
    7
    8
    .wrap{
    display: flex;
    flex-wrap: wrap;
    }
    .wrap >*{
    flex:1 100%;
    height: 100px;
    }
  • 子容器要给高度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @media all and (min-width: 600px) {
    .aside{
    flex:1 auto;
    height: 200px;
    }
    }
    @media all and (min-width: 800px) {
    .main{
    flex:2 auto;
    }
    .aside-1{
    order: -1;
    }
    .header{
    order: -2;
    }
    }

知识梳理图

111

由浅入深了解webpack的使用

webpack

webpack是一款强大的模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理,优势如下:

  1. webpack 是以commonJS的形式来书写,但对AMD/CMD的支持也很全面,方便旧项目进行代码迁移
  2. 能被模块化的不仅仅是JS,还包括各种资源文件
  3. 开发便捷,能替代部分gulp的工作,比如打包、混淆压缩、图片转base64等
  4. 扩展性强,插件机制完善,特别是支持React热插拔

1. webpack命令行

1.1 全局安装webpack

1
$ npm install webpack -g

1.2 本地安装webpack

1
$ npm install webpack --save-dev

1.3 命令行中使用

1
$ webpack index.js bundle.js

index.js 打包的入口文件路径
bundle.js 打包后的输出文件名

1.4 命令行参数

  • webpack 开发环境下编译
  • webpack -p 生产环境下编译,会压缩生成后的文件
  • webpack -w 开发环境下持续的监听文件>变动来进行编译
  • webpack -d 生成map映射文件,会在控制台的Sources页签中出现存放打包前原始文件的webpack://目录,可以打断点,帮助调试
    index.js bundle.js -d'``
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    - webpack --progress 显示构建百分比进度
    - webpack --display-error-details 显示打包过程中的出错信息(比如 webpack寻找模块的过程)
    - webpack --profile 输出性能数据,可以看到每一步的耗时
    ## 2. 使用webpack配置文件
    ### 2.1 初始化git
    ```javascript
    $ mkdir webpack-demos && cd webpack-demos && git init

2.2 初始化项目

1
$ npm init -y

2.3 增加.gitignore

创建文件

1
$ touch.gitignore

在文件中增加以下内容

1
2
node_modules
.idea

2.4 在项目根目录下创建src和build目录

src目录存放源码,build目录存放编译打包之后的资源

1
$ mkdir src build

2.5 增加以下文件

2.5.1 src/component.js

1
$ cd src && touch component.js
1
exports.name = 'zfpx';

2.5.2 src/index.js

1
$ cd src && touch index.js
1
2
var comp = require('./component.js');
console.log(comp.name);

2.5.3 build/index.html

1
$ cd build && touch index.html
1
<script src="bundle.js"></script>

2.6 下载webpack

1
$ npm install webpack --save-dev

2.7 创建webpack的配置文件

1
$ touch webpack.config.js

配置webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
var path = require('path');
module.exports = {
//打包的入口文件 String|Object
entry: path.resolve(__dirname, 'src/index.js'),
output: { //配置打包结果 Object
//定义输出文件路径
path: path.resolve(__dirname, 'build'),
//指定打包文件名称
filename: 'bundle.js'
},
};

请注意webpack.config.js这个文件名是定死的,不然会报Output filename not configured的错误;另外,如果不按这个命名,那么在webpack运行的时候需要通过--config这个参数指定配置文件,比如:webpack --config conf.js

2.8 修改 package.json

1
2
3
"scripts": {
+ "build": "webpack"
}

2.9 执行命令进行编译

1
$ npm run build

build目录下会新增了一个bundle.js文件,里面就存放着打包后的目录

3. loader

使用babel-loader来解析es6写成的模块
加载器列表

3.1 安装loader

babel-loader可以将ES6的代码转为ES5的代码
babel官网

1
2
$ npm install babel-loader babel-core --save-dev
$ npm install babel-preset-es2015 babel-preset-stage-0 --save-dev

3.2 修改webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = {
////打包的入口文件 String|Object
entry: path.resolve(__dirname, 'src/index.js'),
output: {
//定义输出文件路径
path: path.resolve(__dirname, 'build'),
//指定打包文件名称
filename: 'bundle.js'
},
//定义了对模块的处理逻辑 Object
+ module: {
+ loaders: [ 定义了一系列的加载器 Array
+ {
+ test: /\.js$/, //正则,匹配到的文件后缀名
+ // loader/loaders:string|array,处理匹配到的文件
+ loader: 'babel-loader'
+ // include:String|Array 包含的文件夹
+ // exclude:String|Array 排除的文件夹
+
+ }
+ ]
+ }
};

“-loader”其实是可以省略不写的,多个loader之间用“!”连接起来
loaders是一个数组

3.3 添加.babelrc文件

内容如下:

1
2
3
4
{
"presets": ["es2015", "stage-0"],
"plugins": []
}

3.4 修改src/component.js

1
2
- exports.name = 'zfpx';
+ export var name = 'zfpx';

3.4 修改src/index.js

1
2
3
4
- var comp = require('./component.js');
- console.log(comp.name);
+ import {name} from './component.js';
+ console.log(name);

3.5 增加.babelrc文件

1
2
3
4
{
"presets": ["es2015", "stage-0"],
"plugins": []
}

3.6 执行命令进行编译

1
$ npm run build

4. devServer

webpack-dev-server是一个Web服务器,可以预览项目,并且当修改源码后可以实时刷新页面
server配置

4.1 安装devServer

1
$ npm install webpack-dev-server --save-dev

4.3 修改package.json

1
2
3
"scripts": {
+ "dev": "webpack-dev-server"
}

4.4 配置webpack.config.js

1
2
3
4
5
+ devServer: {
+ stats: { colors: true }, //显示颜色
+ port: 8080,//端口
+ contentBase: 'build',//指定静态文件的根目录
+ }

4.5 执行命令进行启动服务

1
$ npm run dev

启动此服务的时候,编译后的产出文件放在内存里,在build目录下看不见,但也不会删除原来已经有的文件

4.6 预览项目

打开浏览器中访问
http://localhost:8080

4.7 proxy模拟后台接口

4.7.1 修改配置webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//重写url
+ function rewriteUrl(replacePath) {
+ return function (req, opt) {
//取得?所在的索引
+ var queryIndex = req.url.indexOf('?');
//取得查询字符串的内容
+ var query = queryIndex >= 0 ? req.url.substr(queryIndex) : "";
//$1取自path匹配到的真实路径中的第一个分组
+ //把proxy的path替换为 '/$1\.json',
+ req.url = req.path.replace(opt.path, replacePath) + query;
+ };
+ }
devServer: {
stats: { colors: true }, //显示颜色
port: 8080,//端口
contentBase: 'build',//指定静态文件的根目录
+ proxy: [
+ {
//替换符合此正则的接口路径
+ path: /^\/api\/(.*)/,
//目标域名端口
+ target: "http://localhost:8080/",
//重新定向到新的地址
//$1取自path正则匹配到的真实路径的第一个分组
+ rewrite: rewriteUrl('/$1\.json'),
//修改来源地址
+ changeOrigin: true
+ }
+ ]
}

4.7.2 在build目录下添加 book.json

1
{"name":"javascript"}

4.7.3 直接访问此接口

在浏览器输入此地址
http://localhost:8080/api/book
将会被重写向到
http://localhost:8080/book.json

5. resolve解析

5.1 extension

指定extension之后可以不用在require或是import的时候加文件扩展名,会依次尝试添加扩展名进行匹配

5.1.1 修改 webpack.config.js

1
2
3
4
+ resolve: {
//自动补全后缀,注意第一个必须是空字符串,后缀一定以点开头
+ extensions: ["",".js",".css",".json"],
+ },

5.1.2 修改src/index.js

1
2
- import comp from './component.js';
+ import comp from './component';

5.2 alias

配置别名可以加快webpack查找模块的速度

  • 每当引入jquery模块的时候,它会直接引入jqueryPath,而不需要从node_modules文件夹中按模块的查找规则查找
  • 不需要webpack去解析jquery.js文件

5.2.1 先安装jquery

1
$ npm install jquery --save

5.2.2 修改 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+ var jqueryPath = path.join(__dirname,
+ "./node_modules/jquery/dist/jquery.js");
resolve: {
extensions: ["",".js",".css",".json"],
+ alias: {
+ 'jquery': jqueryPath
+ }
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader'
}
],
//如果你 确定一个模块中没有其它新的依赖 就可以配置这项,webpack 将不再扫描这个文件中的依赖
+ noParse: [jqueryPath]
},

5.2.3 修改 build/index.html

1
+ <div id="app"></div>

5.2.4 修改 src/index.js

1
2
3
+import $ from 'jquery'
- document.write(comp);
+ $('#app').html(comp);

6. 解析less样式文件

6.1 安装loader

  • less-loader负责把less源码转成css代码
  • css-loader负责读取css代码
  • style-loader负责在css代码转变成style标签并作为页内样式插入到页面中去
    1
    $ npm install less style-loader css-loader less-loader --save-dev

6.2 修改配置文件webpack.config.js

1
2
3
4
+ {
+ test: /\.less/,
+ loader: 'style!css!less'
+ }

6.3 增加less文件 src/index.less

1
2
3
4
@color: red;
.red {
color: @color;
}

6.4 在src/index.js中引入’less’文件

1
+ require('./index.less');

6.5 修改build/index.html,使用red

1
2
- <div id="app"></div>
+ <div id="app" class="red"></div>

7. 资源文件的加载

实现CSS、图标、图片等资源文件加载

7.1 安装bootstrap和相应的loader

1
2
$ npm install bootstrap --save
$ npm install file-loader url-loader --save-dev

7.2 修改 webpack.config.js

设置css文件和图标文件的加载器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
devServer: {
stats: {colors: true}, //显示颜色
+ {
+ test: /\.css/,
+ loader: 'style!css'
+ },
+ {
+ test: /\.(woff|woff2|ttf|svg|eot)$/,
+ loader: "url?limit=8192"
+ },
+ {
+ test: /\.(jpg|png)$/,
+ loader: "url?limit=8192"
+ }

配置信息的参数“?limit=8192”表示将所有小于8kb的图片都转为base64形式(其实应该说超过8kb的才使用url-loader 来映射到文件,否则转为data url形式)

DataURL和图片

7.3 修改 src/index.js

1
2
3
4
5
+ import 'bootstrap/dist/css/bootstrap.css';
+ var img = document.createElement("img");
+ img.className = 'img-circle';
+ img.src = require("./zfpx.jpg");
+ document.body.appendChild(img);

7.4 修改 build/index.html

1
2
3
+ <button class="btn btn-success">bootstrap按钮</button>
+ <span class="glyphicon glyphicon-qrcode"></span>
+ <img src="/zfpx.jpg" class="img-rounded" alt="lufy">

8. 自动刷新

在源码修改之后可以自动刷新页面
修改webpack.config.js

1
2
3
contentBase: 'build',
+ inline:true, //设置自动刷新
proxy: [

9. 自动产出html

9.1 创建html模板文件

1
$ cd src && touch index.html

9.2 下载webpack插件

1
npm install html-webpack-plugin --save-dev

9.3 修改webpack.config.js

1
2
3
4
5
6
7
8
+ var HtmlWebpackPlugin = require('html-webpack-plugin');
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: 'zhufeng-react',//标题
+ template: './src/index.html', //模板文件
+ filename:'./index.html' //产出后的文件名称
+ })
+ ]

10. 自动打开浏览器

10.1 安装插件

1
$ npm install open-browser-webpack-plugin --save-dev

10.2 修改webpack.config.js

1
2
3
4
+ var openBrowserWebpackPlugin = require('open-browser-webpack-plugin');
+ plugin: [
+ new openBrowserWebpackPlugin({ url: 'http://localhost:8080' })
+ ]

11. 区分环境标识

11.1 在脚本中设置环境变量

WIN系统

1
2
3
4
+ "scripts": {
+ "publish-dev": "set BUILD_ENV=dev && webpack-dev-server",
+ "publish-prod": "set BUILD_ENV=prod && webpack-dev-server"
+ }

MAC系统

1
2
3
4
+ "scripts": {
+ "publish-dev": "export BUILD_ENV=dev && webpack-dev-server",
+ "publish-prod": "export BUILD_ENV=prod && webpack-dev-server"
+ }

11.2 修改webpack.config.js

1
2
3
4
5
6
7
8
+ var webpack = require('webpack');
+ var definePlugin = new webpack.DefinePlugin({
+ __DEV__: (process.env.BUILD_DEV||'dev').trim() == 'dev'
+ });
plugins: [
+ definePlugin,
new HtmlWebpackPlugin

12. 暴露全局对象

12.1 安装暴露组件

1
$ npm install expose-loader --save-dev

12.2 暴露到全局对象

1
2
3
4
+ {
+ test: /jquery.js$/,
+ loader: "expose?jQuery"
+ }

12.3 在html中使用

1
2
3
+ <script>
+ console.log(window.jQuery);
+ </script>

13. css文件单独加载

13.1 安装插件

1
$ npm install extract-text-webpack-plugin --save-dev

13.2 修改webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+ var ExtractTextPlugin = require("extract-text-webpack-plugin");
+ {
+ test: /\.less/,
+ loader: ExtractTextPlugin.extract("style-loader"
, "css-loader!less-loader")
+ },
+ {
+ test: /\.css/,
+ loader: ExtractTextPlugin.extract("style-loader"
, "css-loader")
+ }
plugins: [
definePlugin,
+ new ExtractTextPlugin("bundle.css"),

14. 应用代码和第三方代码分离

14.1 修改webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
- entry: path.resolve(__dirname, 'src/index.js'),//入口文件
+ entry: {
+ index:path.resolve(__dirname, 'src/index.js'),
+ vendor: ['jquery'],
+ }
output: {
path: path.resolve(__dirname, 'build'),//输出路径
- filename: 'bundle.js' //输出文件名
+ filename: '[name].js' //输出动态文件名
},
//如果没有这句话,vendor只是一个普通的入口文件而矣,有了此语句会把vendor中的模块
//从index中分离出来,不再包含在打包出来的index.js中,会成生一个zfvendor.js文件
+ new webpack.optimize.CommonsChunkPlugin('vendor', 'zfvendor.js'),

15. 提取其它公共的代码

15.1 增加a.jsb.js

  • components.js

    1
    2
    export var name = 'zfpx';
    export var age = 8;
  • a.js

    1
    2
    var {name} = require('./component');
    console.log(name);
  • b.js

    1
    2
    var {name} = require('./component');
    console.log(age);

15.2 修改webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
entry: {
+ a:path.resolve('src/a.js'),
+ b: path.resolve('src/b.js')
}
- new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js'),
+ new webpack.optimize.CommonsChunkPlugin('common.js'),
plugins:[
+ new htmlWebpackPlugin({
+ title:'珠峰Webpack',
+ template:'./src/index.html',
+ filename:'./a.html',
+ chunks:['a','common.js']//包含产出的资源
+ }),
+ new htmlWebpackPlugin({
+ title:'珠峰Webpack',
+ template:'./src/index.html',
+ filename:'./b.html',
+ chunks:['b','common.js']//包含产出的资源
+ })
]

16. 添加哈希值

16.1 修改webpack.config.js

1
2
- filename: '[name].js' //输出文件名
+ filename: '[name].[hash].js' //输出文件名

17. 压缩资源

17.1 修改webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+ new webpack.optimize.UglifyJsPlugin({
+ compress: {
+ warnings: false
+ }
+ }),
+ new webpack.optimize.MinChunkSizePlugin({
+ compress: {
+ warnings: false
+ }
+ }),
+ // 查找相等或近似的模块,避免在最终生成的文件中出现重复的模块
+ new webpack.optimize.DedupePlugin(),
+ // 按引用频度来排序 ID,以便达到减少文件大小的效果
+ new webpack.optimize.OccurenceOrderPlugin(),
+ new webpack.optimize.AggressiveMergingPlugin({
+ minSizeReduce: 1.5,
+ moveToParents: true
+ })

18. 打包react

18.1 安装

1
$ npm install react react-dom babel-preset-react --save-dev

18.2 增加webpack.config.react.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var openBrowserWebpackPlugin = require('open-browser-webpack-plugin');
var webpack = require('webpack');
module.exports = {
entry: path.resolve(__dirname,'react/index.js'),
output: {
path: path.resolve(__dirname, 'build'),//输出路径
filename: 'bundle.js' //输出文件名
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
query: { presets: ["es2015","react"] },
exclude:/node_modules/,
include:path.resolve(__dirname,'react')
}
],
},
devServer: {
inline:true,
stats: {colors: true}, //显示颜色
port: 8080,//端口
contentBase: 'build',//指定静态文件的根目录
},
plugins: [
new HtmlWebpackPlugin({
title: '珠峰React课程',
template: './react/index.html'
}),
new openBrowserWebpackPlugin({ url: 'http://localhost:8080' }),
]
};

关于babel的预设有三种传参方法

  1. .babelrc 中配置 "presets": ["es2015", "stage-0","react"],
  2. 在loader中增加 query: { presets: ["es2015","react"] },,这会对所有的loader生效
  3. loaders: ['react-hot','babel?presets[]=es2015&presets[]=react'] 只针对某个loader生效

18.3 在package.json中增加

1
2
3
4
+ "scripts": {
+ "build-react": "webpack --config webpack.config.react.js",
+ "start-react":"webpack-dev-server --config webpack.config.react.js"
+ }

18.4 启动服务

1
npm run start-react

19. react模块热加载

19.1 安装

1
$ npm install react-hot-loader --save-dev

19.2 修改webpack.config.react.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
test: /\.jsx?$/,
- loaders: ['babel?presets[]=es2015&presets[]=react'],
- query: { presets: ["es2015","react"] },
+ loaders: ['react-hot','babel?presets[]=es2015&presets[]=react'],
exclude:/node_modules/,
include:path.resolve(__dirname,'react')
}
devServer: {
+ hot:true,
inline:true,
plugins: [
+ new webpack.HotModuleReplacementPlugin()
]

注意: 如果有多个loader的话,就不可以用query属性传参了,只能用?查询字符串传参数

19.4 启动服务

1
npm run start-react

只要修改了源代码,就会在不刷新页面的情况下刷新某个组件

20 重命名类名

为了避免不同的组件使用的类名重复可以对这些类名进行重命名

20.1 增加style.css文件

1
2
3
.red{
color:green;
}

20.2 修改webpack.config.react.js

1
2
3
4
5
+ {
+ test: /\.css/,
+ loaders: [ 'style-loader',
+ 'css-loader?modules&localIdentName=[name]__[local]___[hash:base64:5]']
+ }

20.3 修改 react/app.js

1
2
3
4
5
6
7
8
9
+ import styles from './style.css'
export default class App extends React.Component{
render(){
return (
- <h1>欢迎光临珠峰培训</h1>
+ <h1 className={styles.red}>欢迎光临珠峰培训</h1>
)
}
}

gulp 的四个核心api

1. 什么是gulp

gulp是可以自动化执行任务的工具
在平时开发的流程里面,一定有一些任务需要手工重复得执行,比如:

  • 把文件从开发目录拷贝到生产目录
  • 把多个 JS 或者 CSS 文件合并成一个文件
  • 对JS文件和CSS进行压缩
  • sass或者less文件编译CSS
  • 压缩图像文件
  • 创建一个可以实时刷新页面内容的本地服务器

只要你觉得有些动作是要重复去做的,就可以把这些动作创建成一个gulp任务
然后在指定的条件下自动执行
比如在less源文件发生改变后自动编译成css文件

2. gulp特点

  • 易于使用 通过代码优于配置的策略,Gulp 让简单的任务简单,复杂的任务可管理。
  • 快速构建 利用 node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作。前一级的输出,直接变成后一级的输入,使得在操作上非常简单
  • 高质量的插件 Gulp 严格的插件指南确保插件如你期望的那样简洁地工作。
  • 易于学习 通过最少的 API,掌握 gulp 毫不费力,构建工作尽在掌握。

3. 流

3.1 流的概念

  • Streamnodejs各种对象实现的抽象接口。
  • 所有的stream对象都是EventEmitter的实例,可以发射事件。
  • 流是一种有起点终点数据传输手段。
  • 上一个的输出是下一个的输入

3.2 gulp中的流

  • gulp正是通过代码优于配置的策略来尽量简化任务编写的工作。
  • 类似jquery里的链式操作,把各个方法串连起来构建完整的任务。
  • 用gulp编写任务也可看作是用Node.js代码编写任务。
  • 当使用流时,gulp不需要生成大量的中间文件,只将最后的输出写入磁盘,整个过程因此变得非常快。

3. 安装gulp

在项目里使用gulp需要

  • 安装node
  • 在全局范围内去安装一下gulp的命令行工具
  • 然后在项目里面再去本地安装gulp

5.1 安装node

gulp是基于Nodejs的自动任务运行器
安装Gulp和相关行件用的都是node的包管理工具npm
所以你需要先在电脑上安装 node,确定在命令行工具的下面可以使用npm这个命令,这样就能去安装Gulp了

node.js官网

安装好以后,我们可以打开命令行工具,mac 用户可以使用终端工具,windows 用户可以找到cmd命令行工具。

5.2 gulp 命令行工具

  • 使用 npm install 去安装 gulp,注意加上一个 -g 的参数,表示在全局范围内去安装.
  • 一般用 npm 安装的时候用一个 -g 的参数就表示,这个安装的东西会作为命令去执行。
  • 如果你在mac或linux下遇到了权限问题,在下面这个命令的前面加上 sudo npm install gulp -g 并输入mac密码。
    1
    $ npm install -g gulp

安装完成后可以输入 gulp --help
如果输出一些帮助的信息就表示可以gulp命令行成功安装了

如果安装不上可以换一下源试试

5.3 gulp本地安装

  1. 先创建一个目录
    maclinux 操作系统下创建一个文件夹

    1
    $ mkdir learngulp
  2. 使用 cd 命令进入此目录

    1
    $ cd learngulp
  3. 创建项目描述文件package.json
    项目需要一个叫package.json的文件来管理项目的配置,可以使用 npm init 这个命令生成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ npm init
    name: (zhufeng_automation) learngulp //项目名称
    version: (1.0.0) 1.0.0 //项目版本号
    description: learn gulp //项目说明
    entry point: (index.js) index.js // 入口文件
    test command: test.js //测试脚本 执行npm test时会执行此文件
    git repository: (https://github.git) //模块的git仓库
    keywords: node.js gulp //在npmjs官网搜索时的关键字
    author: zhufengpeixun //项目作者名字
    license: (ISC) MIT //授权协议
    About to write to D:\mygit\zhufeng_automation\package.json:
    Is this ok? (yes) yes //直接回车确认

回车后会在当前目录下创建一个 package.json 文件

4. 安装gulp

  1. 本地安装gulp到开发依赖中
    1
    $ npm install gulp --save-dev

这样可以把 gulp 作为项目的开发依赖(只在开发时用,不会发布到线上)
第一会在node_modules下安装本地的gulp
第二会把并把添加配置到package.json文件里面

1
2
3
"devDependencies": {
+ "gulp": "^3.9.0"
}

5. 运行gulp

5.1 创建配置文件

gulp的任务要放到一个叫 gulpfile.js 的文件里面
先在项目的根目录下面创建一个这样的文件
然后在这个文件的顶部添加下面这行代码

1
+ var gulp = require('gulp');

通过require可以把gulp模块引入当前项目并赋值给gulp变量
这样gulp这个变量里面就会拥有gulp的所有的方法了

5.2 创建gulp的任务

可以使用gulp的task方法
同样我们去创建一个叫 hello 的任务,它要做的事就是在控制台上输出 “您好” 这两个字

  1. 第一个参数是任务的名称
  2. 第二个参数是任务的定义,是一个匿名函数
    1
    2
    3
    gulp.task('hello', function () {
    console.log('您好');
    });

5.3 执行gulp任务

打开命令行工具,进入到项目所在的目录,然后输入:

1
$ gulp hello

会返回:

1
2
3
[21:36:34] Starting 'hello'...
您好
[21:36:34] Finished 'hello' after 959 μs

gulp后面跟着的是任务的名称
不输入任务名称的话会默认找default任务,找不到会报错

5.4 执行其它任务

可以使用

1
$ gulp <task> <othertask>

6. gulp参数

gulp 只有你需要熟知的参数标记,其他所有的参数标记只在一些任务需要的时候使用。

  • -v 或 –version 会显示全局和项目本地所安装的 gulp版本号
  • –gulpfile 手动指定一个 gulpfile 的路径,这在你有很多个 gulpfile 的时候很有用。这也会将 CWD 设置到该 gulpfile 所在目录
  • –cwd dirpath 手动指定 CWD。定义 gulpfile 查找的位置,此外,所有的相应的依赖(require)会从这里开始计算相对路径
  • -T 或 –tasks 会显示所指定 gulpfile 的 task 依赖树
  • –color 强制 gulp 和 gulp 插件显示颜色,即便没有颜色支持
  • –no-color 强制不显示颜色,即便检测到有颜色支持
  • –silent 禁止所有的 gulp 日志

7. gulp.js工作方式

gulp的使用流程一般是

  1. 首先通过gulp.src()方法获取到想要处理的文件流
  2. 然后把文件流通过pipe方法导入到gulp的插件中
  3. 最后把经过插件处理后的流再通过pipe方法导入到gulp.dest()中
  4. gulp.dest()方法则把流中的内容写入到文件中
1
2
3
var gulp = require('gulp');
gulp.src('script/src.js') // 获取文件的流的api
.pipe(gulp.dest('dist/dest.js')); // 写文件的api

8. gulp核心API

gulp只有4个核心API

8.1 gulp.src()

在Gulp中,使用的是Nodejs中的stream(流),首先获取到需要的stream
然后可以通过stream的pipe方法把流导入到你想要的地方
比如Gulp的插件中,经过插件处理后的流又可以继续导入到其他插件中,当然也可以把流写入到文件
所以Gulp是以stream为媒介的,它不需要频繁的生成临时文件,这也是Gulp的速度快的一个原因
gulp.src()方法正是用来获取流的

但要注意这个流里的内容不是原始的文件流,而是一个虚拟文件对象流,这个虚拟文件对象中存储着原始文件的路径、文件名和内容等信息
vinyl

1
2
3
4
5
6
7
8
9
10
11
12
var File = require('vinyl');
var indexFile = new File({
cwd: "/",
base: "/test/",
path: "/test/index.js",
contents: new Buffer("name=zfpx")
});
console.log(File.isVinyl(indexFile));
console.log(indexFile.isBuffer());
console.log(indexFile.isStream());

其语法为:

1
gulp.src(globs[, options])

  • globs 参数是文件匹配模式(类似正则表达式),用来匹配文件路径(包括文件名),当然这里也可以直接指定某个具体的文件路径。当有多个匹配模式时,该参数可以为一个数组
  • options 为可选参数。通常情况下我们不需要用到

8.2 glob语法

gulp内部使用了node-glob模块来实现其文件匹配功能。我们可以使用下面这些特殊的字符来匹配我们想要的文件:

8.2.1 glob规则












匹配符说明
匹配文件路径中的0个或多个字符,但不会匹配路径分隔符
**匹配路径中的0个或多个目录及其子目录
?匹配文件路径中的一个字符(不会匹配路径分隔符)
[…]匹配方括号中出现的字符中的任意一个,当方括号中第一个字符为^或!时,则表示不匹配方括号中出现的其他字符中的任意一个
!(pattern|pattern|pattern)匹配任何与括号中给定的任一模式都不匹配的
?(pattern|pattern|pattern)匹配括号中给定的任一模式0次或1次,类似于js正则中的(pattern|pattern|pattern)?
+(pattern|pattern|pattern)匹配括号中给定的任一模式至少1次,类似于js正则中的(pattern|pattern|pattern)+
(pattern|pattern|pattern)匹配括号中给定的任一模式0次或多次,类似于js正则中的(pattern|pattern|pattern)*
@(pattern|pattern|pattern)匹配括号中给定的任一模式1次,类似于js正则中的(pattern|pattern|pattern)

8.2.2 glob示例













glob匹配
*能匹配 a.js,x.y,abc,abc/,但不能匹配a/b.js
*.*a.js,style.css,a.b,x.y
*/*/*.js能匹配 a/b/c.js,x/y/z.js,不能匹配a/b.js,a/b/c/d.js
**能匹配 abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用来匹配所有的目录和文件
a/**/z能匹配 a/z,a/b/z,a/b/c/z,a/d/g/h/j/k/z
a/**b/z能匹配 a/b/z,a/sb/z,但不能匹配a/x/sb/z,因为只有单**单独出现才能匹配多级目录
?.js能匹配 a.js,b.js,c.js
a??能匹配 a.b,abc,但不能匹配ab/,因为它不会匹配路径分隔符
[xyz].js只能匹配 x.js,y.js,z.js,不会匹配xy.js,xyz.js等,整个中括号只代表一个字符
[^xyz].js能匹配 a.js,b.js,c.js等,不能匹配x.js,y.js,z.js

8.3 gulp.dest()

是用来向硬盘写入文件的,其语法为:

1
gulp.dest(path[,options])

  • path 为写入文件的路径
  • options 为一个可选的参数对象,通常我们不需要用到

要想使用好gulp.dest()这个方法,就要理解给它传入的路径参数与最终生成的文件的关系。

gulp.dest()传入的路径参数只能用来指定要生成的文件的目录,而不能指定生成文件的文件名
它生成文件的文件名使用的是导入到它的文件流自身的文件名
所以生成的文件名是由导入到它的文件流决定的

1
2
3
4
var gulp = require('gulp');
gulp.src('script/jquery.js')
.pipe(gulp.dest('dist/jquery.js'));
//最终生成的文件路径为 dist/jquery.js/jquery.js,而不是dist/jquery.js

gulp.dest(path)生成的文件路径是我们传入的path参数后面再加上gulp.src()中有通配符开始出现的那部分路径

通过指定gulp.src()方法配置参数中的base属性,我们可以更灵活的来改变gulp.dest()生成的文件路径

1
2
3
4
5
//配置了base参数,此时base路径为script
gulp.src(script/lib/*.js, {base:'script'})
//假设匹配到的文件为script/lib/jquery.js
//此时生成的文件路径为 build/lib/jquery.js
.pipe(gulp.dest('build'))

8.4 gulp.task()

gulp.task方法用来定义任务,其语法为:

1
gulp.task(name[, deps], fn)

  • name 为任务名称
  • deps 是当前定义的任务需要依赖的其他任务,为一个数组。当前定义的任务会在所有依赖的任务执行完毕后才开始执行。如果没有依赖,则可省略这个参数
  • fn任务定义函数,我们把任务要执行的代码都写在里面。该参数也是可选的。
    1
    2
    3
    4
    gulp.task('mytask', ['array', 'of', 'task', 'names'],
    function() { //定义一个有依赖的任务
    // Do something
    });

如果某个任务所依赖的任务是异步的,就要注意了,gulp并不会等待那个所依赖的异步任务完成,而是会接着执行后续的任务

1
2
3
4
5
6
7
8
9
10
//two任务虽然依赖于one任务,但并不会等到one任务中的异步操作完成后再执行
gulp.task('one',function(){
//one是一个异步执行的任务
setTimeout(function(){
console.log('one is done')
},5000);
});
gulp.task('two',['one'],function(){
console.log('two is done');
});

在异步操作完成后执行一个回调函数来通知gulp这个异步任务已经完成,这个回调函数就是任务函数的第一个参数

1
2
3
4
5
6
7
gulp.task('one',function(cb){ //cb为任务函数提供的回调,用来通知任务已经完成
//one是一个异步执行的任务
setTimeout(function(){
console.log('one is done');
cb(); //执行回调,表示这个异步任务已经完成
},5000);
});

8.5 gulp.watch()

用来监视文件的变化,当文件发生变化后,我们可以利用它来执行相应的任务,例如文件拷贝等。其语法为

1
gulp.watch(glob[, opts], tasks)

  • glob 为要监视的文件匹配模式,规则和用法与gulp.src()方法中的 glob 相同。
  • opts 为一个可选的配置对象,通常不需要用到
  • tasks 为文件变化后要执行的任务,为一个数组
    1
    2
    3
    4
    5
    6
    7
    gulp.task('uglify',function(){
    //do something
    });
    gulp.task('reload',function(){
    //do something
    });
    gulp.watch('js/**/*.js', ['uglify','reload']);

另外一种使用方式:

1
gulp.watch(glob[, opts, cb])

  • globopts 参数与第一种用法相同
  • cb参数为一个函数。每当监视的文件发生变化时,就会调用这个函数,并且会给它传入一个对象,该对象包含了文件变化的一些信息 type属性为变化的类型,可以是 addedchangeddeletedpath属性为发生变化的文件的路径
    1
    2
    3
    4
    5
    6
    gulp.watch('js/**/*.js', function(event){
    //变化类型 added为新增,deleted为删除,changed为改变
    console.log(event.type);
    //变化的文件的路径
    console.log(event.path);
    });

9.基本任务

9.1 复制单个文件

1
2
3
4
var gulp = require('gulp');
gulp.task('copy-html',function(){
return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});

9.2 复制多个文件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var gulp = require('gulp');
//复制图片
gulp.task('copy-images',function(){
return gulp.src('app/imgs/*.jpg')
.pipe(gulp.dest('dist'));
});
/**
* 1. {} 里可以指定多个扩展名
* 2. * 匹配所有的字符,除了路径分隔符 /
* 3. ** 匹配所有的字符,包括路径分隔符 /
*/
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}')
.pipe(gulp.dest('dist'));
});
/**
* 1. 匹配多个目录 glob
* 2. 可以填写一个数组
*/
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js'],{base:'app'})
.pipe(gulp.dest('dist'));
});
/**
* 1. 匹配多个目录 glob
* 2. !表示 排除一个文件
*/
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js'
,'!app/js/*.tmp.js'],{base:'app'})
.pipe(gulp.dest('dist'));
});

9.3 组合任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var gulp = require('gulp');
gulp.task('copy-html',function(){
return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}').pipe(gulp.dest('dist'));
});
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});
gulp.task('default',['copy-html','copy-images','copy-other'],function(){
console.log('全部拷贝任务执行完毕!');
});

9.4 监听任务

使用 gulp 的 watch 这个方法,我们可以去监视一些文件,当这些文件发生变化的时候,立即去执行一些指定的任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var gulp = require('gulp');
gulp.task('copy-html',function(){
return gulp.src('app/index.html')
.pipe(gulp.dest('dist'));
});
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}',{base:'app'})
.pipe(gulp.dest('dist'));
});
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js'
,'app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});
//在执行watch的时候会监控index.html文件的变化,发生变化后可以执行拷贝html的任务
gulp.task('default',function(){
gulp.watch('app/index.html',['copy-html']);
gulp.watch('app/imgs/**/*.{jpg,png}',['copy-images']);
gulp.watch(['app/css/*.css','app/js/*.js'
,'app/js/*.tmp.js'],['copy-other']);
});

10. gulp插件

gulp提供了一些很实用的接口,但本身并不能做太多的事情
可以读取文件、写入文件以及监控文件等一少部分功能
其它实用的功能都是依靠插件来进行扩展的
这些插件可以实现比如

  • 编译 Sass:gulp-sass
  • 编译 Less:gulp-less
  • 合并文件:gulp-concat
  • 压缩js 文件:gulp-uglify
  • 重命名js文件:gulp-rename
  • 优化图像大小:gulp-imagemin
  • 压缩css 文件:gulp-minify-css
  • 创建本地服务器:gulp-connect
  • 实时预览 gulp-connect

10.1 使用插件步骤

  1. npm install xxx --save-dev 安装插件
  2. gulpfile.js 顶部引入此插件
  3. 在创建任务的时候使用此插件

10.2 gulp-load-plugins

这个插件能自动帮你加载package.json文件里的gulp插件。
例如假设你的package.json文件里的依赖是这样的:

1
2
3
4
5
"devDependencies": {
"gulp": "^3.9.0",
"gulp-concat": "^2.6.0",
"gulp-connect": "^2.2.0"
}

然后我们可以在gulpfile.js中使用gulp-load-plugins来帮我们加载插件

1
2
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();

然后我们要使用gulp-concatgulp-connect这两个插件的时候,
就可以使用$.concat$.connect来代替了,也就是原始插件名去掉gulp-前缀,之后再转换为驼峰命名。

10.3 less

less插件可以把less文件编译成css

1
$ npm install gulp-less --save-dev

1
2
3
4
5
6
7
8
9
10
var gulp = require('gulp');
var less = require('gulp-less');
gulp.task('less',function(){
return gulp.src('app/less/*.less')
.pipe(less())
.pipe(gulp.dest('dist/css'));
});
gulp.task('default',['less']);

10.4 gulp-concat

这个插件可以把几个文件合并到一块

1
$ npm install gulp-concat --save-dev

1
2
3
4
5
6
7
8
9
10
var gulp = require('gulp');
var concat = require('gulp-concat');
gulp.task('concat',function(){
return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])//指定要合并的文件glob
.pipe(concat('app.js'))//进行合并并指定合并后的文件名
.pipe(gulp.dest('dist/js'));//输出到目标路径
});
gulp.task('default',['concat']);

10.5 gulp-uglify

合并后我们可以对JS文件进行压缩,最小化处理

1
$ npm install gulp-uglify --save-dev

1
2
3
4
5
6
7
8
9
10
11
12
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify')
gulp.task('uglify',function(){
return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])
.pipe(concat('app.js')) //把多个JS文件合并成一个文件
.pipe(uglify()) //对合并后的app.js文件进行压缩
.pipe(gulp.dest('dist/js')); //输出到目的地
});
gulp.task('default',['uglify']);

10.6 gulp-rename

在把处理好的文件存放到指定的位置之前,我们可以先去重新命名一下它

1
$ npm install gulp-rename --save-dev

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
gulp.task('uglify',function(){
return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])//指定要处理的文件
.pipe(concat('app.js'))//合并成一个文件
.pipe(gulp.dest('dist/js'))//保存此文件
.pipe(uglify())//进行压缩
.pipe(rename('app.min.js'))//对此文件进行重命名
.pipe(gulp.dest('dist/js'));//再输出一次
});
gulp.task('default',['uglify']);

10.7 gulp-minify-css

压缩css

1
$ npm install gulp-minify-css --save-dev

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var gulp = require('gulp');
var less = require('gulp-less');
var minify = require('gulp-minify-css');//在文件的顶部去包含这个插件,起个名字,叫做 minify
var rename = require('gulp-rename');
gulp.task('minify',function(){
return gulp.src('app/less/page.less')//指定 less文件
.pipe(less())//把less编译成css
.pipe(gulp.dest('dist/css'))//输出到目的地
.pipe(minify())//对 css再进行压缩
.pipe(rename('page.min.css'))//重命名
.pipe(gulp.dest('dist/css'));//输出到目的地
});
gulp.task('default',['less']);

10.8 gulp-minify-html

html文件压缩

1
$ npm install gulp-minify-html --save-dev

1
2
3
4
5
6
7
8
var gulp = require('gulp'),
minifyHtml = require("gulp-minify-html");
gulp.task('minify-html', function () {
gulp.src('src/*.html') // 要压缩的html文件
.pipe(minifyHtml()) //压缩
.pipe(gulp.dest('dist/html'));//输出到目的地
});

10.9 gulp-imagemin

如果要想在保证不改变图像质量的情况下,让图像文件的体积变得更小一点,我们可以使用gulp-imagemin

1
$ npm install gulp-imagemin --save-dev

1
2
3
4
5
6
7
8
9
10
var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}')//指定要压缩的图片
.pipe(imagemin()) //进行图片压缩
.pipe(gulp.dest('dist'));//输出目的地
});
gulp.task('default',['copy-images']);

10.10 gulp-connect

有些时候我们需要把文件放到本地服务器上去预览,gulp-connect可以帮我们创建一个本地服务器去运行我们的项目

1
npm install gulp-connect --save-dev

1
2
3
4
5
6
7
8
9
10
11
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('server',function(){
connect.server({
root:'dist',//服务器的根目录
port:8080 //服务器的地址,没有此配置项默认也是 8080
});
});
gulp.task('default',['server']); //运行此任务的时候会在8080上启动服务器,

10.11 自动刷新

我们希望当文件变化的时候浏览器可以自动刷新,这样我们就不需要文件修改后手动去刷新浏览器了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('copy-html',function(){
gulp.src('app/index.html')//指定源文件
.pipe(gulp.dest('dist'))//拷贝到dist目录
.pipe(connect.reload());//通知浏览器重启
});
gulp.task('watch',function(){
gulp.watch('app/index.html',['copy-html']);//当index.html文件变化时执行copy-html任务
});
gulp.task('server',function(){
connect.server({
root:'dist',//服务器的根目录
port:8080, //服务器的地址,没有此配置项默认也是 8080
livereload:true//启用实时刷新的功能
});
});
gulp.task('default',['server','watch']);//运行此任务的时候会在8080上启动服务器,

10.12 jshint

可以用此插件进行代码检查,注意必须同时安装jshint和gulp-jshint
全部选项

1
npm install jshint gulp-jshint --save-dev

1
2
3
4
5
6
7
8
var gulp = require('gulp'),
jshint = require("gulp-jshint");
gulp.task('jsLint', function () {
gulp.src('src/*.js')
.pipe(jshint()) //进行代码检查
.pipe(jshint.reporter()); // 输出检查结果
});

11 gulp.js 特点

  1. 使用gulp.js构建的是代码不是配置文件
  2. 使用node标准库编写脚本
  3. 插件非常简单,职责单一
  4. 任务都是最大的并发数执行

12 学习建议

  • 多了解插件库,利用最合适的插件。
  • 常用的插件,仔细阅读 文档以便更好使用。
  • 学习好自身的API
  • 尝试编写适合自己工作流程中和习惯的plugin

13 项目实战

13.1 安装生成器gulp-webapp

yeoman

13.2 生成项目

1
2
3
4
$ mkdir gulpstart
$ cd gulpstart
$ npm install generator-gulp-webapp@0.2.0 -g
$ yo gulp-webapp gulpstart

会打开一个向导,在这里为了简化起见,我们不使用任何第三方库。

13.3 阅读gulpfile.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* jshint node:true */
'use strict';
// generated on 2015-10-15 using generator-gulp-webapp 0.2.0
//使用require把gulp引入进来
var gulp = require('gulp');
/**
* 读取package.json中的devDependencies配置项,调用gulp api把相关的插件加载进来
* 返回一个object,每个key指向各自的插件,把对象赋值给 $,后面可以用$获取每个插件的引用
* 如果不使用gulp-load-plugins,就可以使用require引入插件 如
* var sass = require('gulp-sass');
*
*/
var $ = require('gulp-load-plugins')();
/**
* 1.此插件是用来编译sass的
* 2.
*/
gulp.task('styles', function () {
//把执行结果返回,以便此任务可以跟后续的任务配合依次执行。将多个小的操作进行组合,连接在一起就是流,数据依次从源头穿过一个个的管道,依次执行,最终在底部得到结果,可以很好的进行数据的转换
return gulp.src('app/styles/main.scss')//读取此文件到数据流中
/**
* 1.pipe是steam模块中负责传递流数据的方法,把前一个流里的数据以管道的方式传递给下一个管道。
* 2.标准的流当期中一个管道出错的时候会触发unpipe事件,会导致gulp报错并强制退出
* 我们现在监听main.scss文件的变化,一旦变化时会执行rubySass,但如果sass有语法错误,执行rubySass的时候会报错,会导致gulp报错并强制退出从而导致整个任务失败,watch就会失败,只能重启gulp服务。
* 然后不停的失败再重启,这样肯定是不可接受的。
* 3.plumber是水管工的意思,plumber通过替换pipe方法并移除onerror处理函数,这样即使有管道出问题了不会影响其它管道以及影响其它后续数据流的再处理。
* 当我们希望我们的管道能容忍容错的时候,就必须先通过plumber插件。
*/
.pipe($.plumber())
/**
* 通过 npm install gulp-ruby-sass 安装
*/
.pipe($.rubySass({
style: 'expanded',// 设置编译出来的模式为expanded模式,一共有四种 nested(层级选择器嵌套) expanded(不嵌套) compact(属性合合并在一行) compressed(全部合并到一行),请参考 http://sass-lang.com/documentation/file.SASS_REFERENCE.html#_13
precision: 10 //属性保留几位小数点 因为sass支持表达式,比如10/3,那么除不尽会有小数,我们尽可能保留完整,如果不能保留10位
}))
//需要厂商前缀的属性自动添加厂商前缀,只适配每种浏览器最新的一个版本
.pipe($.autoprefixer({browsers: ['last 1 version']}))
//处理完成后把流数据写入.tmp/styles目录
.pipe(gulp.dest('.tmp/styles'));
});
gulp.task('jshint', function () {
//对scripts目录下的JS进行校验,使用.jshintrc作为配置文件
//配置文件说明 http://jinlong.github.io/2014/10/25/jshint-configuration/?utm_source=tuicool
return gulp.src('app/scripts/**/*.js')
.pipe($.jshint())
//校验结果传递给jshint-stylish reporter
.pipe($.jshint.reporter('jshint-stylish'))//传递的是report的名称
//当校验没通过时会通过stylish记录下错误信息并传递给fail reporter,并使当前任务失败
.pipe($.jshint.reporter('fail'));
});
gulp.task('html', ['styles'], function () {
//lazypipe用来缓存一组管道配置,存起来稍后使用
var lazypipe = require('lazypipe');
var cssChannel = lazypipe()
//注意传递的是插件对象而不是插件方法调用
//csso用来压缩css文件
.pipe($.csso)
//替换内容
.pipe($.replace, 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap','fonts');
//通过解析html中的注释块来处理替换html中那些未经合并压缩的JS CSS等资源的引入
//分成二步 assets 和 useref
// assets方法用来生成检索资源文件的管道
var assets = $.useref.assets({searchPath: '{.tmp,app}'});//指定在哪些目录中搜索 html文件,是相对于gulp
return gulp.src('app/*.html')
.pipe(assets)//检索传递进来的html文件,按注释指令对这些文件进行合并,然后生成一个新的流,将之前的HTML文件替换掉,新增加合并合的资源文件
.pipe($.if('*.js', $.uglify()))//符合条件才能进入后面的流,如果是JS进行压缩再回归到主流
.pipe($.if('*.css', cssChannel()))//如果是CSS文件,则先压缩CSS再替换fonts路径
.pipe(assets.restore())//再回到主流,把删除的HTML文件添加回来
.pipe($.useref())//修改原来注释块用修改后的引用地址替换掉原来的地址
.pipe($.if('*.html', $.minifyHtml({conditionals: true/*true不移除针对IE的注释*/, loose: true/*压缩空格的时候至少保留一个空格*/})))//如果是html文件,则进行压缩
.pipe(gulp.dest('dist'));//把处理后的文件输出到dist目录
});
gulp.task('images', function () {
return gulp.src('app/images/**/*')//把图片读取入流中
/**
* 为了避免图片多次压缩失真
* imagemin只负责压缩图片,不负责检查图片是否被压缩过
* 为了避免二次压缩使用$.cache,维护一份临时文件记录哪些文件已经被处理过了,处理过了则不再传递给它包装的管道。
*/
.pipe($.cache($.imagemin({
progressive: true,//针对jpg 图像逐行扫描,先以比较模糊的方式出现,再清晰。
interlaced: true //针夺gif,隔行扫描的方式。比如先出奇数行,再出偶数行,一半的时间就可以看到轮廓。
})))
.pipe(gulp.dest('dist/images'));//输出到images目录
});
gulp.task('fonts', function () {
//main-bower-files 读取所有的bower的文件并合并上所有的字体文件读取入流
return gulp.src(require('main-bower-files')().concat('app/fonts/**/*'))
.pipe($.filter('**/*.{eot,svg,ttf,woff}'))//类似于if,符合流转,不符合则被剔除
.pipe($.flatten())//将相对路径移除
.pipe(gulp.dest('dist/fonts'));//将字体文件写入fonts目录
});
//将app下除了html以外的文件拷贝到dist目录 只拷贝一级
gulp.task('extras', function () {
return gulp.src([
'app/*.*',
'!app/*.html',
'node_modules/apache-server-configs/dist/.htaccess'//拷贝apache配置文件
], {
dot: true// node glob配置项,true时匹配以.开头的文件或文件夹
}).pipe(gulp.dest('dist'));
});
//删除.tmp和dist下的所有文件
gulp.task('clean', require('del').bind(null, ['.tmp', 'dist']));
//等同于 gulp.task('clean',function(){require('del')(['.tmp','dist'])});
/**
* 1.connect会依赖styles
* 2.这是一个node扩展的http框架,可以使用中间件方便配置
*/
gulp.task('connect', ['styles'], function () {
var serveStatic = require('serve-static');//静态文件服务器中间件
var serveIndex = require('serve-index');//显示索引文件中间件
var app = require('connect')()//先创建connect对象叫app
/**
* 此中间件就是自动为html插入livereload脚本,通过参数传递配置项参数
*/
.use(require('connect-livereload')({port: 35729}))//实时重启服务器中间件
.use(serveStatic('.tmp'))//对根目录的请求映射到.tmp目录
.use(serveStatic('app'))//对根目录的请求映射到app目录
//将对bower_components目录的访问定位到bower_components目录下
.use('/bower_components', serveStatic('bower_components'))
//参数为本地的一个文件目录,当路径命中这个目录的时候,而路径下没有index文件的时候会显示目录索引文件显示此目录下的所的文件
.use(serveIndex('app'));
//加载http组件并创建http服务器,传入的参数app就是一个请求监听处理函数
//当服务器接受请求的时候,会依次执行上面的一系列中间件,其实就是用请求路径在相应的文件夹里进行匹配,如果匹配上就返回
require('http').createServer(app)
.listen(9000)
//服务器监听成功后会输出此信息
.on('listening', function () {
console.log('Started connect web server on http://localhost:9000');
});
});
/**
* 1. 在命令行中执行 gulp serve 就可以自动打开浏览器,然后修改app/index.html就会实时刷新浏览器
* 2.因为watch依赖connect,所以这里connect可以省略
* 3.
*
*/
gulp.task('serve', ['connect', 'watch'], function () {
//打开浏览器并打开指定的URL地址
require('opn')('http://localhost:9000');
});
//插入bower_component文件
gulp.task('wiredep', function () {
var wiredep = require('wiredep').stream;
//先处理sass文件对bower_component文件的依赖
gulp.src('app/styles/*.scss')
.pipe(wiredep())
.pipe(gulp.dest('app/styles'));
//处理app下的html文件对bower_component文件的依赖
gulp.src('app/*.html')
.pipe(wiredep({exclude: ['bootstrap-sass-official']}))//排除bootstrap-sass-official
.pipe(gulp.dest('app'));
});
/**
* 1. watch依赖connect执行
* 2.
*/
gulp.task('watch', ['connect'], function () {
/**
* 1.先调用livereload的listen方法启动监听,这样文件发生改动时就可以接收到变化通知了
* 原理都是一样的,即通过在本地开启一个websocket服务,检测文件变化,当文件被修改后触发livereload任务,推送消息给浏览器刷新页面。详情参考
* http://blog.csdn.net/u010373419/article/details/38184333?utm_source=tuicool
*/
$.livereload.listen();
//监听文件的变化,当文件发生变化的时候重启服务器
//gulp.watch返回的一个eventEmitter对象,通过on change可以添加事件监听 ,当watch监控这些文件发生变化的时候可以发射change事件,从而调用$.livereload.changed监听函数执行,这就是订阅者设计模式
//监听函数可以获得哪些文件发生了改变,通过livereload服务器哪些文件变更了,
gulp.watch([
'app/*.html',
'.tmp/styles/**/*.css',
'app/scripts/**/*.js',
'app/images/**/*'
]).on('change', $.livereload.changed);
//当scss文件变化的时候重新编译sass
gulp.watch('app/styles/**/*.scss', ['styles']);
//当bower.json文件发生变化的时候自动重启把依赖的组件引入html文件
gulp.watch('bower.json', ['wiredep']);
});
/**
*编译
*
*/
gulp.task('build', ['jshint', 'html', 'images', 'fonts', 'extras'], function () {
//size展示文件大小以及总的大小 gzip为true展示gzip压缩后的文件大小,展示的是项目的总大小
return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});
/**
* 组合任务
*
*/
gulp.task('default', ['clean'], function () {
gulp.start('build');//start 可以运行build任务
});

14 自定义插件

14.1 vinyl

gulp.src中这个流里的内容不是原始的文件流,而是一个虚拟文件对象流,这个虚拟文件对象中存储着原始文件的路径、文件名和内容等信息
vinyl

1
2
3
4
5
6
7
8
9
10
11
12
var File = require('vinyl');
var indexFile = new File({
cwd: "/",//当前路径
base: "/test/",//文件名
path: "/test/index.js",//路径
contents: new Buffer("name=zfpx")//文件内容
});
console.log(File.isVinyl(indexFile));//是否是vinyl
console.log(indexFile.isBuffer());//内容是否是Buffer
console.log(indexFile.isStream());//内容是否是Stream

14.2 through2

https://www.npmjs.com/package/through2
二进制流的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var through2 = require('through2');
var fs = require('fs');
fs.createReadStream('src.txt',{highWaterMark:1})
.pipe(through2(function (chunk, encoding, callback) {
for (var i = 0; i < chunk.length; i++)
chunk[i] = chunk[i] + 1;
this.push(chunk); //向流中写数据,每push一次就发射一次data事件
callback();
})).on('data', function (data) {
console.log(data.toString());
}).on('end', function (data) {
console.log('end');
})
//.pipe(fs.createWriteStream('dest.txt'))

对象方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var through2 = require('through2');
var fs = require('fs');
var all = [];
fs.createReadStream('src.txt', {highWaterMark: 1})
.pipe(through2.obj(function (chunk, enc, callback) {
var data = {
name: chunk.toString()
}
this.push(data);
callback();
}))
.on('data', function (data) {
console.log(data)
})
.on('end', function () {
console.log('end')
})

14.3 buffer往头部增加内容插件

如果你的插件依赖着一个基于 buffer 处理的库,你可能会选择让你的插件以 buffer 的形式来处理 file.contents。让我们来实现一个在文件头部插入额外文本的插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var through = require('through2');
var PluginError = require('gulp-util').PluginError;
const PLUGIN_NAME = 'gulp-prefixer';
// 插件级别的函数(处理文件)
function gulpPrefixer(prefixText) {
if (!prefixText) {
throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
}
prefixText = new Buffer(prefixText); // 提前分配
// 创建一个 stream 通道,以让每个文件通过
var stream = through.obj(function(file, enc, cb) {
if (file.isStream()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
return cb();
}
if (file.isBuffer()) {
file.contents = Buffer.concat([prefixText, file.contents]);
}
// 确保文件进入下一个 gulp 插件
this.push(file);
// 告诉 stream 引擎,我们已经处理完了这个文件
cb();
});
// 返回文件 stream
return stream;
};
// 导出插件主函数
module.exports = gulpPrefixer;

上述的插件可以这样使用:

1
2
3
4
5
6
var gulp = require('gulp');
var gulpPrefixer = require('gulp-prefixer');
gulp.src('files/**/*.js')
.pipe(gulpPrefixer('prepended string'))
.pipe(gulp.dest('modified-files'));

14.4 stream往头部增加内容插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var through = require('through2');
var PluginError = require('gulp-util').PluginError;
//常量
const PLUGIN_NAME = 'gulp-prefixer';
function prefixStream(prefixText) {
var stream = through();
stream.write(prefixText);
return stream;
}
// 插件级别函数 (处理文件)
function gulpPrefixer(prefixText) {
if (!prefixText) {
throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
}
prefixText = new Buffer(prefixText); // 预先分配
// 创建一个让每个文件通过的 stream 通道
var stream = through.obj(function (file, enc, cb) {
if (file.isBuffer()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Buffers not supported!'));
return cb();
}
if (file.isStream()) {
// 定义转换内容的 streamer
var streamer = prefixStream(prefixText);
// 从 streamer 中捕获错误,并发出一个 gulp的错误
streamer.on('error', this.emit.bind(this, 'error'));
// 开始转换
file.contents = file.contents.pipe(streamer);
}
// 确保文件进去下一个插件
this.push(file);
// 告诉 stream 转换工作完成
cb();
});
// 返回文件 stream
return stream;
}
// 暴露(export)插件的主函数
module.exports = gulpPrefixer;

上述的插件可以这样使用:

1
2
3
4
5
6
var gulp = require('gulp');
var gulpPrefixer = require('gulp-prefixer');
gulp.src('files/**/*.js', { buffer: false })
.pipe(gulpPrefixer('prepended string'))
.pipe(gulp.dest('modified-files'));

轻松掌握jQuery的使用

JQuery

$(this).hide() - 隐藏当前元素
$("p").hide() - 隐藏所有 <p> 元素
$("p.test").hide() - 隐藏所有 class="test" 的 <p> 元素
$("#test").hide() - 隐藏所有 id="test" 的元素

语法

  • 在完全加载(就绪)之后运行 jQuery 代码。
    $(document).ready(function(){
    // 开始写 jQuery 代码…
    });

    选择器

    元素选择器
    $(“p”) 在页面中选取所有p元素
    #id选择器
    $(“#test”) 通过 id 选取元素
    .class选择器
    $(“.test”) 通过类查找元素

事件

鼠标事件               键盘事件             表单事件              文档/窗口事件
click                 keypress            submit                    load
dblclick双击         keydown键按下          change                 resize
mouseenter          keyup键抬起             focus 获取焦点          scroll
mouseleave                                   blur 失去焦点           unload
mousedown鼠标按下
mouseup鼠标抬起
hover 光标悬停
  • $(“p”).click(function(){
    鼠标点击p元素后执行的代码!!
    });

  • $(“#p1”).mouseenter(function(){
    alert(“p1”); 鼠标移入p1时,桌面弹出p1
    });

jquery效果

$(selector).show(speed,callback);
可选的 speed 参数规定隐藏/显示的速度,可以取以下值:”slow”、”fast” 或毫秒。
可选的 callback 参数是隐藏或显示完成后所执行的函数名称。

显示和隐藏 (可以指定时间)

$(“#hide”).click(function(){
$(“p”).hide(); 隐藏
});

$(“#show”).click(function(){
$(“p”).show(); 显示
});
$(“button”).click(function(){
$(“p”).toggle(); 切换
});

toggle() 方法来切换 hide() 和 show() 方法。

淡入淡出 (可以指定时间)

jQuery fadeIn(speed,callback)淡入
jQuery fadeOut(speed,callback)淡出
jQuery fadeToggle(speed,callback)切换淡入和淡出
jQuery fadeTo(speed,opacity,callback)渐变为给定的不透明度(值介于 0 与 1 之间)。

  • 实例

     $("button").click(function(){
       $("#div1").fadeIn();
       $("#div2").fadeIn("slow");
       $("#div3").fadeIn(3000);
    });
    

滑动 (可以指定时间)

slideDown(speed,callback)向下滑
slideUp(speed,callback)向上
slideToggle(speed,callback)切换上下

动画

$(selector).animate({params},speed,callback);
必需的 params 参数定义形成动画的 CSS 属性。
可选的 speed 参数规定效果的时长。它可以取以下值:”slow”、”fast” 或毫秒。
可选的 callback 参数是动画完成后所执行的函数名称。

jQuery animate() - 操作多个属性

实例

$("button").click(function(){
    $("div").animate({
     left:'250px',
     opacity:'0.5',
     height:'150px',
     width:'150px'
     });
 });

停止动画

$(selector).stop(stopAll,goToEnd);
可选的 stopAll 参数规定是否应该清除动画队列。默认是 false,即仅停止活动的动画,允许任何排入队列的动画向后执行。
可选的 goToEnd 参数规定是否立即完成当前动画。默认是 false。

callback

  • Callback 函数在当前动画 100% 完成之后执行。

     $("button").click(function(){
        $("p").hide("slow",function(){
          alert("The paragraph is now hidden");
       });
    });
    

    Chaining 链式写法

    $(“#p1”).css(“color”,”red”).slideUp(2000).slideDown(2000);

jq的捕获

获得内容 - text()、html() 以及 val()

text() - 设置或返回所选元素的文本内容
html() - 设置或返回所选元素的内容(包括 HTML 标记)
val() - 设置或返回表单字段的值

获取属性 - attr()

设置内容和属性

$(“#btn1”).click(function(){

$("#test1").text("Hello world!");

});

$(“#btn2”).click(function(){

$("#test2").html("\<b\>Hello world!\</b\>");

});

$(“#btn3”).click(function(){

$("#test3").val("RUNOOB");    

});

jQuery attr() 方法也用于设置/改变属性值。

$(“button”).click(function(){

$("#runoob").attr({
    "href" : "http://www.runoob.com/jquery",
    "title" : "jQuery 教程"
});

})

添加新的 HTML 内容

append() - 在被选元素的结尾插入内容
prepend() - 在被选元素的开头插入内容
after() - 在被选元素之后插入内容
before() - 在被选元素之前插入内容
  • 在下面的例子中,我们创建若干个新元素。这些元素可以通过 text/HTML、jQuery 或者 JavaScript/DOM 来创建。然后我们通过 append() 方法把这些新元素追加到文本中(对 prepend() 同样有效):
    实例

    function appendText()

     {
          var txt1="\<p\>文本。\</p\>";              // 使用 HTML 标签创建文本   
          var txt2=$("\<p\>\</p\>").text("文本。");  // 使用 jQuery 创建文本
         var txt3=document.createElement("p");
         txt3.innerHTML="文本。";               // 使用 DOM 创建文本 text with DOM
         $("body").append(txt1,txt2,txt3);        // 追加新元素
    }
    

删除元素/内容

如需删除元素和内容,一般可使用以下两个 jQuery 方法:

remove() - 删除被选元素(及其子元素) 自己也被移除
empty() - 从被选元素中删除子元素  不删除自己
$("p").remove(".abc");    过滤删除  只删除类名为abc的p元素

##jQuery 操作 CSS

jQuery 拥有若干进行 CSS 操作的方法。我们将学习下面这些:

addClass() - 向被选元素添加一个或多个类
removeClass() - 从被选元素删除一个或多个类
toggleClass() - 对被选元素进行添加/删除类的切换操作
css() - 设置或返回样式属性

jQuery css() 方法

css() 方法设置或返回被选元素的一个或多个样式属性。

$(“p”).css({“background-color”:”yellow”,”font-size”:”200%”});

尺寸

http://www.runoob.com/jquery/jquery-dimensions.html

遍历祖先

向上遍历 DOM 树

这些 jQuery 方法很有用,它们用于向上遍历 DOM 树:

parent() 方法返回被选元素的直接父元素。
parents()方法返回被选元素的所有祖先元素,直到文档的根元素 (<html>)。
parentsUntil()方法返回介于两个给定元素之间的所有祖先元素

实例

$(document).ready(function(){

返回介于 元素之间的所有祖先元素:

$("span").parentsUntil("div");

}); 

向下遍历 DOM 树

下面是两个用于向下遍历 DOM 树的 jQuery 方法:

children()方法返回被选元素的所有直接子元素。也可以使用可选参数来过滤对子元素的搜索
find()方法返回被选元素的后代元素,一路向下直到最后一个后代。

有许多有用的方法让我们在 DOM 树进行水平遍历:

siblings()方法返回被选元素的所有兄弟元素。可选参数过滤
next()返回被选元素的下一个弟弟元素。
nextAll()返回被选元素的下面所有的弟弟元素。
nextUntil()返回介于两个给定参数之间的所有弟弟元素。
prev()
prevAll()
prevUntil()

过滤

first()方法返回被选元素的首个元素。
last() 方法返回被选元素的最后一个元素。
eq() 方法返回被选元素中带有指定索引号的元素。
filter() 方法允许您规定一个标准。不匹配这个标准的元素会被从集合中删除,匹配的元素会被返回。
not() 方法返回不匹配标准的所有元素。  not方法与 filter() 相反。

Git入门知识详解

Git的使用

配置使用人的账号和邮箱

git config --global user.name zhufengzhufeng
git config --global user.email xxxxx
git config --list 查看所有配置

mkdir 创建目录

初始化git

git init

初始化文件

echo hello > index.txt       覆盖写入
echo hello word >> index.txt 写入
cat index.txt  查看文本里的内容

一个大于号表示清空并写入 >> 表示 追加

删除文件rm

查看状态 git status

将文件加入到暂存区中

1
2
git add file
git add ./git add -A

提交commit

1
git commit -m"first"

vi控制台

如果进入编辑模式可以i键进入插入模式

  • i表示编辑
  • 退出esc + :wq

查看版本库信息

git log --oneline 查看版本库信息
git reflog   查看未来的版本

比较代码差异

git diff            比较工作区和暂存区的区别
git diff master     比较工作区和版本库的区别
git diff --cached   比较暂存区和版本库的区别

从暂存区删除本次的add

1
git reset HEAD <file>

取消本次的add

从缓存区 从历史区将代码覆盖掉工作区

1
2
3
4
git checkout <file>
```
## 回到过去

git reset –hard commit_id/HEAD^^^^^^^/HEAD~6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
## 分支
查看所有分支git branch
创建分支git branch dev
切换分支git checkout dev
创建并切换git checkout -b fixbug
删除分支git branch -d dev
合并分支git merge 分支名
> 在主干上拉取一条分支,在分支上进行开发,开发后,在主干上将代码进行合并,主干上目前没有人开发,
可以使用快转的方式,将我们的指针直接指向到分支的最新装态 fast-forward
## 在github上部署静态页
需要将特定的内容推送到github上的gh-pages分支上
- 创建一个gh-pages的分支

git checkout -b gh-pages

1
2
- 将代码commit 到这个分支上

git add .
git commit -m ‘ok’

1
2
- 连接远程仓库和本地仓库

git remote add aaa 地址

1
2
- 将代码推送到远程仓库上

git push aaa gh-pages

1
2
3
4
5
6
7
8
9
10
##合并分支产生冲突
git log --graph --oneline --decorate 查看
## 合并分支产生冲突
- 在主干的某个版本上进行分支开发,在分支上开发1.txt这个文件(drag),在主干上也开发1.txt(limit),此时回到主干上合并时,会产生冲突,需要我们手动解决
## 从工作区中提交到历史区

git commit -a -m’drag’

1
2
3
4
5
6
7
8
9
## 解决冲突
去掉>>>>>> ======== <<<<<<< 保留需要的内容再次提交
## 合并
git rebase 变基
git cherry-pick 精选
## 显示结构

git log –graph –oneline –decorate

1
2
3
4
5
6
## 创建忽略文件
将项目提交到github上,需要在github上创建一个空的仓库
## 添加远程仓库的连接

git remote add 名字 地址

1
2
## 查看配置的所有配置的地址

git remote -v

1
2
## 删除地址

git remote rm 名字

1
2
## upstream

-u 下次提交或者拉取代码可以直接git push 或者git pull
```