Web前端-Vue2.0框架学习

Web前端-Vue框架学习

  • 1. 前端工程化与Webpack
    • 1.1 隔行变色的demo实现
    • 1.2 webpack的基本使用
    • 1.3 webpac插件
      • 1.3.1 webpack-dev-server插件
      • 1.3.2 html-webpack-plugin
    • 1.4 webpack中的loader(加载器)
      • 1.4.1 css-loader
      • 1.4.2 less-loader
      • 1.4.3 url-loader & file-loader (处理url路径相关的文件)
      • 1.4.4 打包处理js文件中的高级语法
    • 1.5 打包发布
    • 1.6 Source Map
  • 2. Vue的基础入门
    • 2.1 vue简介
    • 2.2 vue的基本使用
    • 2.3 vue的调试工具
    • 2.4 vue的指令
      • 2.4.1 内容渲染指令
      • 2.4.2 属性绑定指令
      • 2.4.3 事件绑定
      • 2.4.4 事件/按键 修饰符
      • 2.4.5 双向绑定
      • 2.4.6 条件渲染指令
      • 2.4.7 列表渲染指令
    • 2.5 品牌列表案例
    • 2.6 过滤器
    • 2.7 侦听器
    • 2.8 计算属性
    • 2.9 axios
    • 2.10 vue-cli
    • 2.11 vue组件
      • 2.11.1组件的基本使用
      • 2.11.2 组件之间的父子关系
      • 2.11.3 私有组件和全局组件
      • 2.11.4 组件的props
    • 2.12 生命周期
    • 2.13 组件之间的数据共享
    • 2.14 ref
    • 2.15 动态组件
    • 2.16 插槽
    • 2.17 自定义指令
    • 2.18 eslint
    • 2.19 路由
      • 2.19.1 实现简易的前端路由
      • 2.19.2 vue-router的基础使用
      • 2.19.3 嵌套路由
      • 2.19.4 动态路由
      • 2.19.5 声明式导航 & 编程时导航
      • 2.19.6 导航守卫

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/13088.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Node【Global全局对象】之【URL】

文章目录 &#x1f31f;前言&#x1f31f;URL&#x1f31f;URL组成部分&#x1f31f;URL 类&#x1f31f;url.href&#x1f31f;url.pathname&#x1f31f;url.port&#x1f31f;url.protocol&#x1f31f;url.search&#x1f31f;url.searchParams&#x1f31f;url.hash&#…

C语言模拟银行排队叫号(链队)

一.队列 队列是一种具有先进先出&#xff08;FIFO&#xff09;特性的线性数据结构&#xff0c;它只允许在队列的两端进行插入和删除操作。队列的一端称为队尾&#xff08;rear&#xff09;&#xff0c;另一端称为队头&#xff08;front&#xff09;。新元素总是插入在队列的队…

C++进阶——二叉搜索树BST

C进阶——二叉搜索树BST 其实应该是二叉树内容的进阶版本&#xff1a; 二叉树在前面C数据结构阶段已经讲过&#xff0c;本节取名二叉树进阶是因为&#xff1a; map和set特性需要先铺垫二叉搜索树&#xff0c;而二叉搜索树也是一种树形结构二叉搜索树的特性了解&#xff0c;有…

【路径规划】基于前向动态规划算法在地形上找到最佳路径(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

自然语言处理:词嵌入简介

动动发财的小手&#xff0c;点个赞吧&#xff01; Word Embeddings 机器学习模型“查看”数据的方式与我们&#xff08;人类&#xff09;的方式不同。例如&#xff0c;我们可以轻松理解“我看到一只猫”这一文本&#xff0c;但我们的模型却不能——它们需要特征向量。此类向量或…

C/C++每日一练(20230417)

目录 1. 字母异位词分组 &#x1f31f;&#x1f31f; 2. 计算右侧小于当前元素的个数 &#x1f31f;&#x1f31f;&#x1f31f; 3. 加一 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 J…

通过简单demo让你秒懂Python的编译和执行全过程

基本说明 python 是一种解释型的编程语言&#xff0c;所以不像编译型语言那样需要显式的编译过程。然而&#xff0c;在 Python 代码执行之前&#xff0c;它需要被解释器转换成字节码&#xff0c;这个过程就是 Python 的编译过程。 DEMO演示讲解 假设我们有以下 Python 代码&…

Session使用和原理分析图与实现原理-- 代码演示说明 Session 的生命周期和读取的机制代码分析

目录 Web 开发会话技术 -Session —session 技术 session 基本原理 Session 可以做什么 如何理解 Session Session 的基本使用 session 底层实现机制 原理分析图 代码演示 CreateSession.java 测试 Session 创的机制&#xff0c; 注意抓包分析​编辑 ReadSession.j…

python+vue 基于推荐算法的在线电影视播放网站

以广大影视剧迷们为研究对象&#xff0c;深入了解影视剧迷对在线视频观看视频的需求进行分析&#xff0c;形成系统需求分析设计一个符合影视剧迷们需求的在线视频网站。设计网站的前期工作包括对系统的各个功能进行详细分析&#xff0c;对数据库设计进行详细的描述&#xff0c;…

【C++】STL理解【容器】

【C】STL理解【容器】 1. STL概念引入 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西&#xff0c;以及一种得以制造出”可重复运用的东西”的方法&#xff0c;从函数(functions)&#xff0c;类别(classes),函数库(function libraries),类别库(class libraries…

nssctf web 入门(6)

这里通过nssctf的题单web安全入门来写&#xff0c;会按照题单详细解释每题。题单在NSSCTF中。 想入门ctfweb的可以看这个系列&#xff0c;之后会一直出这个题单的解析&#xff0c;题目一共有28题&#xff0c;打算写10篇。 目录 [SWPUCTF 2021 新生赛]caidao [SWPUCTF 2021 新…

GitLab与jekins结合构建持续集成(cl)环境(2)

目录 GItlab配置邮箱 绑定邮箱 创建群组 添加人员 创建一个项目 添加文件 新建分支 如何拉取代码 Git bash 演示 Git GUI演示 安装jenkins 更改插件镜像源 配置jenkins使用gitlab更新代码 安装jekins插件 配置jenkins免密拉取gatlab代码 jenkins创建项目 将代码…

VUE基本使用详解

目录 一、VUE框架原理 1. 了解VUE框架 2. VUE框架原理 3. MVC设计模式 4. MVVM设计模式 二、引入VUE框架 1. 本地引入 2. 网络引入 三、安装Vue插件 一、VUE框架原理 1. 了解VUE框架 vue 框架 是基于MVVM设计模式的前端框架&#xff0c;其中的Vue对象是MVVM设计模式中的VM视图…

Zebec Protocol 出席香港 Web3 峰会,带来了哪些信息?

梳理香港加密新政的细节&#xff0c;一个明确的脉络是&#xff0c;香港加密新政的整体目的是令虚拟资产交易明确化和合法化&#xff0c;通过不断完善的监管框架&#xff0c;促进香港虚拟资产行业的可持续和负责任地发展。 在加强合规和持牌经营的监管思路下&#xff0c;长期审慎…

TensorFlow 和 Keras 应用开发入门:1~4 全

原文&#xff1a;Beginning Application Development with TensorFlow and Keras 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形…

《简化iOS APP上架流程,App Uploader助你搞定!》

转载&#xff1a;Appuploader常见问题 Appuploader 常见错误及解决方法 问题解决秘籍 遇到问题&#xff0c;第一个请登录苹果开发者官网 检查一遍账号是否有权限&#xff0c;是否被停用&#xff0c;是否过期&#xff0c;是否有协议需要同意&#xff0c;并且在右上角切换账号后…

页表结构详细说明

一、页表 1. 内存地址的分解 我们知道linux采用了分页机制&#xff0c;通常采用四级页表&#xff0c;页全局目录(PGD)&#xff0c;页上级目录(PUD)&#xff0c;页中间目录(PMD)&#xff0c;页表(PTE)。如下&#xff1a; 其含义定义在arch/arm64/include/asm/pgtable-hwdef.…

HCIP-6.9BGP路由反射器原理与配置

路由反射器原理与配置 1、路由反射器概念1.1、路由反射器原理&#xff1a;1.2、多集群路由反射器1.3、备份路由反射器2、路由反射器配置3、路由反射器防环机制 1、路由反射器概念 IBGP的水平分割&#xff0c;IBGP 1只能update一跳&#xff0c;就是说在IBGP 2 设备收到IBGP 1设…

密码学|DES加密算法|学习记录

DES简介 DES属于对称密码算法中的分组加密算法 密钥一共64bit&#xff0c;其中56位参与运算&#xff0c;其余8bit为校验位&#xff08;8 16 24 32 40 48 56 64&#xff09; n个64位明块经过加密后得到的n个64位密文块加在一起就是密文 DES一般步骤 IP置换 &#xff1a; IP置…

Python中的异常——概述和基本语法

Python中的异常——概述和基本语法 摘要&#xff1a;Python中的异常是指在程序运行时发生的错误情况&#xff0c;包括但不限于除数为0、访问未定义变量、数据类型错误等。异常处理机制是Python提供的一种解决这些错误的方法&#xff0c;我们可以使用try/except语句来捕获异常并…
最新文章