博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端与移动开发----Vue----vue配合webpack工程化实践
阅读量:119 次
发布时间:2019-02-26

本文共 16163 字,大约阅读时间需要 53 分钟。

Vue配合webpack工程化实践

回顾webpack

能够说出什么是前端工程化 能够说出 webpack 的作用 能够掌握 webpack 的基本使用 了解常用 plugin 的基本使用 了解常用 loader 的基本使用 能够说出 Source Map 的作用
采用工程化的方式来开发前端项目。区别于传统开发,工程化开发会有源文件和目标的概念,在开发阶段写源文件,在发布阶段时,用webpack进行打包,发布。 模块打包器。对模块进行打包。 1. 先要有一个项目(npm init)。2. 本地安装webpack。3. 根据webpack配置文件要求,去写各类配置:mode, entry, output, devtool, plugin, loader… 最终完成打包功能。 1. 安装2.wepback.config.js中去配置plugins. 3.每一个plugin都有自己的操作细节,要单独去学习使用(查官网)。 3. 常用的有:(1)清空打包目录(2)压缩 (3)抽取css到独立文件 (4)复制index.html到目录文件夹 1. 作用:去帮助webpack去加载非.js模块。 一个文件类型对应一个Loader。2.使用步骤:(1)下载安装(2)配置module,rules 3.每个Loader的使用细节都不一样。4. 常用的:css-loader, style-loader, less-loader, postcss-loader, file-loader,babel-loader,url-loader 帮助我们去调试代码。因为源文件打包成目标代码之后(多个文件混成了一个),不方便调试代码。可以用souce-map来对源代码和目标文件之间生成映射关系

hero案例-项目介绍

综合应用: vue, 组件,路由,webpack

在这里插入图片描述

功能介绍:

  • 三个模块
    • 英雄列表(只做这个)
    • 装备列表
    • 技能列表
  • 英雄列表
    • 列表组件
    • 删除功能
    • 添加组件
    • 编辑组件

回顾为什么要讲webpack?

在这里插入图片描述

在这里插入图片描述

用webpack搭建开发环境

用webpack搭建一个支持单文件组件(一个组件就放在一个文件中)的开发环境。

目录结构

在这里插入图片描述

创建一个空文件夹,并做初始化

建立文件夹,名为heros,在文件夹下,做npm init --yes

在这里插入图片描述

安装包

安装需要用到的各种包。

### 开发依赖npm i html-webpack-plugin vue-loader vue-style-loader vue-template-compiler webpack@4.44.2 webpack-cli@3.3.12 webpack-dev-server -D### 生产依赖npm i vue
  • html-webpack-plugin: 1.把指定的模板拷贝到打包出口。2. 自动插入打包后的资源地址
  • vue-loader vue-style-loader vue-template-compiler : 用它们用来处理.vue文件(webpack是不支持.vue的,所以需要用loader)
  • webpack@4.44.2 webpack-cli@3.3.12 : 要用webpack必须要先安装它们。这里指定版本的原因是:如果不指定,会默认安装最新版本,目前最新版与webpack-dev-server有些不兼容。
  • webpack-dev-server: 在开发阶段,在内存中实时打包,更新显示结果。
  • -D: (前面有一个空格)它表示开发依赖。
    • 生产依赖:房子卖出去了,现在已经住人了,就不需要挖掘机了。 线路,下水道还是需要的。(线路,下水道 就是生产依赖)
    • 开发依赖:在建房子的过程中,要用到挖掘机。建房子的过程是依赖于挖掘机。 (挖掘机就开发依赖);在建房子的过程中,需要线路,下水道…
  • npm i vue: 下载使用vue.js。与我们之前使用vue.js不同(我们之前是直接script src=“xx.vue.js”),现在有了webpack及nodejs项目,就可以用更高级的方式来使用。 不加-D:项目开发完成,这个包还是要用到的。

配置webpack.config.js

在根目录下,创建一个名为webpack.config.js的文件,内容如下:

  • 入口
  • 出口
  • devServer
  • .vue的loader
  • HtmlWebpackPlugin
const path = require('path')const VueLoaderPlugin = require('vue-loader/lib/plugin')const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {
// 配置 webpack-dev-server的选项 devServer: {
host: '127.0.0.1', // 配置启动ip地址 port: 10088, // 配置端口 open: true // 配置是否自动打开浏览器 }, output: {
// 拼接一个绝对路由 path: path.join(__dirname, './dist'), filename: 'bundle.js' }, entry: './src/main.js', // 入口 // 插件来于拓展webpack功能 module: {
rules: [ {
test: /\.vue$/, use: 'vue-loader' } ] }, plugins:[ new HtmlWebpackPlugin({
minify: {
// 压缩HTML文件 removeComments: true, // 移除HTML中的注释 collapseWhitespace: true, // 删除空白符与换行符 minifyCSS: true// 压缩内联css }, filename: 'index.html', // path.resolve()就是转成绝对路径 template: path.resolve('./public/index.html') // 指定模板的位置 }), new VueLoaderPlugin() ]}

创建模板文件

在根目录下,创建public/index.html ,内容如下:

    
Document

在html-webpack-plugin工作时,把它拷贝到指定的出口文件夹下。

创建入口文件

在根目录下,创建: src/main.js 。内容如下:

// 入口文件// import es6的模块化, 用来导入另一个模块// 引入根组件import app from './app.vue'// console.log(app)import Vue from 'vue'new Vue({
// 这是Vue的配置项,名是render,值是一个函数。 // 功能: 把app这个组件手挂载到vue实例 ------ vue实例中就只一个根组件 render: function (h) {
return h(app) }}).$mount('#app')// #app: 就是public/index.html中的div

创建vue根组件

在src下面创建app.vue文件, src/app.vue 它的后缀名是.vue,需要在vscode中安装插件(vetur)才可以正确显示出来代码高亮效果。

内容如下:

下面是建议安装vscode拓展:

在这里插入图片描述

补充一个dev命令

在这里插入图片描述

启动项目

运行 npm run dev。 这里的dev就是上面在package.json中指定的属性名,当然,你也可以换成其它的名字。

在这里插入图片描述

验收成果

在这里插入图片描述

单文件组件(SFC)

single file component

用一个.vue为后缀的文件来声明一个组件,在webpack的加持下解析这个文件。

在这里插入图片描述

以前定义组件

// 全局注册组件Vue.component('com-a',{
// 组件配置对象 template: '
组件结构
'})new Vue({
// 局部注册组件 components: {
'com-b': {
// 组件配置对象 template: '
组件结构
' } }})

无论是何种注册方式,每个组件必须有一个组件配置化对象。

现在定义组件

在vue-loader 配合webpack中

  • 以 .vue 文件的方式来定义组件,文件的内容代表的是:组件配置对象,称为:单文件组件。
  • 共有三个部分
    • template(必须 ): 约定这个组件的视图
    • script(可选): 设置除了template之外的组件配置项,并默认导出
    • style(可选 ): 用来组件中元素的样式(注意css-loader, style-loader的使用)
  • 需要渲染这个组件
    • 使用这个配置对象进行 全局注册 或者 局部注册,再来使用。
    • 使用路由规则中的 component 选项指定路由配置对象。

.vue文件的格式:

// 相对于组件配置对象中 template 选项,声明组件结构。
// 如果有其他的配置选项,需要默认导出一个对象,在对象中声明其他配置选项// 当前组件需要样式

用这种方式定义组件,结构 逻辑 样式 分工明确,非常清晰,便于维护。

  • style中scoped属性作用:限制样式在当前组件下生效。

单文组件必须要有配置的环境来支持,在浏览器直接使用是不行的。

ES6模块化

es6的模块 — 与vue无关

webpack与vue无关

不要认为 学习了es6的模块化,webpack只能在vue中使用!

什么是模块化

目标:让一个.js文件(A.js)中可以引用另一个.js文件(B.js)中的代码

模块: 就是一个文件。

模块化的规范:

  • commonjs 规范。nodejs中是commonjs规范。
  • es6规范。ECMAScript规范。

在nodejs中,模块化规范:CommonJS

  • 导出:module.exports = '导出的内容' exports.xxx = '导出的内容'
  • 导入:const path = require('path')

nodejs中的模块化与es6中的模块化是不同的。

ES6模块化

ES6也提供了模块化规范:ES6模块

  • 默认导入与导出
    • 导出:export default 导出内容
    • 导入:import 变量名 from 'js模块路径'
  • 按需导入与导出
    • 导出:
      • export const 成员变量名1 = '导出内容1'
      • export const 成员变量名2 = '导出内容2'
    • 导入:import {成员变量名1} from 'js模块路径'

基本步骤

(1) 先导出

(2) 再导入

定义模块: src/es6module/a.js

  • 创建一个.js文件,其中,写一些变量,函数…
// 创建一个模块// 如何把es6module/a.js中的fn这个函数给main.js中去使用?const a = 100function fn(x,y) {
return x + y}

导出模块

// 创建一个模块// 如何把es6module/a.js中的fn这个函数给main.js中去使用?// const a = 100function fn(x,y) {
return x + y}// 导出模块中的fnexport {
fn }

导入模块

main.js

import {
fn } from './es6module/a.js'console.log(fn(100,200)) // 300

默认导入与导出

module-a.js

// 模块a  默认导出// 可以导出任何格式的内容:字符串  数字  函数  对象  数组 ...export default {
name: '模块A', attr: '属性'}

main.js

import obj from './module-a'console.log(obj) // {name: "模块A", attr: "属性"}

按需导入与导出

导出

module-b.js

// 模块B  按需导出export function fn(x,y) {
return x + y}export function fn1(x,y,z) {
return x + y +z}export const a = 314

另一种写法:

function fn(x,y) {
return x + y}function fn1(x,y,z) {
return x + y +z}const a = 314export {
fn, fn1, a}

导入

按需

main.js

// 按需导入import {
a,b} from './module-b'console.log(a,b)

你要提前知道在导出时,它们是不是叫a,b。

整体导入

// 按需导入(全部成员导入)import * as all from './module-b'console.log(all) // 收集了所有成员的变量(对象)

默认导出和按需导出共存

module-c.js

// 混合导入//  同时有默认导出和 按需导出const fn = function(x,y) {
return x + y}const a = 100const fn1 = function(x,y,z) {
return x + y+z}// 按需导出export {
a, fn1}// 默认导出export default {
fn}

main.js

// 有混合导入import obj, {
fn1} from './es6module/c.js'// 有混合导入, 也可以拆开写// import obj from './es6module/c.js'// import {fn1} from './es6module/c.js'console.log(obj,fn1)

导入导出重命名

一个名字在a.js中导出也是这个名字;

在main.js中也有一个名字与之重复了,此时就要改名字,有两个地方可改名字:

  • 在a.js中导出时改下名字
  • 在main.js中导入时改下名字
export {
xxx as 新名字}# 导入重命名import {
xxx as 新名字}
// tool.jsconst fn = function(x,y) {
return x + y}// 导出重命名export {
fn as f2}// index.jsimport {
f2 as f1} from "./tool.js"

代码工作原理

在这里插入图片描述

引入bootstrap,改造app.vue

导入bootstrap到项目中

直接在public/index.html中引入bootstrap的样式即可

  
Document

改写src/app.vue

从示例代码中把基本的html结构复制过来。

container,col-md-2,col-md-10 都是在boostarp.css中要用到的class。

实现顶部通栏组件

分析布局:

在这里插入图片描述

创建组件

src/components/header.vue按boostrap样式要求,完成dom

对于.vue而来,如果不写script项,则相当于一个默认导出。

在app.vue中引入组件

步骤:

  1. 导入
  2. 注册组件
  3. 在模板中使用

实现左侧侧边栏组件

创建组件

src/components/sideBar.vue按boostrap样式要求,完成dom

在app.vue中引入组件

步骤:

  1. 导入
  2. 注册组件
  3. 在模板中使用

实现路由

目标

  • 在支持左侧边栏中的链接显示不同的内容
  • 在点击添加,编辑时显示不同的内容

思路

引入vue-router

配置路由规则

在根组件中添加router-view

给左侧添加声明式路由导航

基本步骤

  1. 安装vue-router

    vue-router是vue的插件,我们通过npm包的方式来加载(在.html中,是通过srcript 的src属性来加载的)

npm i vue-router
  1. 导入并注册插件

    main.js

import VueRouter from 'vue-router'Vue.use(VueRouter) //注册插件(**重要**)
  1. 准备页面组件

src下创建pages文件夹,并在下面放置三个组件,分别表示路由切换时的三个页面:

src/pages/index.vuesrc/pages/add.vuesrc/pages/edit.vue

每个页面组件中,都只需要维持基本内容即可。

  1. 导入组件,初始化路由插件,路由规则配置

    main.js中

// 提前定义好三个组件,以备在路由中使用import Index from './pages/index.vue'import Add from './pages/add.vue'import Edit from './pages/add.vue'// 创建路由实例,定义路由规则const router = new VueRouter( {
routes: [ {
path: '/', component: Index }, {
path: '/add', component: Add } ]})
  1. 把vueRouter挂载在vue实例上
new Vue({
render: h => h(App), router: router}).$mount('#app')
  1. 在根组件中,使用router-view设置路由出口

App.vue

7.直接在地址栏中进行测试

http://127.0.0.1:10088/#/

http://127.0.0.1:10088/#/add

修改左侧导航组件

在components/MyAside.vue中,使用router-link替换之前的a。

再次点击测试。

1.当前激活的路由导航链接会多出一个特殊的类名:router-link-exact-active 。根据它来设置高亮效果。

对应修改路由配置

// 入口文件// import es6的模块化, 用来导入另一个模块// 引入根组件import app from './app.vue'import Vue from 'vue'import Index from './pages/index.vue'import Add from './pages/add.vue'import Assets from './pages/assets.vue'import Skills from './pages/skills.vue'// 1.导入包import VueRouter from 'vue-router'// 以vue插件的方式去引入vueRouter到vue中// 2. 使用插件Vue.use(VueRouter)// 3.创建路由对象const router = new VueRouter({
routes: [ // 重定向 {
path: '/', redirect: '/hero' }, {
path: '/hero', component: Index }, {
path: '/add', component: Add }, // 装备管理 {
path: '/assets', component: Assets }, // 技能管理 {
path: '/skills', component: Skills } ]}) // 4. 在vue实例中使用new Vue({
router: router, // 这是Vue的配置项,名是render,值是一个函数。 // 功能: 把app这个组件手挂载到vue实例 ------ vue实例中就只一个根组件 render: function (h) {
return h(app) }}).$mount('#app')// #app: 就是public/index.html中的div

工作原理小结

在这里插入图片描述

提取router/index.js

分析:

在main.js中涉及路由代码太多,有必须提练一下。

思路:

  • 把与路由相关的代码,提取出来,写在src/router/index.js中;

  • 在main.js中引入它

操作:

(1)新建 src/router/index.js,写入代码如下:

import Vue from 'vue'// 引入路由import VueRouter from 'vue-router'// 注册插件// Vue.use(插件) : 把这个插件的功能集成到vueVue.use(VueRouter)import Index from '../pages/index.vue'import Add from '../pages/add.vue'import Assets from '../pages/assets.vue'import Skills from '../pages/skills.vue'const router = new VueRouter({
routes: [ {
path: '/', component: Index }, {
path: '/add', component: Add }, {
path: '/assets', component: Assets }, {
path: '/skills', component: Skills } ]})export default router

注意一下:组件文件的路径关系。

(2) 在main.js中引入

// 入口文件// import es6的模块化, 用来导入另一个模块// 默认导入,引入根组件import app from './app.vue'// console.log(app)// "vue"是我们之前npm i vue时下载的,它相当于是第三个模块,所以不需要加相对路径// 其实,这里的vue来自:node_modules\vue\dist\vue.runtime.common.jsimport Vue from 'vue'import router from './router/index.js'const vm = new Vue({
// render:这是Vue的配置项(el, data,computed....),名是render,值是一个函数。 // 功能: 把app这个组件手挂载到vue实例 ------ vue实例中就只一个根组件 render: function(h) {
return h(app) }, router: router})vm.$mount('#app')

关系图

在这里插入图片描述

json-server模拟接口

json-server 是一个全局安装的工具,用来把.json快速生成RESTful风格的接口。

在前面的学习中,已经全局安装过。

建立目录mockdata,在下面放置一个db.json文件,内容如下:

|-src|-src\mockdata\db.json

内容:

{
"heroes":[ {
"id":10000, "heroName": "安妮", "gender": "女", "cTime": "2010-10-10 10:10:10" }, {
"id":10001, "heroName": "德玛西亚", "gender": "男", "cTime": "2014-10-10 10:10:10" }, {
"id":10002, "heroName": "刘三姐", "gender": "女", "cTime": "Fri Apr 17 2020 16:24:42 GMT+0800 (中国标准时间)" }, {
"id":10003, "heroName": "超人", "gender": "男", "cTime": "2020/10/10 10:10:10" } ]}

在 db.json 的位置启动数据接口服务器:json-server db.json

在这里插入图片描述

验证一下:

在这里插入图片描述

在项目运行过程,不能关闭这个服务。

安装并使用axios

在项目中通过npm i axios安装axios,方便我们来获取json-server接口服务器中数据。

安装

之前是<script src='axios的地址'> 来使用axios的,现在要通过第三方包的方式来下载使用。

项目目录下运行如下命令:

npm i axios

结果:

+ axios@0.21.1added 4 packages from 7 contributors in 26.593s

使用

在src/pages/hero/index.vue中,测试axios的使用

通过click事件来测试使用。

在浏览器的network面板观察请求是否发出。

获取并显示数据

  • 补充一个方法loadHeros用来发ajax请求,获取数据,并保存到数据项中。

  • 在钩子函数 created中调用它

  • 显示数据

文件:src/pages/index.vue

根据数据进行渲染

注意:

  • key的使用

删除功能

在这里插入图片描述

实现大致步骤:

  1. 绑定点击事件
  2. 弹出确认框
  3. 点击确认,上传请求
  4. 删除成功,更新列表

src/page/index.vue

             

补充一个做删除的方法:

hDelete (id) {
const res = window.confirm('你确定要删除吗?') if(!res) {
return } // json-server时,它会自动会生成restful风格的接口 // 它用来作删除的接口就是这样要求的 axios({
method: 'DELETE', url: 'http://localhost:3000/heroes/' + id }).then(res => {
console.log(res) this.loadData() }) },

添加功能

由于这个添加功能比较复杂,不方便与列表页做在一起,这里单独来设置一个页面组件来实现添加功能。

实现大致步骤:

  1. 将英雄列表组件,添加按钮改成router-link,跳转到 /add 路由地址。
  2. 定义路由规则,创建添加组件,指定这个添加组件。
  3. 完成添加组件中的基础布局(表单),双向绑定表单元素。
  4. 监听表单提交事件,调用添加接口,进行添加操作。
  5. 成功的时候:跳转到英雄列表组件。失败:错误提示。

准备页面组件和路由

页面

新增文件:src/pages/add.vue

补充路由跳转链接

pages/index.vue

添加英雄
或者:添加英雄

实现功能

  1. 添加v-model,给表单元素添加双向绑定 ,以获取用户输入的数据
  2. 添加button添加点击事件,提交ajax

heroAdd.vue

编辑功能

实现大致步骤:

  1. 在英雄列表,给编辑按钮绑定点击事件,跳转到编辑组件/hero/edit/:id
  2. 创建编辑组件,配置路由规则,使用的动态路由规则
  3. 完成编辑组件中的基础布局(表单),双向绑定表单元素。
  4. 在组件初始化的时候,获取当英雄数据,填充给表单。
  5. 监听表单的提交事件,进行编辑请求的发送。
  6. 成功:跳转英雄列表进行预览,失败:错误提示。

准备页面组件和路由

页面组件

新增:src/pages/edit.vue

编辑英雄

设置路由

router/index.js

+ import Edit from './pages/edit.vue'const router = new VueRouter({  routes: [    // ...+    { path: '/edit', component: Edit },  ]})

补充路由跳转

落地项目代码:

src/pages/index.vue

    

实现功能

思路:

1.发一次请求,根据id获取这个英雄的详情并显示出来

2.用户在此基础上进行修改,并提交数据。

显示初值

思路:

发一次请求,根据id获取这个英雄的详情并显示出来

要点:

  • 定义数据项,在表单元素进行双向绑定。
  • 定义loadDetail访求,根据id获取详情。
  • 在created中去调用loadHeroById
data () {
return {
hero: {
gender: '', heroName: '' } } },created () {
this.loadDetail() }, methods: {
loadDetail() {
axios({
method: 'GET', url: 'http://localhost:3000/heroes/' + this.$route.query.id }).then(res => {
console.log(res) // 保存到数据项中 this.hero.gender = res.data.gender this.hero.heroName = res.data.heroName }) } }

视图

实现保存

用户在页面上进行修改,点击保存,把改动通过axios调用接口,实现保存。

  • 给按钮添加click事件。
  • 在回调函数中:
    • 收集用户信息
    • 判空
    • 调用接口
hModify () {
// 收集表单的信息 const {
heroName, gender} = this.hero // 检验有效性 if (heroName === '') {
alert('名字不能为空') return false } // ajax提交 axios({
method: 'PUT', url: 'http://localhost:3000/heroes/' + this.$route.query.id, data: {
heroName, gender, cTime: Date.now() // 获取当前的时间戳 } }).then(res => {
// 跳回主页 // console.log(res) this.$router.push('/') }).catch(err => {
alert('添加失败') console.log(err) }) }

如有不足,请多指教,

未完待续,持续更新!
大家一起进步!

转载地址:http://rcku.baihongyu.com/

你可能感兴趣的文章