vue入门--插槽(具名、匿名、作用域插槽)+ES6模块化导入导出+webpack的使用(基本使用+配置使用+如何一步步演化成cli脚手架)+webpack插件使用(搭建本地服务器、配置文件分离)

vue入门–基础命令+axios+案例练习
vue入门–vue常用属性、生命周期、计算属性、过滤器、组件、虚拟DOM、数组的响应式方法、页面闪烁、ES6简单语法增强
vue入门–js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问
vue入门–插槽(具名、匿名、作用域插槽)+ES6模块化导入导出+webpack的使用(基本使用+配置使用+如何一步步演化成cli脚手架)+webpack插件使用(搭建本地服务器、配置文件分离)
vue-cli脚手架2版本及3+版本安装、目录解析、only和compiler的区别、3+版本如何改配置、箭头函数及this的指向
vue-router基本使用、路由传参、懒加载、嵌套路由、导航守卫、keep-alive
Promise基本使用、三种状态、链式调用及简写、all方法
Vuex的作用、使用、核心概念(State、Mutations、Getters、Actions、Modules)、文件抽离
axios网络请求基本使用、配置使用(全局axios和局部axios实例)、模块封装、axios拦截器

插槽

组件的插槽:

有点类似于Java的接口。

  • 组件的插槽是为了让我们封装的组件更加具有扩展性。
  • 让使用者可以决定组件内部的一些内容到底展示什么。

基本使用(单插槽)

  • 基本使用:<slot></slot>
  • 插槽中设置默认值 : <slot><button>按钮</button></slot>
  • 如果有多个标签元素放入插槽中,那么都会被显示在插槽中
<div id="app">
    <cpn></cpn>
    <cpn>		
        <!-- 插槽中有多个标签时,会全都显示在一个插槽中 -->
        <div>div元素</div>
        <p>p元素</p>
    </cpn>
    <cpn><i>额额额</i></cpn>
</div>

<template id="cpn">
    <div>
        <h2>我是组件</h2>
        <p>是组件</p>
        <!-- 定义一个插槽,且插槽中可以设置默认的标签 如 button -->
        <slot><button>按钮</button></slot>
    </div>
</template>
<script src="./vue/vue.js"></script>
<script>
    const cpn = {
      
      
        template: "#cpn"
    }
    const app = new Vue({
      
      
        el:"#app",
        components:{
      
      
            cpn
        }
    })
</script>

具名插槽的使用(多插槽)

在子组件中定义插槽时,可以为插槽指定一个name属性。

使用组件时,可以用<template></template> + v-slot:名称,指定替换掉哪个slot里的内容。

注意:v-slot只能添加在 <template></template>标签上

<div id="app">
    <cpn>
        <!-- 使用的时候,我可以指定只切换哪个插槽里的内容 -->
        <template v-slot:center>
            <span>标题</span>
        </template>
    </cpn>
    <cpn>
        <!-- 将名为right的插槽中的内容替换为一下内容 -->
        <template v-slot:right>
            <span>标题</span>
        </template>
    </cpn>
</div>

<template id="cpn">
    <div>
        <!-- 定义三个插槽并且起了名字,都设置了默认值 -->
        <slot name="left"><span>左边</span></slot>
        <slot name="center"><span>中间</span></slot>
        <slot name="right"><span>右边</span></slot>
    </div>
</template>
<script src="./vue/vue.js"></script>
<script>
    const cpn = {
      
      
        template: "#cpn"
    }
    const app = new Vue({
      
      
        el:"#app",
        components:{
      
      
            cpn
        }
    })
</script>

编译作用域

要注意到当模板中使用实例中的属性或者方法时,当前模板是vue实例挂载的模板还是组件的模板。如果当前模板是vue实例模板,那么调用属性和方法时,一定是调用的当前vue实例的属性和方法。如果是组件模板,那么调用时,一定是调用的vue组件实例中的属性和方法。

<div id="app">
    <!-- 当前模板是 vue实例模板,那么调用vue实例的isShow -->
    <cpn v-show="isShow"></cpn> 
</div>

<template id="cpn">
    <!-- 当前模板是 组件实例模板,那么调用当前组件的isShow -->
    <div>
        <div v-show="isShow">
            <h2>我是子组件</h2>
            <p>我是内容</p>
        </div>
    </div>
</template>
<script src="./vue/vue.js"></script>
<script>
    const cpn = {
      
      
        template: "#cpn",
        data() {
      
      
            return {
      
      
                isShow: false   
            }
        }
    }
    const app = new Vue({
      
      
        el:"#app",
        components:{
      
      
            cpn
        },
        data:{
      
      
            isShow:true
        }
    })
</script>

作用域插槽的使用

如何能让插槽访问到子组件中的数据呢?

可以将子组件中的属性通过自定义属性名的方式传递给 slot插槽。

<div id="app">

    <!-- 使用的时候,我不想用firstName而是想用 lastName -->
    <cpn>
		<!--使用具名插槽绑定 center,并且将定义插槽时传过来的 user对象加入到 自定义的"uProp"对象中-->
        <template v-slot:center="uProp">
            <span>{
   
   {uProp.user.lastName}}</span>
        </template>
    </cpn>
</div>
<template id="cpn">
    <div>
        <!-- 这里默认定义使用子组件中的 firstName,那么我给 slot绑定一个自定义属性 :user
			将 子组件中的 user属性传递给了这个名为 center的插槽-->
        <slot name="center" :user="user">{
   
   {user.firstName}}</slot>
    </div>
</template>
<script src="./vue/vue.js"></script>
<script>
    const cpn = {
      
      
        template: "#cpn",
        data() {
      
       return {
      
      user:{
      
      firstName: "w", lastName:"lh"} }}
    }
    const app = new Vue({
      
      
        el:"#app",
        components:{
      
      
            cpn
        }
    })
</script>

解构插槽prop

<cpn>
    <!--使用具名插槽绑定 center,并且将定义插槽时传过来的 user对象加入到 自定义的"uProp"对象中-->
    <template v-slot:center="uProp">
        <span>{
   
   {uProp.user.lastName}}</span>
    </template>
</cpn>

此代码块中,uProp其实是一个对象,可以将这个对象拆分。

<cpn>
    <template v-slot:center="{user}">
        <span>{
   
   {user.lastName}}</span>
    </template>
</cpn>

也可以将里面的对象,重命名。

<cpn>
    <template v-slot:center="{user:person}">
        <span>{
   
   {person.lastName}}</span>
    </template>
</cpn>

甚至,还可以设置默认值,用于当插槽prop是 undefined 情况。

<cpn>
    <template v-slot:center="{user={firstName:'Guest'}}">
        <span>{
   
   {person.lastName}}</span>
    </template>
</cpn>

具名插槽的语法糖

v-onv-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header

<cpn>
    <template #header="{user}">
        <span>{
   
   {user.lastName}}</span>
    </template>
</cpn>

匿名插槽的缩写

其实同具名插槽一样,匿名插槽也是有名字的,名称都为 default,当使用匿名插槽的时候,甚至可以不使用<template></template> + v-slot,而是直接在组件上使用 v-slot即可。

组件模板定义为:

<template id="cpn">
    <div>
        <!-- 匿名插槽 -->
        <slot :user="user">{
   
   {user.firstName}}</slot>
    </div>
</template>

使用时:只用了 v-slot,没有使用template标签

<cpn v-slot="{user}">	<!--  写法v-slot等价于 v-slot:default  -->
    <span>{
   
   {user.lastName}}</span>
</cpn>
<cpn v-slot:default="{user}">
    <span>{
   
   {user.lastName}}</span>
</cpn>

语法糖:

<cpn #default="{user}">
    <span>{
   
   {user.lastName}}</span>
</cpn>

ES6模块化的导入导出

  • export : 导出
  • import : 导入

当使用模块化进行开发的时候,每个模块中(js文件中)的作用域都是互相独立的,不可能跨模块去访问到其他模块中的变量或者函数,必须通过export导出,将自己模块中的变量或者函数暴露给其他模块,然后其他模块通过import将这个模块中暴露出来的东西接收到,然后就可以使用了。

export

// 导出对象 es6的字面量增强写法
export {
    
    
	flag, sum
}

// 导出变量
export var num1 = 1000
export var height = 1.77

// 导出函数
export function a(n1, n2) {
    
    
    return n1 + n2;
}

某些情况系,一个模块中包含某个功能,我们并不希望给这个功能命名,而是让导入者可以自己来命名。这个时候就可以使用 export default,(在同一个模块中只能使用一次)但是只能导出一个。所以建议使用方式二,导出一个对象。

const address = "北京市"

// 方式一
export default address

// 方式二
export default {
    
    
    address, ...
}

import

import {
    
    flag, sum} from './index.js'
import num1 from './index.js'
import height from './index.js'
import a from './index.js'

// 调用a函数
a()

导入所有,并且起个别名,那么这个别名中包含了所有导出的数据。注意:这个别名是一个对象。

import * as aaa from './index.js'
aaa.flag
aaa.sum
aaa.a()

webpack(一)

前端模块化打包工具。开发中我们基于某些规范进行开发,比如es6的一些语法,但很可能别的浏览器中不支持这种语法,那么我们就需要webpack打包工具,将我们的项目打包成浏览器能够识别的一种资源。

webpack又依赖于nodejs环境,必须安装node,其中有一个npm包管理工具,用来管理node环境中的各种依赖包。

**首先安装好Node。**查看自己的node版本

node -v

然后使用npm命令安装 webpack打包工具

全局安装

npm install [email protected] -g

局部安装

  • –save : 局部安装
  • -dev : 指定环境
cd 对应目录下
npm install [email protected] --save-dev

为什么全局安装后,还需要局部安装?

  • 在终端直接执行webpack命令,使用的是全局安装的webpack
  • 当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部的webpack.

基本使用

使用组件化思想,开发。

比如,我有一个mathUtil.js文件,里面定义了一些函数。那么我如何去暴露给其他的模块?

commonjs写法

function add(num1, num2){
    
    
    return num1 + num2;
}
function mul(num1, num2){
    
    
    return num1 * num2;
}
// commonjs写法 导出
module.exports = {
    
    
    add,mul
}

在其他js中

const {
    
    add, mul} = require('./mathUtil.js')	// 引入
console.log(add(10,20))
console.log(mul(10,20))

写完之后,你会发现,浏览器根本不能识别这种写法…,那么我们就需要使用webpack把这些都打包起来,然后会生成一个dist目录,目录下就是已经打包好的文件,我们可以直接在html文件中引入这些即可,浏览器会识别这些已经被webpakc打包后的文件中的语法。

执行打包。

# 打包main.js文件,生成在 dist目录下的 bundle.js文件
webpack ./src/main.js ./dist/bundle.js

那么为什么只打包了main.js文件呢,那个mathUtil.js怎么不打包?

因为webpack不仅会帮我们进行模块打包,而且还会自动帮我们处理模块之间的依赖关系。main.js依赖到了mathUtil.js,那么webpack会自动帮我们都打包好。

这里打包报错的同学,请你回去老老实实的去使用webpack3.6.0的版本,只需要安装一个全局的就行了,这里只是作为学习使用的

打包后生成一个 js文件,然后我们直接引入这个文件就可以了。

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

es6写法

mathUtil.js

export default{
    
    
    add, mul
}

main.js

import math from './mathUtil' // 因为导出的是一个对象,我直接用一个对象接收
console.log(math.add(10,20))
console.log(math.mul(10,20))

写完后,再次执行 webpack打包

webpack ./src/main.js ./dist/bundle.js

总结:

其实上面说到的commonjs模块化写法和es6模块化写法,并不只局限于哪一种,甚至我们可以两种一起使用,因为最后webpack都会把它们打包成浏览器能够看懂的语法。

配置使用

webpack.config.js

使用webpack的配置来简化我们的webpack执行的命令。创建一个webpack.config.js

由于,我们需要到node中的path组件,我们需要先进行npm init进行下初始化

npm init

我们需要和终端进行交互,确认一些事项,然后完成后会生成一个 package.json的文件

这个文件,是用来记录我们的项目中的一些信息。

并且,当我们在package.json中增加了一些依赖后,需要执行 npm install,将这些依赖下载到项目中,执行后会生成一个package-lock.json的文件。

npm install

然后在 webpack.config.js中就可以使用 node中的相关组件

const path = require('path')	// 使用 commonjs模块化方式导入 path组件

module.exports = {
    
    		// 使用 commonjs模块化方式导出
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js'
    } 
}

在终端中直接执行 webpack,然后执行过程中,它会自动去找 webpack.config.js文件,找里面的打包入口和打包出口文件。

webpack

将webpack命令和npm run build映射(简化打包命令)

package.json

{
    
    
  "name": "demo2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    
    
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"	// 在scripts中定义一个 build,那么 npm run build的时候,它会去找scripts中的名为 build的脚本,然后发现脚本是 webpack ,直接执行
  },
  "author": "",
  "license": "ISC"
}
npm run build

即可。

局部安装webpack

一般地,我们安装的webpack有整个电脑全局的,也有只想为某个项目安装的webpack(局部的)。默认情况下,当我们在项目下执行webpack的一些命令时,它优先于项目局部的webpack,如果项目中没有安装webpack,那么它就去找整个电脑全局安装的 webpack。

npm install [email protected] --save-dev

执行完后,会发现,package.json中多出了

"devDependencies": {
    
    	// 就是dev(开发时)环境的依赖
    "webpack": "^3.6.0"
}

而且多了一个node_modules的目录,这个目录中存放着所有项目本地的依赖。

注意:我们在终端中执行的webpack命令是使用的全局的webpack命令,只有当我们进入项目下的node_modules下找命令时才是执行的项目本地的。当然还有一个方法,就是npm run 和 webpack进行一个映射,它会优先于找项目本地的webpack

流程梳理:终端执行 npm run build时,会去package.json中找响应的scripts脚本,然后找到了 webpack,再去webpack.config.js中找webpack具体的输入和输出位置,拼成命令然后执行。

webpack的loader–css处理

认识一下loader,loader是webpack中一个非常核心的概念。可以将项目中的 scss、less转为css,将TypeScript转为ES5代码,将.jsx、.vue转换为js文件等等

如何使用?

  • npm安装loader
  • 在webpack.config.js中的modules关键字下进行配置。

我们需要去安装所需要的loader。可去官网或中文网站查看,地址贴出来webpack中文网站

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

然后需要在webpack.config.js中配置module

const path = require('path')

module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js'
    },
    module: {
    
    
        rules: [
          {
    
    
            test: /\.css$/,
              // css-loader负责加载css, style-loader负责解析渲染html
              // 使用多个loader时,webpack读取时是从右向左读取的。
            use: [ 'style-loader', 'css-loader' ]
          }
        ]
      }
}

要注意use:[]中的loader的顺序,因为webpack是从右向左读取的,顺序不对很可能会报错的

然后,我们可以创建一个css文件,在main.js中把它当做模块导入一下。

// 依赖css文件,将css也当做一个模块
require('./css/normal.css')

后边,我们执行 npm run build即可。

如果执行后报错,Failed at the [email protected] build script.构建脚本的时候出现报错。

那么我们可以尝试将在package.json中,将css-loader和style-loader的版本调低

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

然后再下载一次依赖,即可

npm install

再次执行build,即可。

npm run build

less文件处理

假如项目中使用less、scss、stylus来写样式,webpack也可以帮我们处理。

创建一个less文件,special.less

@fontSize: 50px;
@fontColor: orange;
body{
    font-size: @fontSize;
    color: @fontColor;
}

在main.js中依赖(引入)less文件

require('./css/special.less')
document.writeln('<h2>你好啊,李银河</h2>')

下载相应的loader(less-loaderless)

npm install less-loader less --save-dev

在webpack.config.js中配置 module

要注意:里面需要3个loader,没有安装的需要先安装下style-loadercss-loader

module: {
    
    
        rules: [  
          // less相关的Loader
          {
    
    
            test: /\.less$/,
            use: [{
    
    
                loader: "style-loader" // creates style nodes from JS strings
            }, {
    
    
                loader: "css-loader" // translates CSS into CommonJS
            }, {
    
    
                loader: "less-loader" // compiles Less to CSS
            }]
        }
        ]
      }

贴一个兼容的版本,在package.json文件中

"devDependencies": {
    
    
    "css-loader": "^3.6.0",
    "less": "^3.9.0",
    "less-loader": "^4.1.0",
    "style-loader": "^0.23.1",
    "webpack": "^3.6.0"
  }

改好版本,记得npm install一下,安装一下相关的依赖。

打包即可。

npm run build

webpack图片文件类处理

例如有一个normal.css中引入了一个图片

body{
    
    
    /* background-color: red; */
    background: url(../img/test.jpg);
}

url-loader

基本使用

安装url-loader

npm install url-loader --save-dev

配置webpack.config.js

module: {
    
    
    rules: [
        {
    
    
            test: /\.(png|jpg|gif)$/,
            use: [
                {
    
    
                    loader: 'url-loader',
                    options: {
    
    	// 配置选项
                       	// 当图片,小于limit时,会将图片编译成base64字符串形式
                        // 大于limit时,会使用file-loader加载图片,所以要先把 file-loader安装一下
                        limit: 8192
                    }
                }
            ]
        }
    ]
}

当图片大于limit时,需要使用到 file-loader,所以安装一下 file-loader

npm install file-loader --save-dev

然后执行打包npm run build,执行完后,当图片大于limit的限制时,低版本的 file-loader很可能会出现404文件找不到的问题。

解决方案:

webpack.config.js中,配置文件

const path = require('path')

module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js',
        publicPath: 'dist/'
    }
}

再次 npm run build即可。

那么后面真正的项目上线,是需要把index.html都打包到dist目录中的,所以后面项目中和可能用不到这个publicPath属性。

处理文件名称、文件目录

打包图片等资源文件时会发现,webpack会自动把文件打包到dist目录中,并且会自动给我们默认生成一个文件名。这是一个32位hash值的文件名,防止名称重复。

我们可以在options中对文件做相关的配置,如处理文件名称,处理文件所属目录。

loader: 'url-loader',
    options: {
    
    
        limit: 8192,
            name: 'img/[name].[hash:8].[ext]'
    }

webpack将ES6转ES5的babel

webpack打包后的js文件中,写的ES6语法并没有转换为ES5,那么意味着可能一些对ES6还不支持的浏览器没有办法很好的运行我们的代码。

我们需要使用babel-loader来将ES6转换为ES5

安装:

npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

配置webpack.config.js

{
    
    
      // 匹配js文件
      test: /\.js$/,
      // 排除目录
      exclude: /(node_modules|bower_components)/,
      use: {
    
    
        loader: 'babel-loader',
        options: {
    
    
          presets: ['es2015']
        }
      }
    }

npm run build打包即可。

使用Vue的配置过程

通过npm安装vue,将vue当成了模块引入。因为后续在实际项目中用到的依赖,不必再设置为开发时依赖。

npm install vue --save

在main.js中引入vue

import Vue from 'vue'
const app = new Vue({
    
    
    el:"#app",
    data:{
    
    
        message:"你好vue"
    }
})

在index.html中使用

<div id="app">
    <h2>{
   
   {message}}</h2>
</div>

打包

npm run build

打开浏览器后,发现报错:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

vue在构建最后的发布版本时,有两种类型:

  • runtime-only : 代码中,不能有任何的 template,无法编译template
  • runtime-compiler : 代码中,可以有template,因为有complier可以用于编码template

我们可以指定使用的是runtime-compiler版本类型,需要在webpack.config.js中配置resolve

const path = require('path')

module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js',
        publicPath: 'dist/'
    },
    resolve:{
    
    
      alias:{
    
    
        // 当我们 import vue的时候,会去这个目录下找响应的vue发布版本
        'vue$': 'vue/dist/vue.esm.js'
      }
    }
}

再次打包即可。npm run build

创建vue实例时el和template

el是用来挂载一个块元素,将这个元素交给了vue来管理。但是实际开发中,我们不会在el所挂载的元素内做任何的改动,而是使用路由的方式来交替展示响应的内容。那么我们就可以将el挂载的元素中什么都不写。

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

然后在vue的实例中定义一个template模板,执行时这个定义好的模板会自动地将整个el挂载的元素替换掉。

import Vue from 'vue'
const app = new Vue({
    
    
    el:"#app",
    template: `
        <div>
            <h2>{
     
     {message}}</h2>
        </div>
    `,
    data:{
    
    
        message:"你好vue"
    }
})

vue使用方案

js导出组件

创建一个app.js文件,并导出一个组件对象。

export default {
    
    
    template: `
    <div>
        <h2>{
     
     {message}}</h2>
    </div>
    `,
    data(){
    
    
        return {
    
    
            message:"你好vue"
        }
    }
}

在main.js中使用这个组件对象。

import Vue from 'vue'
import App from './vue/app'

new Vue({
    
    
    el:"#app",
    template: '<App/>',
    components:{
    
    
        App
    }
})

index.html中

<body>
    <div id="app">
    </div>
    <script src="./dist/bundle.js"></script>
</body>

vue导出组件

创建一个app.vue文件,并且导出组件

<template>	<!-- 定义模板,相当于是组件的template属性 -->
    <div>
        <h2>{
   
   {message}}</h2>
    </div>
</template>

<script>
export default {
    name: "App",
    data(){
        return {
            message:"你好vue"
        }
    }
}
</script>

注意,打包vue文件需要使用相应的loader(vue-loadervue-template-compiler)

npm install vue-loader vue-template-compiler --save-dev

在webpack.config.js中配置rules:

{
    
    
    test: /\.vue$/,
        use: ['vue-loader']
}

配置完之后,如果你使用的是15及以上版本,那么很有可能会打包失败,因为高版本还需要依赖一个插件。

解决方案:

  • 降低版本
  • 安装插件

版本使用 13就行

"vue-loader": "^13.0.0"

记得npm install安装一下。

在main.js中使用

import Vue from 'vue'
import App from './vue/App.vue'

const app = new Vue({
    
    
    el:"#app",
    template: '<App/>',
    components:{
    
    
        App
    }
})

导入时如何省略 .vue后缀呢?在webpack.config.js中配置extensions属性

resolve:{
    
    
    // 导入时,可以省略 .vue .js 文件后缀
    extensions: ['.vue', '.js'],
        alias:{
    
    
            // 当我们 import vue的时候,会去这个目录下找响应的vue发布版本
            'vue$': 'vue/dist/vue.esm.js'
        }
}
import Vue from 'vue'
import App from './vue/App'

const app = new Vue({
    
    
    el:"#app",
    template: '<App/>',
    components:{
    
    
        App
    }
})

npm run build一下即可。

webpack(二)

plugin

一般对现有的框架进行扩展,webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等。

loader和plugin的区别:

  • loader主要用于转换某些类型的模块,它是一个转换器。
  • plugin是插件,它是对webpack本身的扩展,是一个扩展器。

如何使用plugin

  1. 通过npm安装需要使用的 plugins(某些webpack内置的插件不用安装)
  2. 在webpack.config.js中plugins中配置。

横幅plugin使用

为打包的文件添加版权声明,该插件的名称是 BannerPlugin,属于webpack自带的插件,那么直接使用就可以了。

webpack.config.js中配置。

const path = require('path')
const webpack = require('webpack')	// 引入webpack

module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js',
        publicPath: 'dist/'
    },
    plugins:[	// 声明plugins
        new webpack.BannerPlugin("最终版权归 xxx 所有。")
    ]
}

打包后,可看到打包文件中头部包含版权信息。

npm run build

在这里插入图片描述

HtmlWebpackPlugin

目前index.html是存放在根目录中的,但是真实的发布项目中,发布的是dist目录下的内容,但是dist中没有index.html文件,那么我们需要将 index.html打包到dist中,就需要使用到 HtmlWebpackPlugin插件。

HtmlWebpackPlugin插件的作用:

  • 自动生成一个index.html文件(可指定模板)
  • 将打包的js文件,自动通过script标签插入到body中,那么我们项目根目录下的index.html中就没有必要去手动导入js了

安装

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

在webpack.config.js中配置:

const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js',
        // 因为把index.html打包到了dist下,所有index.html再访问时就不用再加 dist/了
        // publicPath: 'dist/'
    },
    plugins:[
        new webpack.BannerPlugin("最终版权归 xxx 所有。"),
        new HtmlWebpackPlugin({
    
    
            // 设置一个模板,会去找当前webpack.config.js文件所在目录下的, index.html文件
            template: "index.html"
        })
    ]
}

打包

npm run build

如果发现有问题,打包不成功,可以尝试将 html-webpack-plugin插件版本调整一下,然后再次打包即可。

压缩js插件–Uglifyjs-webpack-plugin

安装

npm install [email protected] --save-dev

webpack.config.js配置

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const UglifyjswebpackPlugin = require('uglifyjs-webpack-plugin')

module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js'
        // publicPath: 'dist/'
    },
    plugins:[
      new webpack.BannerPlugin("最终版权归 xxx 所有。"),
      new HtmlWebpackPlugin({
    
    
        // 会去找当前webpack.config.js文件所在目录下的, index.html文件
        template: "index.html"
      }),
      new UglifyjswebpackPlugin()
    ]
}

重新打包即可

npm run build

js文件丑化后,会把一些空格、注释等给我们删除掉,也就是我们上面用的版本声明就没什么用了。

webpack-dev-server搭建本地服务器

webpack为我们提供了一个本地开发服务器,这个服务器基于nodejs搭建,内部使用了express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果。

安装

npm install [email protected] --save-dev

在webpack.config.js中配置 devServer,devServer也是webpack中的一个选项,有以下几种属性:

  • contentBase:为哪个文件夹提供本地服务,默认是根目录,我们填写 ./dist即可
  • port:端口
  • inline:是否页面实时刷新
  • historyApiFallBack:在SPA页面中,依赖HTML5的history模式
const path = require('path')
module.exports = {
    
    
    entry:'./src/main.js',   // 入口
    output:{
    
        // 输出到哪个文件中
        path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js'
        // publicPath: 'dist/'
    },
    devServer:{
    
    
      contentBase: './dist',	// 服务于 dist目录
      inline:true,	
      port: 5000	// 端口 5000
    }
}

启动服务,可以在package.json中再配置一条scripts脚本

"scripts": {
    
    
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "dev": "webpack-dev-server --open"	// 配置一条 dev脚本,并且 启动时自动打开浏览器
  }

执行启动服务

npm run dev

它会自动打开浏览器页面,当我们在根目录下修改js文件中的内容时,然后保存文件,webpack-dev-server插件会帮我们执行编译,实时刷新我们访问的页面了。

开发中我们经常使用这样的方式提高开发效率,当一切都已就绪(代码都开发完毕了)后,执行一次npm run build打包一下就可部署了。

webpack配置文件分离

有些插件、依赖只会在开发时用到,上线时根本没有用,那么我们希望将这些配置进行分离,可以理解为区分开发环境和生产环境的配置文件。

对 webpack.config.js进行抽离

  1. 我们可以在根目录下创建一个build目录,这个目录下存放一些配置文件相关的。

  2. 创建一个base.config.js文件,此文件存放 开发时生产时共用的一些配置。

    const path = require('path')
    const webpack = require('webpack')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const UglifyjswebpackPlugin = require('uglifyjs-webpack-plugin')
    
    module.exports = {
          
          
        entry:'./src/main.js',   // 入口
        output:{
          
              // 输出到哪个文件中
            path: path.resolve(__dirname, 'dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
            filename:'bundle.js'
            // publicPath: 'dist/'
        },
        // devServer:{
          
          
        //   contentBase: './dist',
        //   inline:true,
        //   port: 5000
        // },
        plugins:[
          new HtmlWebpackPlugin({
          
          
            // 会去找当前webpack.config.js文件所在目录下的, index.html文件
            template: "index.html"
          }),
          new UglifyjswebpackPlugin()
        ],
        resolve:{
          
          
          extensions: ['.vue', '.js'],
          alias:{
          
          
            // 当我们 import vue的时候,会去这个目录下找响应的vue发布版本
            'vue$': 'vue/dist/vue.esm.js'
          }
        },
        module: {
          
          
            rules: [
              ...
              {
          
          
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
          
          
                  loader: 'babel-loader',
                  options: {
          
          
                    presets: ['es2015']
                  }
                }
              },
              {
          
          
                test: /\.vue$/,
                use: ['vue-loader']
              }
            ]
          }
    }
    
  3. 创建一个生产时配置文件,prod.config.js

    const UglifyjswebpackPlugin = require('uglifyjs-webpack-plugin')
    module.exports = {
          
          
        plugins:[
          new UglifyjswebpackPlugin()
        ]
    }
    
  4. 创建开发时配置文件,dev.config.js文件,将属于开发时的配置放置在 dev.config.js中

    module.exports = {
          
          
        devServer:{
          
          
          contentBase: './dist',
          inline:true,
          port: 5000
        }
    }
    

此时,我们还没有将这些文件进行合并,我们需要安装一个依赖webpack-merge

npm install webpack-merge

在prod.config.js中

const UglifyjswebpackPlugin = require('uglifyjs-webpack-plugin')
const WebpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')

module.exports = WebpackMerge.merge(baseConfig,{
    
    	// 导出时合并 base.config.js和 prod.config.js
    plugins:[
      new UglifyjswebpackPlugin()
    ]
})

在dev.config.js中

const WebpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')

module.exports = WebpackMerge.merge(baseConfig, {
    
    
    devServer:{
    
    
      contentBase: './dist',
      inline:true,
      port: 5000
    }
})

注意:在高版本中 require('webpack-merge') 获取到的是一个对象,而不是函数。

配置文件分完之后,webpack.config.js文件就没有用处了,删了即可。因为package.json会去默认去找webpack.config.js,所以在package.json中配置webpack分环境的配置文件。

"scripts": {
    
    
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config ./build/prod.config.js",	// 指定生产环境
    "dev": "webpack-dev-server --open --config ./build/dev.config.js"	//指定开发环境
}

那么base.config.js中,需要把打包后的文件放到根目录下:

output:{
    
        // 输出到哪个文件中, ../:找上一级目录
        path: path.resolve(__dirname, '../dist'),     // 动态获取路径,拼接路径(这是一个决定路径)
        filename:'bundle.js'
        // publicPath: 'dist/'
    }

执行打包

npm run build
vue入门–基础命令+axios+案例练习
vue入门–vue常用属性、生命周期、计算属性、过滤器、组件、虚拟DOM、数组的响应式方法、页面闪烁、ES6简单语法增强
vue入门–js高阶函数(箭头函数)、v-model数据绑定、组件化、父子组件通信及访问
vue入门–插槽(具名、匿名、作用域插槽)+ES6模块化导入导出+webpack的使用(基本使用+配置使用+如何一步步演化成cli脚手架)+webpack插件使用(搭建本地服务器、配置文件分离)
vue-cli脚手架2版本及3+版本安装、目录解析、only和compiler的区别、3+版本如何改配置、箭头函数及this的指向
vue-router基本使用、路由传参、懒加载、嵌套路由、导航守卫、keep-alive
Promise基本使用、三种状态、链式调用及简写、all方法
Vuex的作用、使用、核心概念(State、Mutations、Getters、Actions、Modules)、文件抽离
axios网络请求基本使用、配置使用(全局axios和局部axios实例)、模块封装、axios拦截器

猜你喜欢

转载自blog.csdn.net/weixin_45248492/article/details/124980522