您现在的位置是:首页 >技术杂谈 >Web前端-Vue2.0框架学习网站首页技术杂谈

Web前端-Vue2.0框架学习

GY-93 2023-06-02 16:00:02
简介Web前端-Vue2.0框架学习

1. 前端工程化与Webpack

webpack: 是前端项目工程化的具体解决方案,其主要功能,是提供了友好的前端模块化开发支持以及代码压缩混淆、处理浏览器端JavaScript的兼容性、性能优化等强大的功能。 目前Vue,React等前端项目,基本都是基于webpack工程化开发

1.1 隔行变色的demo实现

在这我们使用一个demo(创建列表隔行变色项目)来说明webpack的基本使用方法:

  1. 新建一个项目空白目录, 并运行npm init -y命令,初始化包管理配置文件package.json
  2. 新建src源代码目录
  3. 新建src-> index.html首页和src->index.js脚本文件
  4. 初始化首页基本结构
  5. 运行npm install jquery -S命令,安装jQuery。之前我们都是直接下载jQuery文件拷贝到项目,这里直接使用npm命令安装。
  6. 通过ES6模块化的方式导入jQuery,实现列表隔行变色效果

注意: -S 是–save的缩写, 是告诉 npm把包安装到dependencies目录下

在这里插入图片描述

上述效果直接运行把如图的错误, 浏览器的兼容性错误。

1.2 webpack的基本使用

webpack的安装: 我们可以在终端运行如下命令,安装webpack相关的两个包:npm install webpack@5.42.1 webpack-cli@4.7.2 -D

注意:-D 是 --save-dev的简写 是告诉npm把该包安装在devDependencies目录下, 只在开发模式下使用

  • 在项目根目录中,创建名为webpack.config.js的webpack配置文件,并初始化如下配置
// 使用Node.js中的到处语法,向外到处一个webpack的配置对象
module.exports = {
    // mode用来指定构建模式, 可选值 development 和 production
    // 开发时一定要用development,因为追求的是打包的速度,而不是体积
    // 反过来,发布上线的时候一定能要用production,因为上线追求的是体积小,而不是打包速度
    mode: 'development'
}
  • package.json的scripts节点下,新增dev脚本如下
"scripts": {
	// 自定义脚本: dev(脚本名称) , npm run dev 执行名称为dev的脚本
    "dev" : "webpack"
  },
  • 在终端中运行npm run dev命令,启动webpack进行项目的打包构建

运行npm run dev 报如下错误:
在这里插入图片描述
原因: node.js版本太高, 本人这里是v18.12.1, 我这里解决是把node.js的版本降低到v16.19.1

注意: webpack.config.js配置文件是在npm run dev时,执行dev脚本文件之前,会读取这个配置文件的内容, 然后根据配置文件的内容来打包运行项目

1.3 webpac插件

  • 在webpack4.x和5.x的版本中,有如下默认约定:
    • 默认打包入口文件为scr -> index.js
    • 默认的输出文件路径 dist -> mani.js
    • 注意: 我们也可以在webpack.config.js中修改打包的默认约定

在webpack.config.js配置文件中,通过entry节点指定打包的入口。通过output节点自定打包的出口

const path = require('path')
module.exports = {
    // mode用来指定构建模式, 可选值 development 和 production
    mode: 'development',
    entry: path.join(__dirname, './src/index.js'),// 打包入口文件的路径
    output: {
        path: path.join(__dirname, './dist'), // 输出文件的存放路径
        filename: 'bundle.js' // 输出文件的名称
    }
}

1.3.1 webpack-dev-server插件

webpack插件: 通过安装和配置第三方的插件,可以拓展webpack的能力,从而让webpack用起来更方便。最常用的webpack插件有如下两个:

  • webpack-dev-server : 类似node.js阶段用到的nodemon工具, 每当修改了源代码,webpack会自动进行项目的打包盒构建。安装命令:npm install webpack-dev-server@3.11.2 -D
  • 配置webpack-dev-server:
    • 修改package.json -> scripts 中的dev 命令如下"dev": "webpack serve"
    • 在此执行npm run dev
    • 在浏览器中http://localhost:8080/地址,查看自动打包效果
    • 注意:webpack-dev-server会启动一个实时打包的http服务器

当我们配置好package.json文件之后,执行npm run dev命令可能发生如下错误, 产生原因可能是没有安装webpack-cli库或者是webpack-cli库的版本过低导致
在这里插入图片描述

  • 注意(再次执行npm run dev 后):
    • 可以发现页面已经运行在http://localhost:8080/上了
    • 之前输入在dist的文件下的bundle.js 文件, 直接输入在/跟路径下面了,并且是隐藏文件,我们看不到的, 但是我们可以直接使用

在这里插入图片描述

由上面结果可知webpack-dev-server 插件并没有把生成的bundle.js文件放到物理磁盘,而是直接放到内存中

1.3.2 html-webpack-plugin

html-webpack-plugin: webpack中的html插件(类似一个模版引擎插件),可以通过此插件自定制index.html页面的内容
终端执行命令npm install html-webpack-plugin@5.3.2 -D

在webpack.config.js配置文件中配置该插件:
在这里插入图片描述

当我们执行npm run dev之后,点击http://localhost:8080/之后不会出现,需要我们选择的页面,而是直接展示index.html页面。

  • html-webpack-plugin插件做的事情:
    • 通过HTML插件复制到项目根目录中的index.html页面,也被放到了内存中
    • HTML插件生成的index.html页面自动注入了打包的bundle.js文件

在这里插入图片描述

我们可以在webpack.config.js配置文件中,可以通过devserver节点对webpack-dev-server插件进行更多的配置,示例代码如下:
在这里插入图片描述
注意: 凡事修改了webpack.config.js配置文件,或修改了package.js配置文件,必须重启实时打包的服务器,否则最新的配置文件无法生效

1.4 webpack中的loader(加载器)

在实际开发过程中,webpack默认只能打包处理.js后缀名结尾的模块。其它非.js后缀名结尾的模块,webpack默认处理不了,需要调用loader加载器才可以正常打包,否则会报错!

loader加载器的作用:协助webpack大包处理特定的文件模块。比如:

  • CSS-loader可以处理打包.css相关的文件
  • less-loader可以打包处理.less相关文件
  • babel-loader可以打包处理webpack无法处理的高级JS语法

loader的调用过程:
在这里插入图片描述

1.4.1 css-loader

// 导入样式(在webpack中一切皆模块,都可以ES6导入语法进行导入和使用)
// 如果某个模块中,使用from接收到的成员为undefined,则没有必要进行接收
import '../css/index.css'

当我们在index.js中导入.css文件时报如下错误:
在这里插入图片描述
安装处理.css文件的loader:

  • 运行npm install style-loader@3.0.0 css-loader@5.2.6 -D 命令,安装处理css文件的loader
  • 在webpack.config.js的module ->rules数组中添加laoder规则如下:
	module.exports = {
    module: { //所有第三方文件模块的匹配规则
        rules: [ // 文件后缀名的匹配规则
            {test: /.css$/, use:['style-loader', 'css-loader']}
        ]
    }
}

其中test表示匹配的文件类型use表示对应要调用的loader
注意: use数组中指定的loader顺序是固定,多个loader的调用顺序是从后往前调用

  1. webpack默认只能打包处理.js结尾的文件,处理不了他后缀的文件
  2. 由于代码中包含了index.css这个文件,因此webpack默认处理不了
  3. 当webpack发现某个文件处理不了时候,会查找webpack.config.js这个配置文件,看module.rule数组中,是否匹配了对应的loader加载器
  4. webpack是把index.css这个文件,先转交给最后一个loader进行处理(先转交给css-loader)
  5. 当css-loader处理完毕之后,会把处理的结果,转交给下一个loader(转交给style-loader)
  6. 当style-loader处理完毕之后,发现没有下一个loader了,于是把处理的结果,转交给webpack
  7. webpack把style-loader处理的结果,合并到/dist/bundle.js中,最终生成打包好的文件

在这里插入图片描述

1.4.2 less-loader

  1. 运行npm install less-loader@10.0.1 less@4.1.1 -D 命令
  2. 在webpack.config.js的module -> rules数组中,添加loader规则如下:
module: { //所有第三方文件模块的匹配规则
        rules: [ // 文件后缀名的匹配规则
            {test: /.less$/, use:['style-loader', 'css-loader', 'less-loader']},
        ]
    }

1.4.3 url-loader & file-loader (处理url路径相关的文件)

在HTML页面中,例如icon图标,可以转换成base64字符串,如果是直接图片路径下载的话,浏览器需要多发送一个请求。 但是如果我们直接使用base64字符串来加载的话,在你请求网页的时候,就会直接把把图片解析展示出来,而不是请求完网页,在发送一次图片的请求。

如果你的icon图片很多,那么可以省略很多次图片的请求, 这也是网页性能优化的一个点。但是base64字符串方式有个缺点,就是图片转换成base64字符串之后,体积会变大,所以大图片不是适合转换base64字符串。

icon小图片的优化,除了使用base64字符串的方式,还可以使用精灵图。

在这里插入图片描述
我们可以安装一个专门处理URL和文件的插件:

  1. 运行npm install url-loader@4.1.1 file-loader@6.2.0 -D 命令
  2. 在webpack.conig.js的module -> rules数组中,添加loader规则如下:
	module: { //所有第三方文件模块的匹配规则
        rules: [ // 文件后缀名的匹配规则
        // 如果需要调用loader只有一个,则只传递一个字符串也行,如果有多个loader,则必须指定数组
            {test: /.jpg|png|gif/, use: ['url-loader?limit=2222']},
        ]
    }

其中之后的是loader的参数项

  • limit用来指定图片的大小,单位是字节(byte)
  • 只有<=limit大小的图片,才会被转换成base64格式的图片

在这里插入图片描述

1.4.4 打包处理js文件中的高级语法

webpack只能打包处理一部分高级的JavaScript语法。对于那些webpack无法处理的高级js语法,需要借助与babel-loader进行打包处理。例如webpack无法处理下面JavaScript代码:

$(function(){
    
    $('li:odd').css('background-color','red')
    $('li:even').css('background-color', 'green')
})


// 定义名为info的装饰器
function info(target) {
    // 为目标添加静态属性 info
	// 装饰给谁用, target就只像谁
    target.info = 'Person info'
}

// 为Person类 应用info装饰器
@info 
class Person {}

// 打印Person 的静态属性 info
console.log(Person.info);

在这里插入图片描述
装饰给谁用, target指向谁 这里 targer指向person

运行命令安装对应依赖包:npm install babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D
在webpack.config.js的module -> rules数组中,添加到loader规则如下:

module: { //所有第三方文件模块的匹配规则
        rules: [ // 文件后缀名的匹配规则
        // 注意必须使用排除项,因为node_modules目录下的第三方包不需要被打包, 因为第三方中的js兼容性,不需要程序员关心
            {test: /.js$/, use: 'babel-loader', exclude: '/node_modules'},
        ]
    }

在项目的根目录下,创建名为babel.config.js的配置文件,定义Babel的配置项如下:

module.exports = {
    plugins: [
        // 声明babel可用插件, 将来webpack在调用babel-loader的时候,会先加载plugins差价来使用
        ["@babel/plugin-proposal-decorators", { legacy: true }]
    ]
}

详情参考Babel的官网地址:babel-loader的官网地址

1.5 打包发布

配置webpack的打包发布:

  1. package.json文件的scripts节点下,新增build命令如下:
"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "dev": "webpack serve", // 开发环境中, 运行dev命令 在开发环境中加入serve指定是把打包的文件放到内存中,并没有放到物理磁盘中
    "build": "webpack --mode production" // 项目发布时,运行build命令 。 不需要serve指定,项目发布中需要把文件打包在物理磁盘上。然后发送到后台发布
  },

--mode 是一个参数项,用来指定webpack的运行模式production代表生产环境,会对打包生成的文件进行代码压缩性能优化
注意: 通过 --mode 指定的参数项, 会覆盖webpack.config.js中的model选项

当我们执行npm run build指令后,生成的dist的结构目录如下:
在这里插入图片描述
我们会发现所有的文件全都在一个文件下,这样看起来会很混乱,我们可以在webpack.config.js配置文件中配置,把文件分类生成到不同的子目录下:
在这里插入图片描述

图片文件楚了上面配置方法,还可以这样配置{test: /.jpg|png|gif/, use: 'url-loader?limit=2222&outputPath=image'},
配置文件后,再次执行命令npm run build后生成的目录如下:
在这里插入图片描述

为了在每次打包发布时自动清理掉dist目录中的旧文件,可以安装并配置clean-webpack-plugn插件:

  1. 运行npm install clean-webpack-plugin@3.0.0 -D命令
  2. 按需导入插件、得到插件的构造函数之后,创建插件的实例对象
// 按需导入,得到插件的构造函数之后,创建插件的实例对象
// 这种导入方式是结构赋值,得到的结果相当于解析了一层
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// 创建
const cleanPugin = new CleanWebpackPlugin()

module.exports = {
    // 把创建的cleanPugin 插件实例对象, 挂载plugin结点中
    plugins: [cleanPugin],
    }

1.6 Source Map

什么是Source Map?

Source Map就是一个信息文件, 里面存储着位置的信息。也就是说, Source Map文件中存储着压缩混淆后的代码,所对应的转换前的位置
有了它,出错的时候,除错工具将直接显示原始代码, 而不是转换后的代码,能够极大的方便后期的调试。

默认Source Map的问题: 开发环境下默认生成的Source Map, 记录的是生成后的代码的位置。会导致运行时报错的行数源代码的行数不一致的问题。示意图如下:
在这里插入图片描述

开发环境下,推荐在webpack.config.js中添加如下配置,即可保证运行时报错行数源代码的行数保持一致:

module.exports = {
    // eval-source-map 仅限在“开发模式”下使用,不建议在”生产模式“下使用
    devtool:'eval-source-map',
    }

webpack生产环境下的Source Map: 在生产环境下,如果省略了devtool选项,则最终生成的文件中不包含Source Map。这能欧防止原始代码通过Source Map的形式暴露给别有所图之人:

在这里插入图片描述

注意: 在实际发布的时候,建议大家把devtool的值设置为nosources-source-map或直接关闭Source Map

在生产环境下,,如果想在定位报错行数的同时,展示具体报错的源码。此时可以将devtool的值设置为source-map。实际效果如图所示:
在这里插入图片描述

  • Source Map的最佳实践
    • 开发环境: 建议把devtool的值设置为eval-source-map,好处:可以精准定位到具体的错误行
    • 生产环境下:建议关闭Source Map或将devtool的值设置为nosources-source-map , 好处:防止源码泄漏,提高网站的安全性

在实际开发中需要自己配置webpack吗?
不需要
实际开发中会使用命令行工具(俗称CLI)一键生成带有webpack的项目,所有的webpack配置项都是现成的,我们只需要知道哦啊webpack中的基本概念即可

最后我们在代码中可以指定@符号表示src这一层目录, 这样我们在导入文件的时候就不用使用../../等这样的符号, 直接从src这一层目录往下找文件, 不是从里往外找:


module.exports = 
    resolve: {
        alias: {
            // 告诉webpakck, 程序员写的代码中, @符号表示src这一层目录
            '@':path.join(__dirname, './src/')
        }
    }
}

2. Vue的基础入门

2.1 vue简介

vue是一套用于构建用户界面的前端框架。vue框架的特性,主要体现在如下两个方面:

  1. 数据驱动视图
  2. 双向数据绑定

数据驱动视图:

在使用vue的页面中,vue会监听数据的变化,从而自动重新渲染页面的结构。示意图如下:

在这里插入图片描述
好处: 当页面数据发生变化时,页面会自动重新渲染
注意: 数据驱动视图是单向的数据绑定

双向数据绑定: 在填写表单时,双向数据绑定可以辅助开发者不操作DOM的前提下自动把用户填写的内容同步到数据源中

在这里插入图片描述

好处: 开发者不需要手动操作DOM元素,来获取表单元素最新的值

MVVM 是vue实现数据驱动视图双向数据绑定的核心原理。MVVM指的是Model、View和ViewModel,它把每个HTML页面都拆分成这三个部分。

在MVVM的概念中:

  • Model表示当前页面渲染时所依赖的数据源
  • View 表示当前页面所渲染的DOM结构
  • ViewModel表示vue的实例,它是MVVM的核心

在这里插入图片描述

MVVM的工作原理: ViewModel作为MVVM的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在一起。

在这里插入图片描述

数据源发生变化时,会被ViewModel监听到,VM会根据最新的数据源自动更新页面的结构
表单元素的值发生变化时,也会被VM监听到,VM会把变化过后最新的值自动同步到Model数据源中

2.2 vue的基本使用

  • Vue的基本使用步骤:
    • 导入vue.js的script文件
    • 在页面中声明一个将要被vue所控制的DOM区域
    • 创建vm实例对象(vue的实例对象)

在这里插入图片描述

2.3 vue的调试工具

安装vue-devtoools的调试工具:vue官方提供的vue-devtools调试工具,能够方便开始者对vue项目进行调试与开发。

关于vue-devtools的安装过程这里不过多描述

配置Chrome浏览器中的vue-devtools:

点击Chrome浏览器上角的...按钮,选择更多工具 -> 扩展程序 -> Vue.js devtools详细信息,并勾选如下两个选项:

在这里插入图片描述

2.4 vue的指令

指令(Directives): 是vue为开发者提供的模版语法,用于辅助开发者渲染页面的基本结构
vue中的指令按照不同的用途可以分为如下六大类:

  1. 内容渲染指令
  2. 属性绑定指令
  3. 事件绑定指令
  4. 双向绑定指令
  5. 条件渲染指令
  6. 列表渲染指令

2.4.1 内容渲染指令

内容渲染指令用来辅助开发者渲染DOM元素的文本内容。常用的内容渲染指令有如下3个:

  • v-text :把对应数据中的值渲染到标签中。注意:渲染值会覆盖标签中的默认值
  • {{}} :只是内容的占位符,专门用来解决v-text会覆盖默认文本内容的问题,这种{{}}语法的专业名称是插值表达式(Mustache)
  • v-html : v-text插值表达式只能渲染纯文本内容。如果要把包含HTML标签字符串渲染为页面的HTML元素,则需要用到v-html这个指令

在这里插入图片描述

2.4.2 属性绑定指令

属性绑定指令:如果需要元素的属性动态绑定属性值,则需要用到v-bind属性绑定指令。示例代码如下:

在这里插入图片描述

注意: 插值表达式只能在元素中的内容节点中,不能用在元素的属性节点中

  • 在Vue中,可以使用v:bind:指令,为元素的属性动态绑定值,也可以简写为英文的:
  • 在使用v-bind:属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包括单引号,例如:<div :title=" 'box' + index>这是一个div</div>

在vue提供的模版渲染语法中,除了支持绑定简单的数据之外,还支持Javascript表达式的运算,例如:

在这里插入图片描述

2.4.3 事件绑定

vue提供了v-on事件绑定指令,用来辅助程序员为DOM元素绑定事件监听。

在这里插入图片描述
注意: v-on:click 可以简写为 @click(推荐使用)

方法传参:绑定事件的同时可以在()内传参

  • 如果没有传递参数, 在绑定事件方法,有默认的事件对象event作为参数
  • 如果传递了参数, 传递的参数会覆盖默认的事件对象event,如果需要使用默认事件对象event,那需要在多传递一个参数,使用$event固定写法表示事件对象

在这里插入图片描述

注意: 原生DOM对象有onClick、oninput、onkeyup等原生事件,替换为vue的事件绑定形式后,分别为v-on:click、v-on:input、v-on:keyup

2.4.4 事件/按键 修饰符

事件修饰符:在事件处理函数中调用event.preventDefault() (组织默认点击跳转行为)event.stopPropagation() (阻止冒泡)是非常常见的需求。因此vue提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发行为进行控制。常用的5个修饰符如下:
在这里插入图片描述
在这里插入图片描述

注意:@click.prevent;既为a标签绑定了click事件,同时取消了a标签的默认跳转行为

按键修饰符: 在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符

在这里插入图片描述

2.4.5 双向绑定

vue提供了v-model双向数据绑定指令,用来辅助开发者不操作DOM的前提下,快去获取表单的数据

在这里插入图片描述

  • v-model: 双向绑定,能和表单元素、下拉菜单元素组合使用, 但是和只展示的标签组合是没有意义的
  • v-bind:单项绑定,当数据发生变化时,会通知页面;但是在页面修改数据,是不会同步修改数据源的

为了方便对用户输入的内容进行处理,vue位v-model指令提供了3个修饰符,分别是:

在这里插入图片描述

用法如下:
在这里插入图片描述

2.4.6 条件渲染指令

条件渲染指令用来辅助开发者按需控制DOM的显示和隐藏。条件渲染指令有如下两个分别是:

  • v-if
  • v-show

在这里插入图片描述

  • v-show的原理是:动态为元素添加或移除display:none样式,来实现元素的显示和隐藏,如果要频繁的切换元素的显示状态,用v-show性能会更好
  • v-if的原理是:每次动态创建或移除元素,实现元素的显示和隐藏,如果刚进入页面的时候,某些元素默认不需要被展示,而后期这个元素很可能也不需要被展示出来,此时v-if性能更好

v-if指令还可以与v-else-ifv-else指令使用,相当于if {} else if{} esle {}, v-else、v-else-if必须与v-if组合一起使用,不能单独使用,单独使用时不被识别

在这里插入图片描述

2.4.7 列表渲染指令

vue提供了v-for列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for指令需要使用item in items形式的特殊语法,其中:

  • items 是待循环的数组
  • item 是被循环的每一项

在这里插入图片描述

v-for指令还支持一个可选的第二个参数,即当前项的索引,语法格式:(item, index)in list:
在这里插入图片描述

注意: v-for指令中的item项和index索引都是形参,可以更具需要进行重命名。 例如(user, i)in list

官方建议:只要使用到了v-for指令,那么一定要绑定一个:key属性, 而且这里建议尽量把id作为key的值,并且官方对key的值是由要求的:字符串或数字类型。 这里需要注意的是key的值是千万不能重复的,否则会终端报错 Dulicate keys detected

  • key的注意事项:
    • key的值只能是字符串数字类型
    • key的值必须具备唯一性(即:key的值不能重复,唯一性指的是key和数据具有唯一绑定性)
    • 建议把数据项id属性的值作为key的值(因为id属性的值具有唯一性)
    • 使用index的值当做key的值没有任何意义(因为index的值不具有唯一性)
    • 建议使用v-for指令时一定要指定key的值(既能提升性能、又防止列表状态紊乱)

2.5 品牌列表案例

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>品牌列表案例</title>
  <link rel="stylesheet" href="../../lib/bootstrap.css">
  <link rel="stylesheet" href="./css/brandlist.css">
  <script src="../../lib/vue-2.6.12.js"></script>
</head>

<body>

  <div id="app">
    <!-- 卡片区域 -->
    <div class="card">
      <div class="card-header">
        添加品牌
      </div>
      <div class="card-body">
        <!-- 添加品牌的表单区域 -->
        <form @submit.prevent="add">
          <div class="form-row align-items-center">
            <div class="col-auto">
              <div class="input-group mb-2">
                <div class="input-group-prepend">
                  <div class="input-group-text">品牌名称</div>
                </div>
                <input type="text" class="form-control" placeholder="请输入品牌名称" v-model.trim="name">
              </div>
            </div>
            <div class="col-auto">
              <button type="submit" class="btn btn-primary mb-2">添加</button>
            </div>
          </div>
        </form>
      </div>
    </div>

    <!-- 表格区域 -->
    <table class="table table-bordered table-hover table-striped">
      <thead>
        <tr>
          <th scope="col">#</th>
          <th scope="col">品牌名称</th>
          <th scope="col">状态</th>
          <th scope="col">创建时间</th>
          <th scope="col">操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in list" :key="item.id">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>
            <div class="custom-control custom-switch">
              <input type="checkbox" class="custom-control-input" :id="'customSwitch' + item.id" v-model="item.status">
              <label class="custom-control-label" :for="'customSwitch' + item.id">{{ item.status ? '已启用' : '已禁用' }}</label>
            </div>
          </td>
          <td>{{ item.time }}</td>
          <td>
            <a href="javascript:;" @click="remove(item.id)">删除</a>
          </td>
        </tr>
      </tbody>
    </table>
  </div>

  <script>
    const vm = new Vue({
      el:'#app',
      data: {
        name:'',
        list:[
          {id: 1, name: '宝马', status: false, time: new Date()},
          {id: 2, name: '奔驰', status: true, time: new Date()},
          {id: 3, name: '奥迪', status: false, time: new Date()}
        ]
      },
      methods: {
        remove(id) {
          // 根据id来删除数据
          // filter :  把不符合条件的元素过滤掉
          this.list = this.list.filter( item => item.id != id)
        },
        add() {
          if (this.name === '') return alert('请输入品牌名称')

          // 如果不为空则 执行添加逻辑
          const obj = {
            id: this.list.length + 1,
            name: this.name,
            status: true,
            time: new Date()
          }

          this.list.push(obj)

          this.name = ''


        }
      }
    })
  </script>
</body>

</html>

在这里插入图片描述

2.6 过滤器

过滤器(Filters)是vue为开发者提供的功能,常用与文本的格式化。过滤器可以用在两个地方:插值表达式、v-bind属性绑定。过滤器应该被提那家在JavaScript表达式的尾部,由管道符进行调用.但是在Vue3.0中已经不支持过滤器了, 官方建议使用计算属性和方法来代替

在这里插入图片描述

  • 过滤器的注意点:
    • 要定义在filters节点下,本质上是一个函数
    • 在过滤器函数中,一定要有return值
    • 在过滤器的形参中,就可以获取到“管道符”前面待处理的那个值

私有过滤器和全局过滤器: 在filters节点下定义的过滤器,成为私有过滤器,因为它只能在vm实例所控制的el区域内使用。如果希望在多个vue实力之间共享过滤器,则可以按照如下的格式定义全局过滤器:

 // 全局过滤器, 独立于每个vm实例之外
        // Vue.filter()方法接受两个参数: 第一个参数: 全局过滤器的名称  第二个参数:全局过滤器的处理函数
        Vue.filter('capitalize', (str) => {
            return str.charAt(0).toUpperCase() + str.slice(1) + '~~~'
        })

注意:如果全局过滤器函数和私有过滤器名字一致,此时按照就近原则,调用的是私有过滤器

我们也可以连续调用过个过滤器:
在这里插入图片描述

过滤器的本质JavaScript函数,因此可以接受参数,格式如下:

在这里插入图片描述

2.7 侦听器

watch侦听器允许开发者见识数据的变化,从而针对数据的变化做特定的操作
在这里插入图片描述

immediate: 默认值false,其作用是控制侦听器是否自动触发一次
有时候我们会有需求,在界面初始化时,就自动触发触发一次监听器,监听属性的变化, 这时候我们可以做如下实现:

在这里插入图片描述

deep: 开启深度监听,只要对象中任何一个属性变化,都会触发“对象的监听器”, 有时候我们监听的是一个对象, 如果想要对象中的每个属性的变化都会引起对象的变化,那么使用deep关键字。但是只是想要监听对象中某一个属性的变化, 可以之间监听子属性

 const vm = new Vue({
            el: '#app',
            data: {
                info:{
                    username: 'zs',
                    age: 20
                }
            },
            
            watch: {
                // 定义对象格式的侦听器
                info: {
                    handler(newVal) {
                        console.log('触发侦听器-------',newVal);
                    },
                    // 开启深度监听,只要对象中的任何一个属性变化了,都会触发 对象的侦听器
                    deep: true
                },

                // 上述监听,是只要对象中的属性发生变化,都会触发监听器, 
                // 但是有时候我们只需要监听某个属性的变化,所以我们可以监听对象单个舒心改变
                // 如果要侦听的是对象的子属性的变化,则必须包裹一层单引号
                'info.username'(newVal) {
                    console.log(newVal);
                }
            }
        })

侦听器的格式:

  • 方法格式的侦听器:
    • 缺点1: 无法在刚进入页面的时候,自动触发
    • 缺点2: 如果侦听的是一个对象,如果对象中的属性发生了变化, 不会触发侦听器!!!
  • 对象格式的侦听器:
    • 好处1:可以通过immediate选项,让侦听器自动触发!!!
    • 好处2: 可以通过deep选项,让侦听器深度监听对象中的每个属性变化!!!

2.8 计算属性

计算属性指的是通过一系列运算之后,最终得到的一个值。这个动态计算出来的属性值可以被模版结构或methods方法使用。

在这里插入图片描述

  • 计算属性:
    • 特点: 定义的时候,要被定义成方法;在使用计算属性的时候,当普通的属性使用即可
    • 好处: 实现了代码的复用;只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值

2.9 axios

axios:是前端最火的、专注于数据请求的库。

相关文当网站:http://www.axios-js.com/zh-cn/docs/https://www.axios-http.cn

axios的基础语法:
在这里插入图片描述
返回的数据:
在这里插入图片描述

发起 GET 请求:

axios({
  // 请求方式
  method: 'GET',
  // 请求的地址
  url: 'http://www.liulongbin.top:3006/api/getbooks',
  // URL 中的查询参数
  params: {
    id: 1
  }
}).then(function (result) {
  console.log(result)
})

发起 POST 请求:

document.querySelector('#btnPost').addEventListener('click', async function () {
  // 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!
  // await 只能用在被 async “修饰”的方法中
  const { data: res } = await axios({
    method: 'POST', 
    url: 'http://www.liulongbin.top:3006/api/post',
    data: {
      name: 'zs',
      age: 20
    }
  })

  console.log(res)
})

注意:关于axios这里不做过多介绍, 更多用法请参考官方文档

每次使用axios时,在临时导入, 这样如果多个地方使用,那每个地方都使用,非常麻烦, 我们可以把axios挂在到Vue上。我们知道每一个组件都是一个Vue的实例

在这里插入图片描述

在这里插入图片描述
那今后要在那个组件调用axios发起请求, 直接使用this.$http.xxx发起请求,但是这样做不利于API接口的复用。

2.10 vue-cli

什么是vue-cli?

vue-cli是Vue.js开发的标准工具。它简化了程序员基于webpack创建工程化的Vue项目的过程。中文官方地址:https://cli.vuejs.org/zh/

Vue-cli的安装和使用

vue-cli是npm上的一个全局包使用npm install命令,即可方便的把它安装到自己的电脑上:npm install -g @vue/cli ,基于vue-cli快速生成工程化的Vue项目:vue create 项目的名称

执行vue create xxx 的项目创建过程

  1. 选择配置: 这里我们选择手动选择配置
    在这里插入图片描述

  2. 看自己项目的需求,选择相应的配置:
    在这里插入图片描述

  3. 选择Vue的版本: 这里选择的是Vue2.0
    在这里插入图片描述

  4. 选择CSS的编写方式:这里选择less方式:
    在这里插入图片描述

  5. 选择把babel、eslint等插件的配置项,放到独立的配置文件中还是放到package.json配置文件中
    在这里插入图片描述

  6. 是否把当前选择的配置保存起来, 方便下次创建新的项目时直接使用: 这里选择 保存
    在这里插入图片描述

创建完之后,项目的结构目录如下:

在这里插入图片描述

  • vue中src目录的构成:

    • assets文件件: 存放项目中用到的静态资源,例如:css样式表、图片资源
    • components文件夹:程序员封装的、可复用性的组件,都要放到components目录下
    • main.js是项目的入口文件。整个项目的运行,要先执行main.js
    • App.vue是项目的根组件
  • 在工程化的项目中,vue要做的事情很单纯: 通过main.jsApp.vue渲染到index.html的指定区域中。

    • App.vue 用来编写待渲染的模版结构
    • index.html中需要预留一个el区域
    • main.js 把App.vue渲染到了index.html所预留的区域中
// 创建vue的实例对象
new Vue({
  // 把render 函数指定的组件,渲染到HTML页面中 (直接渲染到#app区域,直接替换#app区域)
  render: h => h(App),
}).$mount('#app')
// vue 中$mount()方法,作用和 el 属性完全一样

2.11 vue组件

什么是组件化开发?

组件化开发指的是:根据封装的思想,把页面上可重用的UI结构封装为组件,从而方便项目的开发和维护。

vue是一个支持组件化开发的前端框架。vue中规定:组件的后缀名.vue。之前接触到的App.vue文件本质上就是一个vue组件。

每个.vue组件都由三部分构成,分别是:

  1. template : 组件的模版结构
  2. script:组件的JavaScript行为
  3. style:组件的样式

其中每个组件中必须包含template模版结构,而script行为style样式可选的组成部分

2.11.1组件的基本使用

vue规定:每个组件对应的模版结构,需要定义到<template>结点中

<template>
    <!-- 当前组件的 DOM 结构, 需要定制到template标签的内部 -->
</template>
  • 注意:
    • template是vue提供的容器标签,只起到包裹性质的作用,它不会被渲染为真正的DOM元素
    • template中只能包含唯一的根节点
<template>
    <!-- 当前组件的 DOM 结构, 需要定制到template标签的内部 -->
    <div class="test-box">
        <h3>这是用户自定义的 Test.vue -----{{ username }}</h3>
        <button @click="changeName">按钮事件</button>
    </div>
</template>

<script>

// 默认导出,固定写法
export default {
    // data数据源
    // 注意: .vue组价中的data不能和之前一样, 不能指向对象,.vue中的data必须是一个函数
    
    // 错误写法 :data: {username: 'zs' }
    //正确写法:
    data() {
        return {
            username: 'zs'
        }
    },
    methods: {
        // 在组件中, this就表示当前组件的实例对象
        changeName() {
            console.log(this);
            this.username = '玩哈哈'
        }
    }
}

</script>

<!--  如果css需要使用less语言来写, 需要指定属性 lang="less"  该属性默认值css-->
<style lang="less">
.test-box {
    background-color: red;

    h3 {
        color: white;
    }
}
</style>

在这里插入图片描述

2.11.2 组件之间的父子关系

在这里插入图片描述

使用组件的三个步骤:

  1. 使用import语法导入需要的组件 import Left from '@/components/Left.vue'
  2. 使用components节点注册组件 export default { name: 'App', components: { Left } }
  3. 以标签的形式使用刚才注册的组件 <Left></Left>

2.11.3 私有组件和全局组件

通过coponents注册的是私有组件,例如在组件A的conponents节点下,注册了组件F。则组件F只能在组件A中使用,不能被用在组件C

这时候我们可以采用注册全局组件, 在vue项目的main.js入口文件中通过Vue.component()方法,可以注册全局组件。

// 导入需要全局注册的组件
import Test from '@/components/test.vue'

// 参数一: 字符串格式表示组件的注册名称  参数二: 需要被全局注册的那个组件
Vue.component('Test',Test)

注意: 在组件的内部不能使用自己, 会造成循环使用, 终端会报错

2.11.4 组件的props

props是组件的自定义属性,在封装通用组件的时候, 合理的使用props可以极大的提高组件的复用性。语法格式如下:
在这里插入图片描述

在这里插入图片描述

上述方式可以在组件初始化的时候,给定一个初始值, 但是我们发现这里传递的只能是字符串。 那么我们如果想要传递数字,如何传递了?

解决方案: 我们可以通过v-bind属性绑定传值, 因为通过v-bind绑定之后, 等候后面的语句会当成js语句执行。

没有使用v-bind属性绑定之前
在这里插入图片描述

使用v-bind属性绑定之后
在这里插入图片描述

注意: props是只读的,vue规定,组件封装中的自定义属性是只读的,程序员不能直接修改props的值。否则会直接报错
在这里插入图片描述

如果想要修改props的值, 可以把props的值转存到data中,因为data中的数据都是可读可写的!
在这里插入图片描述

如果我们不想再创建组件时传递一个初始值<MyCount :initCount="10"></MyCount>, 但是我们又希望自定义属性有一个默认值。那我们可以在声明自定义属性的时候,可以通过default定义属性的默认值

在这里插入图片描述

上述定义的自定属性,我们可以传可以不传。但是如果我们需要使用者一定要传的话,我们可以通过require属性来指定,使用组件时必须要传递该属性的初始值。注意: required属性和default默认值 没有任何关系

如果使用required属性修饰,使用组件时没有传递初始值,则终端会报如下错误:
在这里插入图片描述

组件之间的冲突问题: 默认情况下,写在.vue组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突关系
导致组件样式冲突根本原因:

  1. 单页面应用程序中,所有的组件的DOM结构,都是基于唯一的index.html页面进行呈现的
  2. 每个组件中的样式, 都会影响整个index.html页面中的DOM元素

在这里插入图片描述

我在Left组件中设置了<h1></h1>标签的颜色, 并没有在app.vue和Right.vue中设置标签的颜色,但是云信结果发现,页面中所有的<h1></h1>的字体颜色都变成绿色了。 这就是组件之间的样式冲突问题

解决方案: 每个组件中的标签都添加一个自定义属性,然后通过属性选择器来设置CSS,就可以达到单独设置某个组件内的样式,达到解决不同组件的样式冲突问题。

在这里插入图片描述

上述方法是我们自己添加手动在组件中每个标签上添加自定义属性, 然后使用属性选择器来设置CSS。但是 Vue已经给我们解决了这个问题, 只需要我们在写样式时,加上scoped 属性,那么Vue会自动给组件的每个标签加上一个自定义属性。
在这里插入图片描述

当使用第三方组件库的时候,如果有修改第三方组件默认样式的需求,需要使用到/deep/ 属性:
在这里插入图片描述

2.12 生命周期

生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁整个阶段,强调的是一个时间段

生命周期函数:是有vue框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行

注意: 生命周期强调的是时间段生命周期函数强调的是时间点

组件生命周期函数的分类:

在这里插入图片描述

生命周期图示: 可以参考vue官方给出的“生命周期图示”,进一步理解组件生命周期执行的过程:https://v2.cn.vuejs.org/v2/guide/instance.html

请添加图片描述

<script>
export default {
  props: ['info'],
  data() {
    return {
      message: 'hello vue.js',
      // 定义 books 数组,存储的是所有图书的列表数据。默认为空数组!
      books: []
    }
  },
  watch: {
    message(newVal) {
      console.log('监视到了 message 的变化:' + newVal)
    }
  },
  methods: {
    show() {
      console.log('调用了 Test 组件的 show 方法!')
    },
    // 使用 Ajax 请求图书列表的数据
    initBookList() {
      const xhr = new XMLHttpRequest()
      xhr.addEventListener('load', () => {
        const result = JSON.parse(xhr.responseText)
        console.log(result)
        this.books = result.data
      })
      xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
      xhr.send()
    }
  },
  // 创建阶段的第1个生命周期函数
  beforeCreate() {
    // console.log(this.info)
    // console.log(this.message)
    // this.show()
  },
  created() {
    // created 生命周期函数,非常常用。
    // 经常在它里面,调用 methods 中的方法,请求服务器的数据。
    // 并且,把请求到的数据,转存到 data 中,供 template 模板渲染的时候使用!
    this.initBookList()
  },
  beforeMount() {
    // console.log('beforeMount')
    // const dom = document.querySelector('#myh3')
    // console.log(dom)
  },
  // 如果要操作当前组件的 DOM,最早,只能在 mounted 阶段执行
  mounted() {
    // console.log(this.$el)
    // const dom = document.querySelector('#myh3')
    // console.log(dom)
  },
  beforeUpdate() {
    // console.log('beforeUpdate')
    // console.log(this.message)
    // const dom = document.querySelector('#pppp')
    // console.log(dom.innerHTML)
  },
  // 当数据变化之后,为了能够操作到最新的 DOM 结构,必须把代码写到 updated 生命周期函数中
  updated() {
    // console.log('updated')
    // console.log(this.message)
    // const dom = document.querySelector('#pppp')
    // console.log(dom.innerHTML)
  },
  beforeDestroy() {
    console.log('beforeDestroy')
    this.message = 'aaa'
    console.log(this.message)
  },
  destroyed() {
    console.log('destroyed')
    // this.message = 'aaa'
  }
}
</script>

2.13 组件之间的数据共享

在项目开发中,组件之间的最常见的关系分为如下两种: 父子关系、兄弟关系

父组件向子组件共享数据: 父组件向子组件共享数据需要使用自定义属性,示例代码如下:

在这里插入图片描述

子组件向父组件共享数据: 子组件向父组件共享数据使用自定义事件。示例代码如下:

在这里插入图片描述

兄弟组件的数据共享:在vue2.x中,兄弟组件之间数据共享的方案是EventBus

在这里插入图片描述

  • EventBus的使用步骤:
    • 创建eventBus.js模块,并向外共享一个Vue的实例对象
    • 在数据发送方,调用bus.$emit('事件名称',要发送的数据)方法触发自定义事件
    • 在数据接受放,调用bus.$on('事件名称','事件处理函数')方法注册一个自定义事件

2.14 ref

什么是ref引用?

ref是用来辅助开发者在不依赖jQuery的情况下,获取DOM元素或组件的引用。

每个vue的组件实例,都包含一个$refs对象,里面存储着对应的DOM元素或组件的引用。默认情况下,组件的$refs对象指向一个空对象

在这里插入图片描述

如果想要试用ref引用页面上的组件实例,则可以按照如下方式进行操作:

在这里插入图片描述

注意:当我们通过$refs拿到组件的实例对象,就可以调用该组件的方法和属性

有时候我们有如下需求, 当我们修改DOM元素之后, 我们希望在DOM结构更新之后,在执行接下来的动作。

这时候vue给我们提供了this.$nextTick(cb)方法, 会把cb回调推迟到下一个DOM更新周期之后执行。通俗的理解是:等组件的DOM更新完成之后,在执行cb回调函数,从而能保证cb回调函数可以操作到最新的DOM元素。

2.15 动态组件

什么是动态组件?

动态组件指的是动态切换组件的显示与隐藏

component:该标签是vue内置标签, 起作用:组件的占位符, is属性的值,表示要渲染组件的名称(名称是组件在componenes【节点下注册的名称)

在这里插入图片描述

当我们来回切换组件的时候, 我们可以发现一个问题, 当我们切换到另外一个组件时, 之前显示的那个组件已经被销毁了, 有时候根据需求,我们不希望组件被销毁。

针对这种情况, vue提供了keep-alive内置标签来,保持组件的状态, 该标签的作用:可以把内部的组件进行缓存,而不是销毁组件

在这里插入图片描述

有些时候我们需要监听组件的缓存和激活的时间点,用来做一些事件。vue也给我们提供了keep-alive对应的生命周期函数:

  • 当组件被缓存时,会自动触发组件的deactivated生命周期函数
  • 当组件被激活时,会自动触发组件的activated生命周期函数。

在这里插入图片描述

我们可以发现,activated生命周期方法,在第一次创建的时候,也会执行

有时候我们可能在keep-alive同时显示多个组件, keep-alive 给我们提供了iinclude属性,用来指定只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分割:

<keep-alive include="Left">
        <component :is="componentName"></component>
</keep-alive>

在这里插入图片描述

除了include属性之外,还有exclude属性: 指定哪些组件不需要被缓存,需要注意的是不要同时使用include和exclude这个两个属性

keep-alive在使用includeexclude属性时,会根据组件的name来筛选,所以的组件要被keep-alive条件缓存时, 就必选显示申明一个name选项。如果在声明组件的时候,没有为组件指定name名称,则组件的名称默认就是注册时候的名称。但是当我们提供了name属性之后,组件的名称,就是name属性
在这里插入图片描述

2.16 插槽

什么是插槽?

插槽(Slot)是vue为了组件的封装着提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
在这里插入图片描述

在这里插入图片描述

vue官方规定: 每一个slot插槽,都要有一个name名称, 如果省略了slot的 name属性,则有一个默认的名称叫做default

在这里插入图片描述

我们还可以定义多个插槽,然后根据插槽的名字来填充自定义的内容, 我们可以使用v-slot属性来指定内容填充到那个插槽上,v-slot:xxx还可以简写为#xxx
在这里插入图片描述

我们还可以给插槽指定默认值,如果用户没有指定内容,那么该插槽区域就会展示默认内容,如果用户指定了内容,那就展示用户的内容

在这里插入图片描述

我们在封装组件的时候,为预留<slot>提供属性对应的值,这种用法叫做作用域插槽,示例代码如下:

在这里插入图片描述

注意:默认情况下没有传值的话,接收的是一个{} 对象

2.17 自定义指令

什么是自定义指令?

vue官方提供了v-text、v-for、v-model、v-if等常用的指令。除此之外vue还允许开发者自定义指令。
vue中的自定义指令分为:私有自有自定义指令、全局自定义指令

在每个vue组件中,可以在directives节点下声明私有自定义指令。示例代码如下:
在这里插入图片描述

有时候我们希望给自定义属性传一些值:
在这里插入图片描述

bind函数只调用1次:当指令第一次绑定到元素时调用,当DOM更新时bind函数不会被处罚update函数会在每次DOM更新时被调用。

在这里插入图片描述

如果bindupdate函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式
在这里插入图片描述

全局共享的自定义指令需要通过Vue.directive()进行声明,示例代码如下:

在这里插入图片描述

2.18 eslint

ESLint:可组装的JavaScript和JSX检查工具. 代码规范工具
中文网: http://eslint.cn

使用vue create xxx 在创建项目, 在插件选择这一步,选择ESlint(默认选中)
在这里插入图片描述

选择ESlint的规范
在这里插入图片描述

在这里插入图片描述
创建完项目之后,项目的结构目录, 可以发现多了一个.eslintrc.js的目录文件:
在这里插入图片描述

根据团队的代码规则,可以在.eslintrc.js配置文件中,配置想要支持的规则。 具体的规则参考ESlint的官网。

这里有两款辅助ESlint的插件,安装方式参考:https://blog.csdn.net/yyzx_yyzx/article/details/125708717

2.19 路由

什么是路由? 路由(Router)就是对应的关系

前端路由:通俗易懂的概念Hash地址组件之间的对应关系。

  • 前端路由的工作方式:
    • 用户点击了页面上的路由连接
    • 导致了URL地址栏中Hash值发生了变化
    • 前端路由监听了到Hash地址的变化
    • 前端路由把当前Hash地址对应的组件渲染到浏览器中

在这里插入图片描述

2.19.1 实现简易的前端路由

通过<cmponent>标签, 结合conName动态渲染组件。示例代码如下:
在这里插入图片描述

2.19.2 vue-router的基础使用

什么是vue-router?
vue-router 是vue.js官方给出的路由解决方案。它只能结合vue项目进行使用,能够轻松的管理SPA项目中组件的切换。 vue-router的官方文档地址 :https://router.vuejs.org/zh/

  • vue-router安装和配置的步骤:
    • 安装vue-route包 npm install vue-router@3.5.2 -S
    • 创建路由模块
    • 导入并挂载路由模块
    • 声明路由连接占位符

创建路由模块:在src原代码目录下,新建router/index.js路由模块,并初始化如下代码:

在这里插入图片描述

在这里插入图片描述

其实当我们安装和配置了vue-router后,就可以使用router-link 来替代普通的 a 连接:
在这里插入图片描述

在这里插入图片描述

2.19.3 嵌套路由

嵌套路由: 通过路由实现组件的嵌套展示,叫做嵌套路由。

在这里插入图片描述

在这里插入图片描述

除了重定向路由实现第一次进页面显示默认页面,默认子路由也可以实现

在这里插入图片描述

2.19.4 动态路由

动态路由:把Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性。在vue-route中使用英文的冒号(:)来定义路由的参数项。示例代码如下:

在这里插入图片描述

例如我们有如下需求: 我么希望根据电影的id值,展示对应电影的详情信息。

这时候我们可以为路由规则开启props传参,从而方便的拿到动态参。
在这里插入图片描述

我们还可以再路由连接增加查询参数:
在这里插入图片描述

  • 注意:
    • 在hash地址中, / 后面的参数项, 叫做路径参数。 在路由参数对象中 ,需要使用this.$route.params来访问路径参数
    • 在hash地址中, ?后面的参数项,叫做查询参数。在路由参数列表中,需要使用this.$route.query来访问查询参数
    • this.route中, path 只是路径的一部分; fullpath 是完整的地址
      • 例如: /movie/2?name=zs&age=20 是fullpath的值; /movie/2是path的值

2.19.5 声明式导航 & 编程时导航

在浏览器中,点击链接实现导航的方式, 叫做声明式导航。 例如:

在普通网页中点击<a> 链接、vue项目中点击<route-link>都属于声明式导航
在浏览器中,调用API实现导航的方式,叫做编程式导航。例如普通网页中调用locatio.href跳转到新的页面的方式,属于编程式导航

  • vue-router 中提供了许多的编程式导航API,其中最常见的导航API分别是:

    • this.$router.push(''hash 地址): 跳转大指定的hash地址, 并增加一条历史记录。
    • this.$router.replace(‘hash 地址’): 跳转到指定的hash地址,并替换掉当前的历史记录
    • this.$router.go(数值n) : 可以在浏览历史中前进和后退

    在这里插入图片描述
    在这里插入图片描述

在实际开发中,一般只会前进和后退一层页面。 因此vue-router提供了如下两个便捷防范:

  • $ router.back()
  • $router.forward()
    在这里插入图片描述

2.19.6 导航守卫

在这里插入图片描述

每次发生路由的导航跳转时, 都会触发全局前置守卫。因此,在全局前置守卫中 程序员可以对每个路由进行访问权限的控制:

在这里插入图片描述

next函数的3种调用方式:
在这里插入图片描述

当前用户拥有后台主页的访问权限,直接放行:next()
当前用户没有后台主页的访问权限, 强制其跳转到登录页面:next(‘/login’)
当前用户没有后台主页的访问权限,不允许跳转到后台主页: next(false)

控制后台访问权限:
在这里插入图片描述

本文学习过程中的示例代码:https://gitee.com/guoweiyong/web_vue_study

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。