webapck 的学习基础,适合小白,初学者,进阶者学习。
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来加载任何类型的模块或文件,比如VUE
、JSX
、SASS
或图片。
先来看看 loader 有哪些特性?(网上复制的,不喜欢可以跳过。loaders-地址)
-
Loader
可以通过管道方式链式调用,每个loader
可以把资源转换成任意格式并传递给下一个loader
,但是最后一个loader
必须返回JavaScript。 -
Loader
可以同步或异步执行。 -
Loader
运行在node.js环境中,所以可以做任何可能的事情。 -
Loader
可以接受参数,以此来传递配置项给loader
。 -
Loader
可以通过文件扩展名(或正则表达式)绑定给不同类型的文件。 -
Loader
可以通过npm发布和安装。 - 除了通过
package.json
的main
指定,通常的模块也可以导出一个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
,他会启动监听模式。开启监听模式后,没有变化的模块会在编译后缓存到内存中,而不会每次都被重新编译,所以监听模式的整体速度是很快的。
去运行这个命令试试吧!!
在我们改变代码之后,命令行中可以看到直接就自动编译了,但是显然不够智能,还需要我们手动去刷新浏览器,(其实用liveload
hack成自动刷新!)。
我反正不能忍,还要手动刷新浏览器。所以使用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
文件的配置。
想要去编译其他的文件比如react
,coffce
等等,就必须要加载很多对应的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.json
中scripts
字段中的"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)