0
点赞
收藏
分享

微信扫一扫

webapck 的学习基础,适合小白,初学者,进阶者学习。

webapck 的学习基础,适合小白,初学者,进阶者学习。_bundle

Webpack 是德国开发者 Tobias Koppers 开发的模块加载器兼打包工具,在webpack中,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。因此, Webpack 当中 js 可以引用 css, css 中可以嵌入图片 dataUrl。 对应各种不同文件类型的资源, Webpack 有对应的模块 loader比如vue用的是vue-loader

因为webpack是一个基于node的项目,所以首先需要确保你的电脑里面已经安装了node.js,以及npm。在这里我使用的版本是:node:v8.11.2 ,npm:6.2.0,若是版本问题,请更新到最新版。 若是有出现npm安装过慢的情况,可以使用nrm这个项目来进行npm源地址的切换。或者使用使用淘宝出品的 cnpm

安装

首先我们直接进行全局的安装,运行如下命令:npm install webpack webpack-cli -g,可能需要一点时间。

安装成功后,在命令行输入webpack -h即可查看当前安装的版本信息。以及可以使用的指令。

当然,我们都应该将webapck安装到当前的项目依赖中,此时就可以使用项目的本这样就可以使用项目本地版本的 Webpack。

# 确保已经进入项目目录
# 确定已经有 package.json,没有就通过
npm init
# 创建,直接一路回车就好,后面再来详细说里面的内容。
# 安装 webpack 依赖

npm install webpack webpack-cli --save-dev
# 简单的写法:-_-,缩写形式
npm i webpack webpack-cli -D
# –save:模块名将被添加到dependencies,可以简化为参数-S。
# –save-dev: 模块名将被添加到devDependencies,可以简化为参数-D。

安装好之后我们的package.json的目录应该是这样的:

{
  "name": "first-demo",
  "version": "1.0.0",
  "description": "this is my first-demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "guowenfh",
  "license": "MIT",
  "dependencies": {},
  "devDependencies": {
    "webpack": "^4.16.4",
    "webpack-cli": "^3.1.0"
  }
}

既然环境都已经安装好了,那么我们就开始来用webpack进行我们的第一个打包运行程序吧!

首先创建一个静态页面 index.html 和一个 JS 入口文件 entry.js,(这里你想用什么名字都可以,只需要在打包的时候读取文件为该名字就好,不过,到时候就知道这个名字的含义啦!):

<!-- index.html -->
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <h1 id="app"></h1>
    <script src="./dist/bundle.js"></script>
    <!-- 注意这里引入的不是我们创建的文件,而是用webpack生成的文件 -->
</body>
</html>

/*** entry.js ***/
document.getElementById('app').innerHTML="这是我第一个打包成功的程序";

文件都已经创建成功了,那么就开始我们的打包吧!

由于我们将 webpack 安装在了 项目目录。所以是不会向终端写入 webpack 命令的,这时我们可以像 npm script 中加入命令 :

"scripts": {
    "start": "webpack entry.js --output-filename=./bundle.js --mode=development"
  },

然后我们运行 npm run start,就会执行 webpack entry.js --output-filename=./bundle.js --mode=development

或者我们可以借用 npm 内置的执行器做到同样的事情 npx webpack entry.js --output-filename=./bundle.js --mode=development

在浏览器中打开index.html,就能看到我们设置的文字啦!:这是我第一个打包成功的程序

这么简单的功能直接在html中引入不就好了吗?确实是这样的,不过我们这才刚刚开始嘛,不要急。

下面我们再来增加一个文件,名为first.js内容如下:

var h2= document.createElement("h2")
h2.innerHTML="不是吧,那么快第二个打包程序啦!";
document.body.appendChild(h2);

更改 entry.js:

document.getElementById('app').innerHTML="这是我第一个打包成功的程序";
//添加
require("./first.js");

再来进行一次重复的工作,再打包一次。webpack entry.js --output-filename=./bundle.js --mode=development,如果成功,打包过程会显示日志:

Hash: b1cfe7ff9d75ce235dc9
Version: webpack 1.12.14
Time: 54ms
    Asset     Size  Chunks             Chunk Names
bundle.js  1.82 kB       0  [emitted]  main
   [0] ./entry.js 208 bytes {0} [built]
   [1] ./first.js 145 bytes {0} [built]

Webpack 会分析入口文件,解析包含依赖关系的各个文件。这些文件(模块)都打包到 bundle.js 。Webpack 会给每个模块分配一个唯一的 id 并通过这个 id 索引和访问模块。在页面启动时,会先执行 entry.js 中的代码,其它模块会在运行 require 的时候再执行。

刷新浏览器,可以发现我们的刚刚的代码已经生效,又有了新的文字出现。

loader介绍

Loader可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果。这样,我们就可以通过require来加载任何类型的模块或文件,比如VUEJSXSASS 或图片。

先来看看 loader 有哪些特性?(网上复制的,不喜欢可以跳过。loaders-地址)

  • Loader可以通过管道方式链式调用,每个loader可以把资源转换成任意格式并传递给下一个loader,但是最后一个loader必须返回JavaScript。
  • Loader可以同步或异步执行。
  • Loader运行在node.js环境中,所以可以做任何可能的事情。
  • Loader可以接受参数,以此来传递配置项给loader
  • Loader可以通过文件扩展名(或正则表达式)绑定给不同类型的文件。
  • Loader可以通过npm发布和安装。
  • 除了通过package.jsonmain指定,通常的模块也可以导出一个loader来使用。
  • Loader可以访问配置。
  • 插件可以让loader拥有更多特性。
  • Loader可以分发出附加的任意文件。

loader使用

安装

根据上面说的loader的知识,就这样编译是肯定不行的,所以我们安装用来读取css文件的css-loader,再用 style-loader 把它插入到页面中。

在命令行中输入:

npm install css-loader style-loader --save-dev

package.json中,主要是devDependencies这个字段有了改变:

"devDependencies": {
    "css-loader": "^0.23.1",
    "style-loader": "^0.13.0",
    "webpack": "^1.12.2"
}

当然你可以用一个更加方便的方式进行安装,可以直接在package.json中,添加相应的依赖(如上面的代码),之后的命令行中运行npm intall,它会自动帮我们安装相应的依赖。

安装完毕。

加载 CSS 文件

还是上一篇博客中的文件,来添加一个css文件。style.css,在里面添加

body {
    background: red;
}

修改我们的entry.js,原文件不变,添加require("!style-loader!css-loader!./style.css");,用来引入我们的css文件。

我们继续编译:

npx webpack entry.js --output-filename=./bundle.js --mode=development

完成后,刷新我们的页面,背景颜色是不是已经变成了红色了呢?

扩展名自动绑定loader

这就是我们的loader的使用方式了。如果每次 require CSS 文件的时候都要写 loader 前缀!style-loader!css-loader!这样的东西,显然是一件很麻烦的事情。我们需要它可以根据模块类型(扩展名)来自动绑定需要的 loader

来看看更简便的方式,将 entry.js 中的 require("!style-loader!css-loader!./style.css") 修改为require("./style.css"),可以改变一个背景颜色让你更明显的查看到变化!然后执行:

npx webpack entry.js --output-filename=./bundle.js --mode=development --module-bind "css=!style-loader!css-loader"

。。

。。。

没成功对吧! 因为!在命令行中具有特殊的含义,所以我们需要对它进行转义操作。再来试试:

npx webpack entry.js --output-filename=./bundle.js --mode=development --module-bind "css=style-loader\!css-loader"

成功的话,应该能再次看到背景的变化。

虽然这样可以将多个css文件进行编译打包,但是总感觉很是繁琐,我不想每次都运行那么一长串的命令怎么办?继续向下走吧。

了解webpack配置

Webpack在执行的时候,除了在命令行传入参数,还可以通过指定的配置文件来执行。默认情况下,会搜索当前目录的webpack.config.js文件,这个文件是一个 node.js 模块,返回一个 json 格式的配置信息对象,或者通过 --config 选项来指定配置文件。

所以现在我们就来新建一个webpack.config.js,在里面填写进下面的内容:

const webpack = require("webpack");
const path = require('path')
module.exports = {
    entry: ["./entry.js"],
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js"
    },
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin("这里是打包文件头部注释")
    ]
}

我们现在仅仅需要运行:webpack,如果你的配置没有问题的话,可以在命令行中看到正确的输出,因为这个命令会自动在当前目录中查找webpack.config.js的配置文件,并按照里面定义的规则来进行执行。

去修改我们的css文件吧,感受一下它的便利。

上面我们仅仅是使用了这个配置文件,我们肯定想在实际的工作环境中,自我对于项目进行针对性的配置。下面我们就先来简单的了解一下里面参数的意义:

  • entry:指入口文件的配置项,它是一个数组的原因是webpack允许多个入口点。 当然如果你只有一个入口的话,也可以直接使用双引号"./entry.js"
  • output:配置打包结果,path定义了输出的文件夹,filename则定义了打包结果文件的名称
  • module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。

在这里仅仅能做一些很简单的介绍,如果想要真正做到在项目中的实际应用,还需要大量的练习与尝试。在此暂时不做过多的探究。等真正用到了再记录下来。

了解webpack插件

下面就来看看webpack中的插件:

插件可以完成更多loader不能完成的功能。插件的使用一般是在webpack.config.js中的plugins 选项中指定。

Webpack本身内置了一些常用的插件,还可以通过npm安装第三方插件。

接下来,我们从一个最简单的,用来给输出的文件头部添加注释信息BannerPlugin的内置插件来实践插件的配置和运行。

修改 webpack.config.js,添加 plugins配置项:

var Webpack = require("webpack");//必须引入
module:{
},
plugins: [
    new webpack.BannerPlugin("这里是打包文件头部注释!")//注意这是一个数组..
]

运行正确的话应该是这样的,打开bundle.js,会发现在文件头部已经有了我们添加的注释:

/*! 这里是打包文件头部注释 */
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
        /***  省略 ***/
        })

最简单的插件使用方式就是这样的了,就如上面一样的,平淡无奇。

还有部分说明

如果看到了这里,相信你对于webpack的最基本的了解应该就差不多了,下面正式进入实战的阶段,来看看我们的一些loader到底是怎么样使用的。

加载图片

现在来我们来试试加载图片,首先第一件事情,肯定是安装对应的loader。它会将样式中引用到的图片转为模块来处理,使用该加载器需要先进行安装:

npm install url-loader --save-dev

当然你也可以在package.json添加依赖,然后再npm nstall一样的效果。

现在去我们的项目目录中添加img文件夹,添加两张图片,一张大图jpg,一张小图png。

然后在我们的webpack.config.js中添加这段:

rules: [
    {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
            limit: 8192,
            name: path.posix.join('','img/[name].[hash:7].[ext]')
        }
        // 添加到这并且会按照文件大小, 或者转化为 base64, 或者单独作为文件
        //在大小限制可以name属性/[name].[ext],会将我们的文件生成在设定的文件夹下。
    },
]

在html中添加:

<img src="img/logo.png" alt="">
<div id="qwe"></div>
<div id="asd"></div>

在我们的css中添加:

/*记得写宽高。。*/
#qwe{
    background-image: url(img/logo.png);/*3.2k*/
}
#asd{
    background-image: url(img/5.jpg);
}

继续运行webpack如果正确的话,打开我们的浏览器,就可以看到我们正确的图片显示。

如果不正确,请运行npm install file-loader -D,再进行尝试。

现在我们打开浏览器的调试工具,可以看到小于8K的 背景图片 图片已经被转化成了base64的编码,而大于8k的图片则并没有转化(注意它的地址的变化!)。 直接使用img导入的图也并没有进行base64的转化。

热加载

当项目逐渐变大,webpack 的编译时间会变长,可以通过参数让编译的输出内容带有 进度 和 颜色 。

webpack --progress --colors

下面还有一些其他常用的命令:

webpack #最基本的启动webpack命令
webpack -w #提供watch方法,实时进行打包更新
webpack -p #对打包后的文件进行压缩
webpack -d #提供SourceMaps,方便调试
webpack --colors #输出结果带彩色,比如:会用红色显示耗时较长的步骤
webpack --profile #输出性能数据,可以看到每一步的耗时
webpack --display-modules #默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块

我们已经把webpack的内容了解了一部分了,那么在生产环境中,我不想每一次进行改变,都去命令行中运行我们的webpack的命令,我们应该怎么样实现改变后自动更新呢?

webpack 为我们提供了一个webpack --watch,他会启动监听模式。开启监听模式后,没有变化的模块会在编译后缓存到内存中,而不会每次都被重新编译,所以监听模式的整体速度是很快的。

去运行这个命令试试吧!!

在我们改变代码之后,命令行中可以看到直接就自动编译了,但是显然不够智能,还需要我们手动去刷新浏览器,(其实用liveloadhack成自动刷新!)。

我反正不能忍,还要手动刷新浏览器。所以使用webpack-dev-server会是一个更好的办法!

它将在localhost:8080启动一个express静态资源web服务器,并且会以监听模式自动运行webpack,在浏览器打开http://localhost:8080/或 http://localhost:8080/webpack-dev-server/ 可以浏览项目中的页面和编译后的资源输出,并且通过一个socket.io服务实时监听它们的变化并自动刷新页面。

# 安装
npm install webpack-dev-server -D

# 运行
npx webpack-dev-server --config ./webpack.config.js

试试vue

我们来试试使用vue能配合webpack能不能实现自动刷新。(有关vuejs的知识,大家可以可以先自行上官网查看)

首先运行npm install vue -save将vue添加到我们的项目依赖中去。

首先在我们的entry.js这个入口文件中进行添加:

// import Vue form ("vue") //如果你安装了babel-loader的话,可以直接使用ES6的语法

const Vue =require('vue/dist/vue');

new Vue({
  el: '#main',
  data: {
    message: 'hello vue.js'
  }
})

同样在index.html中添加{{ meassge }}来响应vue的数据绑定。

运行webpack-dev-server。去浏览器查看试试效果吧!http://localhost:8080。 任意改变message中的值,可以看到浏览器会自动刷新。并且将改变的值展示在眼前。(有可能只在http://localhost:8080/webpack-dev-server/才会自动刷新)

自动刷新都配好了。下面我们就来试试怎么加载vue的文件,来实现单文件组件!

开始

第一步:初始化项目目录

我们需要创建如下目录及文件夹,最终目录结构如下:

- dist //文件生成目录
    -- //自动生成
- node_module //自动安装
    -- ...
- src //文件入口
    -- components //组件存放
        -- app.vue //主.vue
    -- main.js //主.js
- index.html //主.html
- package.json //npm 配置
- webpack.cofig.js // webpack配置

第二步:安装项目依赖

如果你上面没有创建package.json文件的话,可以直接使用npm init来初始化我们的package.json文件的配置。

想要去编译其他的文件比如reactcoffce等等,就必须要加载很多对应的loader。要想加载一个.vue文件。当然也是同样的道理。 建议用npm install xxx-loader --save-dev这样的命令一条一条的敲。在命令行中,会有提示,可以帮助理解webpack的中的依赖管理关系。我的配置清单如下: 在实际项目中,json文件中不能出现注释,在这里为了方便大家了解里面设置项的含义,就直接使用注释的方式加载后面了。

{
    "name": "05-five-vue", //项目名称
    "version": "1.0.0", //版本
    "description": "vue+webapck", //描述
    "main": "index.js", //主文件
    "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot"
    }, //scripts指定了运行脚本命令的npm命令行缩写,比如这是的start指定了运行npm run start时,所要执行的命令。
    "dependencies": { //项目依赖
        "vue": "^2.5.17"
    },
    // 编译成的 es 版本
    "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
    ],
    "devDependencies": { //各种各样的loader,用来解析想相应的文件格式。要解析vue并且完成相应的功能,这些基本都是必须的。
        "babel-core": "^6.26.3",
        "babel-loader": "^7.1.5",
        "babel-preset-env": "^1.7.0",
        "babel-preset-stage-0": "^6.24.1",
        "babel-preset-stage-0": "^6.24.1",
        "cross-env": "^5.2.0",
        "css-loader": "^1.0.0",
        "file-loader": "^1.1.11",
        "node-sass": "^4.9.2",
        "sass-loader": "^7.1.0",
        "style-loader": "^0.21.0",
        "url-loader": "^1.0.1",
        "vue-loader": "^14.2.3",
        "vue-style-loader": "^4.1.1",
        "vue-template-compiler": "^2.5.17",
        "webpack": "^4.16.4",
        "webpack-cli": "^3.1.0",
        "webpack-dev-server": "^3.1.5"
    },
    "author": "guowenfh", //作者
    "license": "MIT", //开源协议
    "keywords": [ //关键字
        "vue",
        "webpack"
    ]
}

如果你想省事的话,直接复制上面的devDependencies,dependencies字段,并且填写到你的package.json文件中。然后运行npm install就会自动安装所有的模块以及依赖。

第三步:配置webpack

文件已经设置好了,接下来就到了我们关键的一步,配置webpack.config.js,清单如下:

const path = require('path')
const webpack = require('webpack')
// NodeJS中的Path对象,用于处理目录的对象,提高开发效率。
// 模块导入
module.exports = {
    // 入口文件地址,不需要写完,会自动查找
    entry: './src/main',
    // 输出
    output: {
        path: path.join(__dirname, './dist'),
        // 文件地址,使用绝对路径形式
        filename: 'build.js',
        //[name]..这里是webpack提供的根据路口文件自动生成的名字
        publicPath: '/dist/'
        // 公共文件生成的地址
    },
    mode:'development',
    // 加载器
    module: {
        // 加载器,loaders
        rules: [
            // 编译css
            {
                test: /\.css$/,
                use: ['vue-style-loader', 'css-loader']
            },
            //.scss 编译
            {
                test: /\.scss$/,
                use: [
                  'vue-style-loader',
                  'css-loader',
                  'sass-loader'
                ],
              },
              {
                test: /\.sass$/,
                use: [
                  'vue-style-loader',
                  'css-loader',
                  'sass-loader?indentedSyntax'
                ],
              },
            // 解析.vue文件
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                      'scss': [
                        'vue-style-loader',
                        'css-loader',
                        'sass-loader'
                      ],
                      'sass': [
                        'vue-style-loader',
                        'css-loader',
                        'sass-loader?indentedSyntax'
                      ]
                    }
                }
            },
            // 转化ES6的语法
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
                options:{
                    presets: [['env', { modules: false }], 'stage-0']
                }
            },
            // 图片转化,
            {
                test: /\.(png|jpg|gif|svg)$/,
                loader: 'url-loader',
                options: {
                    name: '[name].[ext]?[hash]'
                }
            }
        ]
    },
    resolve: {
        // 别名,可以直接使用别名来代表设定的路径以及其他
        alias: {
            vue$: 'vue/dist/vue.esm.js',
            filter: path.join(__dirname, './src/filters'),
            components: path.join(__dirname, './src/components')
        },
        // require时省略的扩展名,如:require('module') 不需要module.js
        extensions: ['*', '.js', '.vue', '.json']
    },
    // 服务器配置相关,自动刷新!
    devServer: {
        historyApiFallback: true,
        noInfo: true,
        overlay: true
    },
    performance: {
        hints: false
    },
    // 开启source-map,webpack有多种source-map,在官网文档可以查到
    devtool: '#eval-source-map'
}

请详细查看这里面的设置,我这里都是很简单的配置,在你的项目中,还可以更进一步的对于入口文件和输出文件进行更加深入的定制。

并且在这里生成的css文件还会插到js中,有时我们需要更进一步的把它独立出来,然后在html中引入这时就会用到webpack的插件,在这里先不说(因为我暂时没用到,没有试验过,好像也不麻烦,可以的话下篇再试试)

第四步:编写代码

接下来就是我们要展示的文件的编写了,我直接把代码贴上来了。

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>webpack vue</title>
    <style>
        *, *:before, *:after {
            box-sizing: border-box;
        }
        body, html {
            height: 100%;
            overflow: hidden;
        }
        #app {
            margin: 20px auto;
            width: 800px;
            height: 600px;
        }
    </style>
</head>

<body>

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

    <script src="./dist/build.js"></script>
</body>

</html>

这里是main.js的内容:

//es6语法:
import Vue from "vue";
//引入我们编写的测试用vue文件。
import App from './components/app';

Vue.config.debug = true;//开启错误提示

new Vue({
    el: '#app',
    render: h => h(App)
})

这里是app.vue:

<template>
    <div id="app">
        <h1>姓名:{{name}}</h1>
        <h2>{{age}}</h2>
    </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      name: 'guowenfh',
      age: '23'
    }
  }
}
</script>
<style lang="scss" >
$qwe: #098;
body {
  background-color: $qwe;
  h1 {
    background-color: #eee;
    color: yellowgreen;
    transform: translate(10%, 10%);
  }

  h1:hover {
    height: 100px;
  }

  h2 {
    background-color: #999;
  }
}
</style>

第五步:修改自动刷新设置

下面再单独的再谈一下关于自动刷新的实现,首先需要说明,在上一篇博客中的自动刷新实现,是有问题的。只能改变css样式,使颜色进行变化。对于html里面的内容改变时,浏览器并不会自动刷新。

注意点一: 首先我们看到package.jsonscripts字段中的"start": "cross-env NODE_ENV=development webpack-dev-server --open --hot"。 这里开启了 热加载 以及自动打开浏览器。

注意点二: 在webpack.cofig.js中还有其余对于devServer进行一些配置,如下:

devServer: {
        historyApiFallback: true,
        noInfo: true,
        overlay: true,
        inline: true,
        progress: true, // 进度
    },

这样安装设置完成之后,就有了自动局部更新了!!

结束

步骤都走完了,因为在上面的package.json中已经进行了scripts项的配置。运行npm start,打开localhost:8080

可以看到设置的背景色已经出来了,去改变一下背景颜色?data?template?

看看浏览器会不会自动刷新?

添加

开发环境可以了,但是生产环境呢?在 webpack.config.js我们再来增加一些配置

if (process.env.NODE_ENV === 'production') {
    module.exports.mode = 'production',
    module.exports.devtool = '#source-map'
    // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: '"production"'
        }
      }),
      new webpack.LoaderOptionsPlugin({
        minimize: true
      })
    ])
}

然后再加一个 npm script 。 "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 运行 npm run build  我们就可以将我们刚刚开发的内容进行压缩打包了。

如果你按照我的步骤,并且,npm包安装没有错误的话,应该就能成功了。

不行的话,请再仔细对照去看看有什么地方没有编写对吧!

但是我们最终的目的还是要实现单页面应用程序,这个时候我们就必不可少的需要使用到路由管理器来进行SPA的开发,vue官方为我们提供了一个官方库vue-router,并且配有对应的中文文档。关于里面的内容大家自行前去观看。在这里,只会把我们需要的东西拿出来讲。

vue组件

官网对于组件讲解

Vue中定义一个组件非常简单,只需要一对自定义标签,在其中填入内容就可以进行我们的组件编写了,然后使用Vue.component()去注册我们的组件下面来看一个例子,来直观的看看vue的组件。

组件入门

<script src="js/vue.js"></script>
<body>
    <div id="app">
        <my-component></my-component>
        <!-- 自定义标签作为组件名称 -->
        <my-component></my-component>
        <!-- 复用 -->
    </div>
    <script>
        // 定义并且注册组件
        // 在官方的示例中使用 Vue.extend({})先注册了一个定义模板,再引用,看个人喜好吧
        Vue.component("my-component", {
            template:"<h2>hello Vue component</h2>"
        })
        // 创建根实例
        // 在这里 定义并且注册组件 必须创建根实例前,不然会报错,因为解析顺序的问题?
        new Vue({
            el:"#app"
        });
    </script>
</body>

上面就是最简单的定义组件的方式,template属性中写的东西:就是<my-component>这个自定义标签渲染后展现出来的样式,这里渲染为:

<div id="app">
    <h2>hello Vue component</h2>
    <h2>hello Vue component</h2>
</div>

组件的基础介绍就到这,更多详细内容请移步官网,有着非常清晰的讲解。

vue-router

刚刚已经对于vue的组件有了一定的了解。现在来结合vue-router,来进行一下动态的切换。

首先是安装,如果使用npm的形式的话,直接运行npm install vue-router --save,就可以看到vue-router,已经被添加到了项目依赖中。直接上ES6的语法来进行引入

import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);

起步

其实这一部分vue-router的中文文档中已经讲的非常详细了。。在这里与它不同的是它用的CommonJS的规范来进行模块安装,而我使用ES6的import,有兴趣自己去看- -。其他的内容我就直接扒下来了。

html:

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用指令 v-link 进行导航。 -->
    <a v-link="{ path: '/foo' }">Go to Foo</a>
    <a v-link="{ path: '/bar' }">Go to Bar</a>
  </p>
  <!-- 路由外链 -->
  <router-view></router-view>
</div>

javascript:

// 定义组件
var Foo = Vue.extend({
    template: '<p>This is foo!</p>'
})
var Bar = Vue.extend({
    template: '<p>This is bar!</p>'
})
// 路由器需要一个根组件。
// 出于演示的目的,这里使用一个空的组件,直接使用 HTML 作为应用的模板
var App = Vue.extend({})
// 创建一个路由器实例
// 创建实例时可以传入配置参数进行定制,为保持简单,这里使用默认配置
var router = new VueRouter()
// 定义路由规则
// 每条路由规则应该映射到一个组件。这里的“组件”可以是一个使用 Vue.extend
// 创建的组件构造函数,也可以是一个组件选项对象。
// 稍后我们会讲解嵌套路由
router.map({
    '/foo': {
        component: Foo
    },
    '/bar': {
        component: Bar
    }
})
// 现在我们可以启动应用了!
// 路由器会创建一个 App 实例,并且挂载到选择符 #app 匹配的元素上。
router.start(App, '#app')

我个人感觉这部分还是很好理解的,官方也给了一系列的例子:查看仓库的 README.md 来运行它们。很好的展现了它的路由切换。

简单的介绍到这,下面最重要的部分到了,看看如何结合我们定义的.vue单文件组件。

首先来看我们的文件目录结构:


定义路由规则

** 最主要是main.js ** 的变化,直接在文件中讲解了:

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 引入vue以及vue-router的。
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来

// 引入组件!
import App from './App.vue'
import Index from './components/index.vue'
import List from './components/list.vue'
import Hello from './components/hello.vue'

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  {
    path: '/index',
    component: Index,
    children: [
        { path: 'hello', component: Hello }
    ]
  },
  {
    path: '/list',
    component: List
  },
  {
    path: '*',
    redirect: '/index'
  }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

// 现在,应用已经启动了!

App.vue 需要有用于渲染匹配的组件,如下

<template>
    <router-view></router-view>
</template>

现在当我们运行 npm start 进入http://localhost:8080/就会自动跳转到http://localhost:8080/#/index,并且读取里面的内容。

实现路由跳转

主要抽出index.vue中的内容来讲解,的内容是:(list.vue里面的内容自行设置查看吧)

<template>
<div>
    <h1>姓名:{{name}}</h1>
    <h2>{{age}}</h2>
    <button @click="golist">$route.push查看</button>
    <router-link :to="{ path: '/list' }">v-link查看列表</router-link>
    <router-link :to="{ path: '/index' }">回去主页</router-link>
    <router-link :to="{ path: '/index/hello' }">嵌套的路由</router-link>
    <hello></hello>
    <router-view></router-view>
</div>
</template>
<script>
    // import hello from "./hello.vue"
    export default {
        data () {
            return {
                name:"guowenfh",
                age:"21"
            }
        },

        methods :{
            golist (){
                this.$router.push({path:"/list"})
                // this.$route.router.go({name:"list"});
            }
        }
    }
</script>
<style></style>
<!-- 样式自行设置,或者直接看源码就好 -->

因为自刷新的缘故,直接切换到浏览器。

点击上面使用的router-link,与this.$router.push的方式都可以跳转到list定义的路由。(观察浏览器地址栏的变化)在这里我们使用 { path: '/list' } ,如有别名的话,使用的{name:"list"},会有同样的效果。

Vue组件的嵌套

在第一小点里面我们看到了在页面内的组件的使用方法,第二小点中学习到了vue-router的制定路由规则。

看过这两个地方之后,我们把思维发散开来,应该就能触类旁通的想到如何在页面中嵌套加载别的组件了。 我们创建一个hello.vue ,里面内容随意。现在我们如果要在app.vue中加载它,那么只需要在app.vue中使用import hello from "./hello.vue"(其实这个达到了使用require两步的效果。引入赋值)。

引入之后,只需要如下注册:

export default {
    //其它的就
    components:{
        hello//若还有更多的组件,只需要在import的情况下,以逗号分割,继续注册就好
    }
}

最后在app.vue中添加<hello></hello>这一对自定义标签,就可以实现加载hello.vue中的内容。

组件的嵌套也就是这样,很简单的描述完了,但是怎么样去抽离组件,在工作中积累可以复用的组件才是我们真正需要去思考的。

那么先到这,关于组件之间通信的问题,留到以后慢慢了解。

路由嵌套

还是刚刚的代码与目录结构,我们已经实现了组件之间的嵌套,但是有时并不希望组件直接就加载进来,而是在用户点击后才展现在页面中,这是就需要使用到路由嵌套。

为了偷懒,这里就直接使用hello.vue。实现嵌套路由主要有以下几步:

第一步:制定嵌套路由规则:

main.js下面这部分的代码:

{
    path: '/index',
    component: Index,
    // 在/index下设置一个子路由
    children: [
         // 当匹配到/index/hello时,会在index的<router-view>内渲染
        {
            path: 'hello',
            name:'hello',//可有可无,主要是为了方便使用
            // 一个hello组件
            component: Hello
        }
    ]
  }

第二步:在组件中添加<router-view>

来自官网的解释:<router-view> 用于渲染匹配的组件,它基于Vue的动态组件系统,所以它继承了一个正常动态组件的很多特性。

<router-view>写在app.vue<template></template>标签中。

第三步:写入跳转路径

还是在index.vue中:

<router-link :to="{ path: '/index' }">回去主页</router-link>
<!-- 点击这两个标签就会实现页面内的切换效果 -->
<router-link :to="{ path: '/index/hello' }">嵌套的路由</router-link>

,切换到浏览器,点击该嵌套的路由即可让hello.vue中的展现出来,在这里直接使用了router-link来实现跳转 ,当然$router.push同理。(注意在点击两个不同的文字时,地址栏的变化,以及展现内容的切换)

注意:

在我的源码中是在<style scoped></style>标签中定义样式的,请注意scoped的使用,它表示在该style中定义的样式只会在当前的组件中起到效果,而不会去影响全局的css样式。

最简单的理解应该就是:

未写该scoped属性的所有组件中的样式,在经过vue-loader编译之后拥有全局作用域。相当于共用一份css样式表。

而写了该属性的的组件中定义的样式,拥有独立作用域。相当于除去引入了公用的一份css样式表外,但单独拥有一份css的样式表。

举报

相关推荐

0 条评论