【全干工程师必学】一文搞懂Vue2.0

news2024/9/20 5:49:48

一文搞懂Vue2.0

  • 一、前端工程化
  • 二、WebPack
    • 是什么
    • 基本使用
      • 实现奇偶行变色
        • 1.初始化包管理工具
        • 2.安装jquery
        • 3.在项目中安装webpack
        • 4.在项目中配置webpack
        • 5.运行代码
      • mode 的可选值
        • development
        • production
      • webpack.config.js 文件的作用
        • webpack 中的默认约定
        • 自定义打包的入口与出口
    • webpack中的插件
      • webpack 插件的作用
      • 生成到内存中的文件该如何访问?
      • html-webpack-plugin
      • devServer 节点
    • webpack 中的 loader
      • loader 概述
      • loader 的调用过程
      • 打包处理 css 文件
      • 打包处理 less 文件
    • 打包发布
    • 总结
  • 三、Vue基础入门
    • Vue简介
      • 什么是Vue
      • Vue 的两个特性
        • MVVM的原理
        • 总结
    • Vue的基本使用
      • Vue的基本使用步骤
      • 基本代码与 MVVM 的对应关系
    • Vue指令
      • 内容渲染指令
      • 属性绑定指令
      • 事件绑定
      • v-model 指令
      • 条件渲染指令
    • 过滤器
      • 全局过滤器
      • 连续调用多个过滤器
      • 过滤器传参
    • 入门实例
      • 实现增删查功能
  • 四、Vue基础进阶
    • watch 侦听器
      • 什么是侦听器
      • 侦听器的格式
      • 侦听器测试
    • 计算属性
      • 是什么?
      • 特点
      • 好处
    • axios
      • axios 的基本使用
        • 发起 GET 请求
        • 发起 POST 请求
      • 使用解构赋值
    • vue-cli
      • 什么是单页面应用程序?
      • 什么是vue-cli?
      • 安装和使用
      • vue项目的运行流程
    • vue组件
      • 组件化开发
      • vue 中的组件化开发
      • vue 组件的三个组成部分
        • template
        • script
        • style
        • 实例
        • 启用less语法以及唯一根节点
      • 组件之间的父子关系
        • 使用组件的三个步骤
        • 实例
      • 组件的props
        • 实例
        • props 是只读的
        • props 的 default 默认值
        • props 的 type 值类型
        • props 的 required 必填项
      • 组件之间的样式冲突问题
        • scoped
        • /deep/ 样式穿透
  • 五、生命周期&数据共享
    • 生命周期 & 生命周期函数
    • 组件生命周期函数的分类
    • 生命周期详解
      • 简洁版本
      • 详细版本
      • 最重要的三个阶段
    • 组件之间的关系
      • 父子组件之间的数据共享
        • 父组件向子组件共享数据
        • 子组件向父组件共享数据
      • 兄弟组件之间的数据共享
    • ref 引用
      • 什么是 ref 引用
      • 使用 ref 引用 DOM 元素
      • 使用 ref 引用组件实例
      • 控制文本框和按钮的按需切换
      • this.$nextTick(cb) 方法
    • 数组中的方法
      • some循环
      • foreach循环
      • every循环
      • reduce的基本用法
    • 购物车案例
      • 导入,注册,使用组件
      • 基于axios请求列表数据
      • 渲染Goods组件
      • 渲染Footer组件
  • 六、动态组件&插槽&自定义指令&axios
    • 动态组件
      • 什么是动态组件
      • 如何实现动态组件渲染
      • 使用 keep-alive 保持状态
      • keep-alive 对应的生命周期函数
      • keep-alive 的 include 属性
    • 插槽
      • 体验插槽的基础用法
        • 为具名插槽提供内容
        • 具名插槽的简写形式
      • 作用域插槽
        • 使用作用域插槽
        • 解构插槽 Prop
    • 自定义指令
      • 什么是自定义指令
      • 自定义指令的分类
      • 私有自定义指令
      • 使用自定义指令
      • 为自定义指令动态绑定参数值
      • 通过 binding 获取指令的参数值
      • update 函数
      • 函数简写
      • 全局自定义指令
    • 把axios挂载到vue原型上
  • 七、路由
    • 是什么?
    • 前端路由的工作方式
    • 实现简易的前端路由
    • vue-router 的基本用法
      • vue-router安装
      • 创建路由模块
      • 导入并挂载路由模块
      • 声明路由链接和占位符
      • 声明路由的匹配规则
    • 路由重定向
      • 嵌套路由
      • 声明子路由链接和子路由占位符
      • 通过 children 属性声明子路由规则
    • 动态路由匹配
      • $route.params 参数对象
      • 使用 props 接收路由参数
      • 声明式导航 & 编程式导航
        • vue-router 中的编程式导航 API
        • $router.push
        • $router.replace
        • $router.go
        • $router.go 的简化用法
      • 导航守卫
        • 全局前置守卫
        • 守卫方法的 3 个形参
        • next 函数的 3 种调用方式
        • 控制后台主页的访问权限
  • 八、补充知识
    • URL种的#是什么意思?
      • HTTP请求不包括#
      • #后的字符
      • 改变#不触发网页重载
      • 改变#会改变浏览器的访问历史
    • ?说明
      • **连接作用**
      • 清除缓存
    • &说明

一、前端工程化

image-20221115083618555

JS的复用就是模块化

UI样式复用就是组件化(LayUI里面的都是组件化)

所以说前端工程化就是有规范的写,不能你一个样式我一个样式,不够统一不够专业!

二、WebPack

是什么

image-20221115084730331

前端工程化的具体实现方案

基本使用

实现奇偶行变色

1.初始化包管理工具

通过npm init -y生成

image-20221115085243047

2.安装jquery

-S的意思是–save

npm install jquery -S

3.在项目中安装webpack

-D就是把包放到devDependencies下,打包运行的时候不会被打包

-D为–save-dev简写

npm install webpack@5.42.1 webpack-cli@4.7.2 -D 

image-20221115095016557

4.在项目中配置webpack

在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:

module.exports = {
    mode: 'development'
};

在 package.json 的 scripts 节点下,新增 dev 脚本如下:

image-20221115102840682

tips:webpack要和src同目录

image-20221115102745568

5.运行代码

通过npm run dev运行

这里的webpack将用jQuery写的操作和一些新的写法转换成了能被浏览器兼容的js文件(dist下的main.js)

image-20221115103323407

实现效果如下:

image-20221115104323386

mode 的可选值

development

开发环境

不会对打包生成的文件进行代码压缩和性能优化

打包速度快,适合在开发阶段使用

production

生产环境

会对打包生成的文件进行代码压缩和性能优化

打包速度很慢,仅适合在项目发布阶段使用

image-20221115104043506

webpack.config.js 文件的作用

webpack.config.js 是 webpack 的配置文件。

webpack 在真正开始打包构建之前,会先读取这个配置文件, 从而基于给定的配置,对项目进行打包。

注意:由于 webpack 是基于 node.js 开发出来的打包工具,因此在它的配置文件中,支持使用 node.js 相关 的语法和模块进行 webpack 的个性化配置。

webpack 中的默认约定

在 webpack 4.x 和 5.x 的版本中,有如下的默认约定:

① 默认的打包入口文件为 src -> index.js

② 默认的输出文件路径为 dist -> main.js

注意:可以在 webpack.config.js 中修改打包的默认约定

自定义打包的入口与出口

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

示例代码如下:

const path = require('path')//导入node.js中专门操作路径的模块

module.exports = {
    mode: 'production',
    entry: path.join(__dirname,'./src/index.js'),//打包的入口文件
    output: {
        path: path.join(__dirname,'./dist'),//存放路径
        filename: "nice.js"//输入的文件名
    }
};

image-20221115105746224

webpack中的插件

webpack 插件的作用

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

① webpack-dev-server

类似于 node.js 阶段用到的 nodemon 工具(修改代码自动重新打包和构建)

每当修改了源代码,webpack 会自动进行项目的打包和构建(最常用)

② html-webpack-plugin

webpack 中的 HTML 插件(类似于一个模板引擎插件)

可以通过此插件自定制 index.html 页面的内容

安装之后我们还不能直接访问,因为打包生成的文件存放到了内存中

生成到内存中的文件该如何访问?

webpack-dev-server 生成到内存中的文件,默认放到了项目的根目录中,而且是虚拟的、不可见的。

可以直接用 / 表示项目根目录,后面跟上要访问的文件名称,即可访问内存中的文件

例如 /bundle.js 就表示要访问 webpack-dev-server 生成到内存中的 bundle.js 文件

所以我们只有把index页面放到根目录它才能和bundle.js联合使用,才能实现实时更新

怎么实现呢?拷贝过去一份不就行了!我们用下面的方法来实现

html-webpack-plugin

html-webpack-plugin 是 webpack 中的 HTML 插件,可以通过此插件自定制 index.html 页面的内容。

需求:通过 html-webpack-plugin 插件,将 src 目录下的 index.html 首页,复制到项目根目录中一份!

安装

npm install html-webpack-plugin@5.3.2 -D

配置

const path = require('path')//导入node.js中专门操作路径的模块
const HtmlPlugin = require('html-webpack-plugin')

// 创建html插件的实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html',//源文件存放路径
    filename: './index.html'//生成的文件存放路径
})

module.exports = {
    mode: 'development',
    plugins: [htmlPlugin]//通过plugins节点,使htmlPlugin插件生效
};

总结

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

devServer 节点

在 webpack.config.js 配置文件中,可以通过 devServer 节点对 webpack-dev-server 插件进行更多的配置, 示例代码如下:

module.exports = {
    mode: 'development',
    plugins: [htmlPlugin],//通过plugins节点,使htmlPlugin插件生效
    devServer: {
        open: true,
        // host: '',
        port: 80
    }
};

mac中要加sudo才能监听

webpack 中的 loader

loader 概述

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

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

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

image-20221115142755075

loader 的调用过程

image-20221115141421952

打包处理 css 文件

  • 运行 npm i style-loader@3.0.0 css-loader@5.2.6 -D 命令,安装处理 css 文件的 loader

  • 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module: {
  rules: [
    {
      test: /\.css$/, use: ['style-loader', 'css-loader']
    }
  ]
}

image-20221115143446870

打包处理 less 文件

less文件可以让CSS写的更简单,这里是让无序列表的间隙消失

html,
body,
ul{
  margin: 0;
  padding: 0;
  li{
    line-height: 30px;
    padding-left: 20px;
    font-size: 12px;
  }
}

之后在index.js文件中引入改less文件即可

如果不设置less文件加载器,也会报错.所以运行 npm i less-loader@10.0.1 less@4.1.1 -D 命令

在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module: {
    rules: [
        {test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']}
    ]
}

效果不放了因为太刺眼了

打包发布

通过前面的学习我们也能知道,你输入npm run dev 的时候它就会生成一个dist目录,这个dist目录其实就是打包好的,可以直接点index文件去访问的

现在项目要上线了,我们要减少dist文件的体积,其实就是运行npm run 生产环境的配置

在package.json配置一下:

"scripts": {
  "dev": "webpack serve",
  "build": "webpack --mode production"
},

image-20221115155918186

运行程序:

npm run build

总结

webpack了解概念即可,后面使用脚手架这东西都是配置好的

  • 运行程序npm run dev
  • 发布程序npm run build

如果不是这个两个命令,那就去看它的package咋写的替换run 后面的单词即可

三、Vue基础入门

Vue简介

什么是Vue

构建用户界面的框架

  • 构建用户界面

用 vue 往 html 页面中填充数据,非常的方便

  • 框架

框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!

要学习 vue,就是在学习 vue 框架中规定的用法!

vue 的指令、组件(是对 UI 结构的复用)、路由、Vuex、vue 组件库

Vue 的两个特性

数据驱动视图:

  • 数据的变化会驱动视图自动更新
  • 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!

image-20221115161034333

双向数据绑定:

在网页中,form 表单负责采集数据,Ajax 负责提交数据

  • js 数据的变化,会被自动渲染到页面上
  • 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中

注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)

image-20221115161236461

MVVM的原理

image-20221115161907387

image-20221115164735079

总结

课件其实已经总结的很好了,MVVM最重要的就是VUE的实例VM(ViewModel)

  • 它监听DOM的变化,当表单中的值发生变化时,VM会把数据同步到Model源中
  • 它监听Model的变化,当Model发生变化时,它会把最新数据同步到View里

Vue的基本使用

Vue的基本使用步骤

  • 导入vue.js文件
  • 在页面声明一个将要被vue所控制的DOM区域
  • 创建vm实例
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="app">{{username}}</div>

    <script src="./lib/vue-2.6.12.js"></script>

    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          username: "zs",
        },
      });
    </script>
  </body>
</html>

基本代码与 MVVM 的对应关系

image-20221115173712799

Vue指令

内容渲染指令

  1. v-text 指令的缺点:会覆盖元素内部原有的内容!
  2. {{ }} 插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!
  3. v-html 指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!

属性绑定指令

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

  • 在 vue 中,可以使用 v-bind: 指令,为元素的属性动态绑定值;

  • 简写是英文的 :

  • 在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:

    <div :title="'box' + index">这是一个 div</div>
    

事件绑定

  1. v-on: 简写是 @

  2. 语法格式为:

    <button @click="add"></button>
    
    methods: {
       add() {
    			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
    			this.count += 1
       }
    }
    
  3. $event 的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。例如:

    <button @click="add(3, $event)"></button>
    
    methods: {
       add(n, e) {
    			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
    			this.count += 1
       }
    }
    
  4. 事件修饰符:

    • .prevent

      <a @click.prevent="xxx">链接</a>
      
    • .stop

      <button @click.stop="xxx">按钮</button>
      

image-20221115192231374

v-model 指令

  1. input 输入框
    • type=“radio”
    • type=“checkbox”
    • type=“xxxx”
  2. textarea
  3. select

条件渲染指令

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

在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!

v-if 指令在使用的时候,有两种方式:

  1. 直接给定一个布尔值 true 或 false

    <p v-if="true">被 v-if 控制的元素</p>
    
  2. 给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏

    <p v-if="type === 'A'">良好</p>
    

过滤器

Vue3已经放弃,Vue2可以用

怎么理解过滤器?就跟linux里的grep命令一样,就是筛选,它定义在filters里面

我们来看看代码示例:

  • 要定义到 filters 节点下,本质是一个函数
  • 在过滤器函数中,一定要有 return 值
  • 在过滤器的形参中,可以获取到“管道符”前面待处理的那个值
  • 如果全局过滤器和私有过滤器名字一致,此时按照“就近原则”,调用的是”私有过滤器“
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p>message的值是{{message | capi}}</p>
</div>

<script src="/lib/vue-2.6.12.js"></script>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vue.js'
        },
        filters:{
            //过滤器函数形参中的val,永远都是"管道符"前面的那个值
            capi(val){
                const first = val.charAt(0).toUpperCase()
                const other = val.slice(1)
                
                return first + other
            }
        }
    })
</script>

</body>
</html>

全局过滤器

全局过滤器 - 独立于每个 vm 实例之外
Vue. filter()方法接收两个参数:
第1 个参数,是全局过滤器的”名字”
第2 个参数,是全局过滤器的”处理函数”

Vue.filter('capi',(val) =>{
	return val.charAt(0).toUpperCase() + val.slice(1) + '~~~~~~~~~~~~~'
})

连续调用多个过滤器

把 message 的值,交给 filterA 进行处理
把 filterA 处理的结果,再交给 filterB 进行处理
最终把 filterB 处理的结果,作为最终的值這染到页面上
{{ message 1 filterA I filterB }}

{{ message | filterA | filterB }}

过滤器传参

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

image-20221116113238654

示例代码如下:

image-20221116113315121

入门实例

实现增删查功能

实现思路:

  • 增加功能

首先要收集品牌名称,然后阻止表单的默认提交行为,改为调用自定义方法add

在add中定义要添加的对象,name为收集到的brand,状态为status设置为默认值即可,创建时间也设置一个默认值即可

id的话想要保证自增,所以可以自定义一个id,然后每添加一个对象id+1

对象创建好之后,直接push进list列表即可

  • 删除功能

从list列表中过滤对象,通过传入的对象id即可过滤

  • 查询功能

通过v-for去遍历data区域的list数组

image-20221116105130811

完整代码如下:

<!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">
</head>

<body>

<div id="app">
    <!-- 卡片区域 -->
    <div class="card">
        <div class="card-header">
            添加品牌
        </div>
        <div class="card-body">
            <!-- 添加品牌的表单区域 -->
            <!--            表单有默认的提交行为,通过@submit.prevent可以阻止它的默认行为-->
            <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="brand">
                        </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="'cd' + item.id" v-model="item.status">
                    <label class="custom-control-label" :for="'cd' + item.id" v-if="item.status">已启用</label>
                    <label class="custom-control-label" :for="'cd' + item.id" v-else>已禁用</label>
                </div>
            </td>
            <td>{{item.time}}</td>
            <td>
                <a href="javascript:;" @click="remove(item.id)">删除</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

<script src="./lib/vue-2.6.12.js"></script>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            //品牌的列表数据
            brand: "",
            list: [
                {id: 1, name: '宝马', status: true, time: new Date()},
                {id: 2, name: '奔驰', status: false, time: new Date()},
                {id: 3, name: '奥迪', status: true, time: new Date()},
            ],
            nextId: 4,
        },
        methods: {
            remove(id) {
                // console.log(id)
                this.list = this.list.filter(item => item.id != id)
            },
            add() {
                // console.log(this.brand)
                // 如果判断到brand的值为空字符串,则return出去
                if (this.brand === '') return alert("必须填写品牌名称")

                // 如果没有return出去,应该去执行添加的逻辑
                // 先把要添加的品牌对象,整理出来
                const obj = {
                    id: this.nextId,
                    name: this.brand,
                    status: true,
                    time: new Date()
                }
                this.list.push(obj)
                this.brand = ''
                this.nextId += 1

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

</html>

四、Vue基础进阶

watch 侦听器

什么是侦听器

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

image-20221116114639935

侦听器的格式

  1. 方法格式的侦听器

    • 缺点1:无法在刚进入页面的时候,自动触发!!!
    • 缺点2:如果侦听的是一个对象,如果对象中的属性发生了变化,不会触发侦听器!!!
  2. 对象格式的侦听器

    • 好处1:可以通过 immediate 选项,让侦听器自动触发!!!

    image-20221116152955400

    • 好处2:可以通过 deep 选项,让侦听器深度监听对象中每个属性的变化!!!

    image-20221116153008596

侦听器测试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <input type="text" v-model="username">
</div>
<script src="/lib/vue-2.6.12.js"></script>


<script>
    const vm = new Vue({
        el: '#app',
        data: {
            username: '',
        },
        watch: {
            username(newOlder, oldValue) {
                console.log('监听到了username发生了变化', newOlder, oldValue)
            },

        }
    })
</script>


</body>
</html>

image-20221116120019015

计算属性

是什么?

计算属性指的是通过一系列运算之后,最终得到一个属性值。

这个动态计算出来的属性值可以被模板结构或 methods 方法使用。示例代码如下:

image-20221117110139193

特点

  • 定义的时候,要被定义为“方法”
  • 使用计算属性的时候,当普通的属性使用即可

好处

  • 实现了代码的复用
  • 只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值!

axios

axios(发音:艾克C奥斯) 是一个专注于网络请求的库!

它封装了Ajax(通过 Ajax 可以异步从服务器请求数据并将数据更新到网页中,整个过程不需要重载(刷新)整个网页,可以将网页的内容更快的呈现给用户。)

axios 的基本使用

发起 GET 请求

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

简写:

const resu = axios.get('https://www.escook.cn/api/cart')
resu.then(function (books) {
	console.log(books)
})

axios返回的是一个Promise对象,在Promise对象中并不是服务器返回的结果,而是axios对服务器返回的结果又进行了一次封装,如下:

image-20221119172253294

简化如下:

image-20221119171748440

发起 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

image-20221119182015125

vue-cli

什么是单页面应用程序?

SPA(Single Page Application)

指的就是一个Web网站中只有唯一的一个HTML页面,所有的功能与交互都是在这唯一的一个页面完成

一般Vue项目打包之后会生成一个dist文件,这个dist文件就是下面这个样式的

image-20221117110545419

什么是vue-cli?

快速生成一个vue项目的开发环境,程序员可以专注在撰写应用上,而不必花好几天去纠结 webpack 配置的问题。

安装和使用

image-20221117111105875

  1. 在终端下运行如下的命令,创建指定名称的项目:

    vue cerate 项目的名称
    
  2. vue 项目中 src 目录的构成:

    assets 文件夹:存放项目中用到的静态资源文件,例如:css 样式表、图片资源
    components 文件夹:程序员封装的、可复用的组件,都要放到 components 目录下
    main.js 是项目的入口文件。整个项目的运行,要先执行 main.js
    App.vue 是项目的根组件。
    

vue项目的运行流程

在工程化的项目中,vue 要做的事情很单纯:通过main.jsApp.vue渲染到 index.html 的指定区域中。

image-20221117152015785

  • App.vue 用来编写待渲染的模板结构
  • index.html 中需要预留一个 el 区域
  • main.js 把 App.vue 渲染到了 index.html 所预留的区域中

渲染之后,会代替index页面原有的代码

image-20221117152808987

vue组件

组件化开发

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

vue 中的组件化开发

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

vue 组件的三个组成部分

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

template -> 组件的模版结构

Script -> 组件的JavaScript行为

Style -> 组件的样式

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

template

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

<template>
<!--当前组件的DOM结构,需要定义到template标签的内部 -->
</template>

tips:

  • template是vue提供的容器标签,只起到包裹性质的作用,他不会被渲染为真正的DOM元素
  • template 中只能包含唯一的根节点

script

vue 规定:开发者可以在 <script> 节点中封装组件的 JavaScript 业务逻辑。

image-20221117114636442

.vue 组件中的 data 必须是函数

image-20221117114820766

style

image-20221117114843269

image-20221117114906636

实例

<template>
  <div class="wahahaha">
    <h3>这是用户自定义的vue组件--{{ username }}</h3>
  </div>
</template>

<!--固定写法-->
<script>
export default {
  data() {
    return {
      username: 'zs'
    }
  }
}
</script>

<style>
  .wahahaha{
    background-color: pink;
  }
</style>

启用less语法以及唯一根节点

  • 组件中只能有一个根节点,也就是说不能写多个一级div,只能在一级div里定义多个低级div
  • less语法就是让css的编写更简单
<template>
  <div>
    <div id="wahahaha">
      <h3>这是用户自定义的vue组件--{{ username }}</h3>
      <button @click="changeName">点我改变名字</button>
    </div>
    <div>123</div>
  </div>

</template>

<!--固定写法-->
<script>
export default {
  data() {
    return {
      username: 'zs'
    }
  },
  methods: {
    changeName() {
      console.log(this),
          this.username = 'Wahahah'
    }
  },
  // 当前组件的监听器
  watch: {},
  // 当前组件的计算属性
  computed: {}
}
</script>

<style lang="less">
#wahahaha {
  background-color: pink;

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

组件之间的父子关系

image-20221117114957733

使用组件的三个步骤

image-20221117115039148

实例

image-20221117163916959

Hello.vue是我后来加

image-20221117165053906

通过 components 注册的是私有子组件

例如:

  • 在组件 A 的 components 节点下,注册了组件 F。

  • 则组件 F 只能用在组件 A 中;不能被用在组件 C 中。

注册全局组件

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

实例如下:

image-20221117115346254

组件的props

props 是组件的**自定义属性**,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性!

  • props中的数据,可以直接在模版结构中使用

image-20221117200707847

实例

left组件

  • 使用v-bind可以给属性赋值
  • 这里init自定义属性为字符串类型,通过v-bind代表你后面写的是js表达式,数字在js中就是Number型
<template>
  <div class="left-container">
    <h3>我是left</h3>
    <MyCount :init="9"></MyCount>
  </div>
</template>

<script>
export default {
  name: "Left",
}
</script>

<style>
.left-container {
  padding: 0 20px 20px;
  background-color: #42b983;
  min-height: 250px;
  flex: 1;
}
</style>

count组件

<template>
  <div>
    <p>count的值是:{{ init }}</p>
    <button @click="init += 1">Hi,点我给count+1</button>
  </div>
</template>

<script>
export default {
  props: ['init'],
  name: "Count",
  data() {
    return {
      count: 0,
    }
  }
}
</script>

<style scoped>

</style>

如图所示:

image-20221117200944902

props 是只读的

image-20221117201751163

要想修改 props 的值,可以把 props 的值转存到 data 中,因为 data 中的数据都是可读可写的!

所以props值的作用就是做一个初始化,最好是去操作data里的数据,所以这里可以通过this.init去把初始值赋给data里的count

this代表当前组件对象

<template>
  <div>
    <p>count的值是:{{ count }}</p>
    <button @click="count += 1">Hi,点我给count+1</button>
  </div>
</template>

<script>
export default {
  props: ['init'],
  name: "Count",
  data() {
    return {
      count: this.init
    }
  }
}
</script>

<style scoped>

</style>

props 的 default 默认值

在声明自定义属性时,可以通过 default 来定义属性的默认值。示例代码如下:

props:{

​ 自定义属性A:{},

​ 自定义属性B:{},

​ 自定义属性C:{},

}

export default {
  props: {
    init: {
      default: 0,
    }
  },
  name: "Count",
  data() {
    return {
      count: this.init
    }
  }
}

props 的 type 值类型

在声明自定义属性时,可以通过 type 来定义属性的值类型。示例代码如下:

export default {
  props: {
    init: {
      default: 0,
    }
  },
  name: "Count",
  data() {
    return {
      count: this.init,
      type: Number
    }
  }
}

props 的 required 必填项

就是说,你自定义的这个属性是必填项,不填就会报错

image-20221117203428415

组件之间的样式冲突问题

scoped

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

导致组件之间样式冲突的根本原因是:

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

为了提高开发效率和开发体验,vue 为 style 节点提供了 scoped 属性,从而防止组件之间的样式冲突问题:

image-20221117204209632

/deep/ 样式穿透

image-20221117204641697

什么时候会用到

如果代码引入了第三方组件库,想修改它的样式不能去直接修改它的源码,找到要修改的组件位置通过/deep/做样式穿透

五、生命周期&数据共享

生命周期 & 生命周期函数

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

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

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

组件生命周期函数的分类

image-20221118072616877

生命周期详解

简洁版本

回调函数是你留个处理方法给事件,事件发生了以后会自动执行你留下调处理方法

钩子函数是好比找了个代理,监视事件是否发生,如果发生了这个代理就执行你的事件处理方法;在这个过程中,代理就是钩子函数

在某种意义上,回调函数做的处理过程跟钩子函数中要调用调方法一样
但是有一点: 钩子函数一般是由事件发生者提供的。直白了说,它留下一个钩子,这个钩子的作用就是钩住你的回调方法

==钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。==一段用以处理系统消息的程序,用以处理系统消息的程序,是说钩子函数是用于处理系统消息的

img

详细版本

lifecycle

最重要的三个阶段

  • created

    组件的 porps/data/methods已创建好,都处于可用的状态。但是组件的模板结构尚未生成!

  • mounted

    已经把内存中的 HTML 结构,成功的渲染到了浏览器之中。此时浏览器中己然包含了当前组件的 DOM 结构。

  • update

    组件的最新数据,可以操作最新的DOM结构

组件之间的关系

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

① 父子关系

② 兄弟关系

image-20221118083359316

父子组件之间的数据共享

父子组件之间的数据共享又分为:

① 父 -> 子共享数据

② 子 -> 父共享数据

父组件向子组件共享数据

父组件向子组件共享数据需要使用自定义属性

如下:

父组件

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
  <div class="box">
    <Left></Left>
    <Right :username=userinfo :passwd=passwd></Right>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import Left from "@/components/Left";
import Right from "@/components/Right";

export default {
  name: 'App',
  components: {
    HelloWorld,
    Left,
    Right
  },
  data() {
    return {
      userinfo: {name: 'zs', age: 12},
      passwd: 123
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

.box {
  display: flex;
}
</style>

子组件

<template>

  <div class="rightContainer">
    <h2>
      我是right
    </h2>

    <h2>您的姓名是:{{username}}</h2>
    <h2>您的密码是:{{passwd}}</h2>
  </div>


</template>

<script>
export default {
  name: "Right",
  props: ['username','passwd']
}
</script>

<style scoped>
.rightContainer {
  background-color: aquamarine;
  flex: 1;
  height: 300px;
}
</style>

子组件向父组件共享数据

子组件向父组件共享数据使用自定义事件。

image-20221118101743108

如下:

image-20221118102521747

image-20221118102135369

兄弟组件之间的数据共享

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

image-20221118103529647

EventBus 的使用步骤

  1. 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
  2. 在数据发送方,调用 bus.$emit(‘事件名称’, 要发送的数据) 方法触发自定义事件
  3. 在数据接收方,调用 bus.$on(‘事件名称’, 事件处理函数) 方法注册一个自定义事件

ref 引用

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

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

什么是 ref 引用

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

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

组件的 $refs 指向一个空对象。

image-20221118114026831

使用 ref 引用 DOM 元素

如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:

image-20221118114121487

使用 ref 引用组件实例

image-20221118114137863

控制文本框和按钮的按需切换

image-20221118114709005

让文本框自动获得焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的 .focus() 方法即可。示例代码如下:

image-20221118114802704

this.$nextTick(cb) 方法

组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。通俗的理解是:等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。

image-20221118143829921

image-20221118143842473

数组中的方法

some循环

  • 简单来说some循环就是遇到终止条件可以停止继续寻找
  • foreach即使遇到终止条件也会继续寻找
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>
    const arr = ['詹姆斯', '科比', '2届MVP得主库里', '1.5']

    arr.forEach((item, index) => {
        console.log('ok')
        if (item === '2届MVP得主库里') {
            console.log(index)
        }
    })

    console.log('arr.some使用效果如下:')

    arr.some((item, index) => {
        console.log('ok')
        if (item === '2届MVP得主库里') {
            console.log(index)
            return true
        }
    })

</script>

</body>
</html>

image-20221118145828031

foreach循环

foreach就是循环每一项,some是循环到满足条件就停下来

every循环

判断数组中的数据是否被全选了使用every循环

image-20221118150334089

reduce的基本用法

不用reduce计算总和

image-20221118150529758

用reduce计算总和

image-20221118150948771

reduce的简化写法

image-20221118151333626

购物车案例

导入,注册,使用组件

这里的组件是写好的,我们直接导入,注册,使用

Tips:

  • 导入的组件名称一般都给它设置为首字母大写.这样和普通标签能有一个区分

image-20221119163139000

基于axios请求列表数据

axios是对ajax的封装,向后端发送请求就用它

这里是先定义一个封装请求列表数据的方法,然后在vue的created的生命周期阶段调用

created() {
  this.initCartList()
},
methods: {
  //封装请求列表数据的方法
  async initCartList() {
    //调用axios的get方法,请求列表数据
    const {data: res} = await axios.get('https://www.escook.cn/api/cart')
    // 只要请求回来的数据,在页面渲染期间要用到,则必须转存到data里
    this.list = res.list
  }
},

这里的await是用来解构赋值的它一般和async联合使用

那么解构赋值是什么呢?

就是前段通过axios向后端发送请求之后,后端返回的数据会先经过axios进行一次封装,不能直接拿到真实数据

如下:

image-20221119171748440

所以为了直接拿到真实数据,我们需要解构,从回复的数据中取出真实数据

{{data:res}}这是啥意思呢?

axios返回的是一个Promise对象,在Promise对象中并不是服务器返回的结果,而是axios对服务器返回的结果又进行了一次封装,如下:

image-20221119172253294

通过{{data:res}}意思就是取出Promise对象中的data区域数据,并把名字重命名为res

渲染Goods组件

1.商品数据其实就是一个个Goods组件

导入,注册,使用组件

<Goods></Goods>

2.给组件赋值,这里通过v-for来实现

首先看看请求到的结果

image-20221120093440652

list数组里不就是如下一个个的对象吗,然后赋值的时候通过对象.属性即可取得对应的值

这里的:key,:id,:title等都是为子组件的自定义属性,父组件向子组件传递数据就是通过自定义属性来进行传递的

<!--    这里为啥一直要写v-bind呢因为在等号后面我们写的是js表达式,如果不写v-bind则相当于我们传给它了一个字符串!-->
<Goods
    v-for="item in list"
    :key="item.id"
    :id="item.id"
    :title="item.goods_name"
    :img="item.goods_img"
    :price="item.goods_price"
    :state="item.goods_state "
>
</Goods>

3.修改商品的勾选状态

修改商品的勾选状态为子组件向父组件共享数据

通过自定义事件来实现

3.1 在子组件中为复选框绑定自定义事件

复选框状态每发生一次改变就会触发自定义事件

<input type="checkbox" class="custom-control-input" :id="'cb' + id" :checked="state"
       @change="stateChange"/>

3.2 在子组件中自定义事件如下

自定义时间名字为state-change,传递给父组件的数据为id和value

  • id表示当前商品
  • value表示最新的勾选状态
methods: {
  stateChange(e) {
    // console.log(e)
    console.log(e.target.checked)
    const newState = e.target.checked
    // 触发自定义事件
    this.$emit('state-change', {id: this.id, value: newState})
  }
}

3.3 父组件绑定自定义事件

通过参数e来接受子组件传来的数据

通过some循环找到改变状态的子组件判断的条件是id,找到之后给组件的状态赋值为子组件传来的真实数据

<Goods @state-change="getNewState"></Goods>
methods: {
    getNewState(e) {
      console.log(e)
      this.list.some(item => {
        if (item.id === e.id) {
          item.goods_state = e.value
        }
      })
    }
  },

渲染Footer组件

引入footer组件

footer组件做二件事:

  • 全选
  • 计算总价

全选为子组件向父组件共享数据 => 自定义事件

计算总价为父组件向子组件共享数据 => 自定义属性

<Footer
    :is-full="fullState"
    @fullChange="getFullState"
    :total-prices="amt"
></Footer>

全选功能的实现

//子组件
<input type="checkbox" class="custom-control-input" id="cbFull" :checked="isFull" @change="fullChange"/>

  methods: {
    fullChange(e) {
      // console.log(e.target.checked)
      // 触发自定义事件
      this.$emit('fullChange', e.target.checked)
    }
  }


// 动态计算全选的状态是true还是false
fullState() {
  return this.list.every(item => item.goods_state)
},
  
//父组件
  // 动态计算全选的状态是true还是false
  fullState() {
    return this.list.every(item => item.goods_state)
  },

计算总价功能的实现

子组件

props: {
  isFull: {
    type: Boolean,
      default: true
  },
    totalPrices: {
      type: Number,
        default: 0
    }
},

<div>
    <span>合计:</span>
<span class="total-price">{{ totalPrices.toFixed(2) }}</span>
</div>

<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ totalPrices.toFixed() }}</button>

父组件

computed: {
  //总价格
  amt() {
    // 先filter过滤,在reduce累加
    return this.list
        .filter(item => item.goods_state)
        //只有一行的箭头函数,可以省略return和{}花括号
        .reduce((total, item) =>
            (total += item.goods_price * item.goods_count),0)
  }
},

购买数量实现

和计算总价实现一个思路

  • 从集合中过滤出选中的商品
  • 取得选中商品的数量

取得数量之后,还需要和子组件共享数据,所以就用自定义属性来传递数据

computed: {
  //总数量
  totalQuantity() {
    return this.list
        .filter(item => item.goods_state)
        .reduce((total, item) => (total += item.goods_count), 0)
  }

子组件

<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ totalNum}}</button>

  props: {
    totalNum:{
      type:Number,
      default:0
    }
  },

六、动态组件&插槽&自定义指令&axios

动态组件

什么是动态组件

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

如何实现动态组件渲染

vue 提供了一个内置的 组件,专门用来实现动态组件的渲染。示例代码如下:image-20221120194223304

使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 组件保持动态组 件的状态。示例代码如下:

image-20221120194246584

keep-alive 对应的生命周期函数

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

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

image-20221120194329705

keep-alive 的 include 属性

include 属性用来指定:只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分隔:

image-20221120194346399

插槽

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

image-20221120194532307

可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

体验插槽的基础用法

在封装组件时,可以通过 元素定义插槽,从而为用户预留内容占位符。示例代码如下:

image-20221120194635365

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

v-slot只能放在组件上和template上,放在其他上面会报错

默认情况下,在使用组件的时候,提供的内容都会被填充到名字为default 的插槽之中

image-20221120200200258

为具名插槽提供内容

在向具名插槽提供内容的时候,我们可以在一个 <template>(包裹作用) 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。示例代码如下:

image-20221120200451005

具名插槽的简写形式

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。

例如 v-slot:header 可以被重写为 #header:

image-20221120200547696

作用域插槽

在封装组件的过程中,可以为预留的插槽绑定 props 数据,这种带有 props 数据的 叫做作用 域插槽

示例代码如下:

image-20221120201822789

使用作用域插槽

可以使用 v-slot: 的形式,接收作用域插槽对外提供的数据。示例代码如下:

image-20221120202402592

实例

image-20221120203040876

解构插槽 Prop

作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程。

示例代码如下:

image-20221120202640156

实例

image-20221120203414937

自定义指令

什么是自定义指令

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

自定义指令的分类

vue 中的自定义指令分为两类,分别是:

  • 私有自定义指令

  • 全局自定义指令

私有自定义指令

在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下:

image-20221120204949304

使用自定义指令

在使用自定义指令时,需要加上 v- 前缀。示例代码如下

image-20221120204724614

为自定义指令动态绑定参数值

为自定义指令动态绑定参数值

在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值:

image-20221120205114156

通过 binding 获取指令的参数值

在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值:

image-20221120205143256

update 函数

bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函 数会在每次 DOM 更新时被调用。示例代码如下:

image-20221120205222590

函数简写

如果 insert 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:

image-20221120205243275

全局自定义指令

全局共享的自定义指令需要通过“Vue.directive()”进行声明

示例代码如下:

image-20221120205317529

把axios挂载到vue原型上

缺点是无法对api接口实现复用!

image-20221202144907847

在其他组件上直接通过this. h t t p . g e t 或 者 t h i s . http.get或者this. http.getthis.http.post来发请求就行了

七、路由

是什么?

一组对应关系,在 SPA 项目中,不同功能之间的切换,要依赖于前端路由来完成

前端路由的工作方式

image-20221120215504662

实现简易的前端路由

步骤1:通过 <component>标签,结合 comName 动态渲染组件。示例代码如下:

image-20221120215552901

步骤2:在 App.vue 组件中,为 链接添加对应的 hash 值:

image-20221120215736699

步骤3:在 created 生命周期函数中,监听浏览器地址栏中 hash 地址的变化,动态切换要展示的组件的名称:

image-20221120215812178

vue-router 的基本用法

vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目 中组件的切换。

vue-router 的官方文档地址:https://router.vuejs.org/zh/

vue-router安装

在 vue2 的项目中,安装 vue-router 的命令如下:

npm i vue - router@3.5.2 -S

创建路由模块

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

image-20221121093807714

导入并挂载路由模块

在 src/main.js 入口文件中,导入并挂载路由模块。示例代码如下:

image-20221121094045835

声明路由链接和占位符

image-20221121094102418

声明路由的匹配规则

image-20221121094227580

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。 通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

image-20221121094327986

嵌套路由

image-20221121094346744

声明子路由链接和子路由占位符

image-20221121094440465

通过 children 属性声明子路由规则

image-20221121094457351

动态路由匹配

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

image-20221121094619335

$route.params 参数对象

image-20221121094644113

使用 props 接收路由参数

image-20221121094656134

声明式导航 & 编程式导航

vue-router 中的编程式导航 API

image-20221121095018303

$router.push

image-20221121095038559

$router.replace

image-20221121095059840

$router.go

image-20221121095112629

$router.go 的简化用法

image-20221121095123592

导航守卫

image-20221121095140954

全局前置守卫

什么是回调函数?

回调函数是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,在执行传进去这个函数,这个过程就叫回调!

白话文:主函数的事先干完,回头在调用传进来的那个函数.

image-20221121095154479

守卫方法的 3 个形参

next 函数的 3 种调用方式

image-20221121095226022

控制后台主页的访问权限

image-20221121095241472

八、补充知识

URL种的#是什么意思?

#代表网页中的一个位置。

比如,http://www.example.com/index.html#print就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。

在VUE中,路由的实现方式有两种,其中一种就是通过#标识符进行页面内导航从而实现路由切换。

image-20221202172317471

HTTP请求不包括#

#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包括#。
比如,访问下面的网址,http://www.example.com/index.html#print,浏览器实际发出的请求是这样的:

GET /index.html HTTP/1.1

Host: www.example.com

#后的字符

在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。
比如,下面URL的原意是指定一个颜色值:http://www.example.com/?color=#fff,但是,浏览器实际发出的请求是:

GET /?color= HTTP/1.1
 
Host: www.example.com

改变#不触发网页重载

单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。
比如,从http://www.example.com/index.html#location1改成http://www.example.com/index.html#location2,浏览器不会重新向服务器请求index.html。

说明同第一个,例如单页面应用SPA一样,路由的切换,不会重新加载页面,只是切换位置,或者切换组件;第二种应用就是在单个页面里面通过name和id切换当前显示的位置。

改变#会改变浏览器的访问历史

每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。值得注意的是,上述规则对IE 6和IE 7不成立,它们不会因为#的改变而增加历史记录。

说明:通过#的切换,是算在浏览器的访问历史中的,前进和后退都是生效的。

?说明

连接作用

通过?来带参数,连接域名和参数,经常会用到。

http://www.xxx.com/Show.asp?id=77&nameid=2905210001&page=1

清除缓存

http://www.xxxxx.com/index.html

http://www.xxxxx.com/index.html?test123123

两个url打开的页面一样,但是后面这个有问号,说明不调用缓存的内容,而认为是一个新地址,重新读取。

因为在做http请求的时候,如果浏览器检测到你的地址完全没变,会从缓存里读取先前请求过的数据,不再发送请求。有些时候是页面资源的加载,有些时候是API的get请求,都有可能。加上这个,会让浏览器认为这是一个新的地址,从而保证重新获取资源。

&说明

不同参数的间隔符

http://www.xxx.com/Show.asp?id=77&nameid=2905210001&page=1

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uni-app开发常用操作速查记录

记录一下uni-app中常用的使用方法或是操作步骤,方便后期速查使用. 1.设置对象属性 2.组件中数据变化监听方法 3.微信开发者工具中全局搜索与局部搜索 4.Page对象与Componet对象组成 5.tabbar页面切换方法 6.组件中自定义函数的参数传递 7.m…

Android Jetpack Compose的基本介绍

目录一、引言&#xff1a;Android Jetpack1.Jetpack是什么&#xff1f;2. 常用的Jetpack库二、Compose的基本概念1.什么是Jetpack Compose2.Compose的编程思想三、 Compose简单的案例: 一个倒计时效果1.构建一个Compose项目2.声明一个倒计时的UI3.利用线程使其动起来4.实现效果…

快速了解Docker

目录 1.简介 2.Docker的安装及环境配置 2.1.查看是否是root用户 2.2.查看当前内核版本 2.3.更新yum源 2.4.安装Docker所需要的工具包 2.5.设置yum源 2.6.下载安装Docker 2.7.启动Docker并且设置开机自启动 2.8.测试是否安装成功 3.Docker阿里云镜像仓库配置 4.Docker常…

C++ vector

目录 1.vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用 1.2.1 vector的定义 1.2.2 vector iterator 的使用 1.2.3 vector 空间增长问题 1.2.3 vector 增删查改 1.2.4 vector 迭代器失效问题。&#xff08;重点&#xff09; 1.2.5 vector 在OJ中的使用 2.vec…

【Linux】Linux的常见指令详解(上)

目录 前言 ls pwd cd mkdir touch rm man tree nano cp mv cat echo more/less 前言 &#x1f9c1;Linux作为相较于windows的另一种操作系统&#xff0c;同时基于其开源的优越性&#xff0c;使得其在各各企业的使用率极高。因此学好Linux操作系统对我们来说是…

Mongoose应用和文件文件的上传和下载

一、Express框架访问MongoDB数据库 1、目的&#xff1a; ​ &#xff08;1&#xff09;mongoose模块的使用 ​ &#xff08;2&#xff09;学会代码的封装&#xff1a;dao层、service层、接口层 ​ &#xff08;3&#xff09;MVC设计思想&#xff1a;M(Model)、V(View)、C(C…

[附源码]Python计算机毕业设计Django基于SpringBoot的演唱会购票系统论文2022

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

c#与mysql连接和操作教程(增、删、改、查)

一、mysql的连接&#xff08;使用的是vs2019&#xff09; 1. 在一个项目中选择 工具 > NgtGet包管理器 > 管理解决方案的NuGet程序包 2. 搜索MySql.Data&#xff0c;然后下载&#xff0c;并在右边选着对应的项目进行安装&#xff08;ps&#xff1a;每个项目要连接数据库…

【身份证识别】基于BP神经网络实现身份证识别附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

代码随想录刷题|LeetCode 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

目录 300.最长递增子序列 思路 1、dp[i]的定义 2、递推公式 3、dp数组初始化 4、确定遍历顺序 5、推导dp数组 最长递增子序列 674. 最长连续递增序列 思路 最长连续递增序列 动态规划 贪心算法 718. 最长重复子数组 思路 1、确定dp数组的含义 2、确定递推公式 3、dp数组初始化…

docker 命令

目录 Docker 环境信息命令 docker info docker version 系统日志信息常用命令 docker events docker logs docker history 容器的生命周期管理命令 docker create docker run 常用选项 系统 网络 健康检查 命名空间选项 cgroup资源限制选项 CPU CPUset devi…

李宏毅《DLHLP》学习笔记7 - Voice Conversion 1

视频链接&#xff1a;https://www.youtube.com/watch?vJj6blc8UijY&listPLJV_el3uVTsO07RpBYFsXg-bN5Lu0nhdG&index9&ab_channelHung-yiLee 课件链接&#xff1a;https://speech.ee.ntu.edu.tw/~tlkagk/courses/DLHLP20/Voice%20Conversion%20(v3).pdf 1. 语音转…

永磁同步电机恒压频比(V/F)开环控制系统Matlab/Simulink仿真分析及代码生成到工程实现(二)

文章目录前言一、SVPWM二、永磁同步电机恒压频比开环控制系统Matlab/Simulink仿真分析2.1.仿真电路分析2.1.1.恒压频比控制算法2.1.2.输出处理2.1.3.主电路2.2.仿真结果分析三、永磁同步电机恒压频比开环控制系统代码生成及工程实现3.1.恒压频比开环控制算法代码生成3.2.仿真验…

计算机毕业论文Java项目源码下载基于SSM的旅游资讯网站含前台与后台

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 《ssm地方旅游资讯网站》该项目采用技术&#xff1a;jsp 、springmvc、spring、mybatis 、css、js、jQuery、bootstrap、easyui等相关技术&#x…

在云服务器上部署jupyter服务器环境(with conda-forge)

tags: Python Conda Tips Server 写在前面 最近想折腾点服务器的新花样(总是空着太可惜了), 想到前阶段配置的jupyter, 发现这不就能部署在服务端吗?还不走流量的那种(指安装包时候), 话不多说, 开整! 下面的用户名以及组都是test, 用于测试. 大家需要改成自己的用户名. 安装…

【Nginx】负载均衡、动静分离理论篇

一、负载均衡 1. 应用场景&#xff1a; 2. 负载均衡是什么&#xff1f; 在当业务系统服务器无法支撑当前的业务量时&#xff0c;用户可以选择更高性能的服务器。 但更为合理的做法是通过在既有业务服务器基础上&#xff0c;增量的方式增加相同功能的服务器&#xff0c;将处理…

Linux操作系统(基础操作)

文章目录一、文件操作命令1. 目录和文件操作2. 查看文件内容3. 重定向4. 管道二、信息系统相关命令1. 查看系统进程 -- ps2. 查看系统监听端口 -- netstat3. 查看日志信息命令 -- head / tail三、用户权限和管理1. linux中的权限2.修改用户权限chmod3.增加用户、查看登录用户4.…

CAS-比较并交换

CAS-比较并交换 原子类 何为原子类 没有CAS之前 多线程环境不使用原子类保证线程安全i&#xff08;基本数据类型&#xff09; 常用synchronized锁&#xff0c;但是它比较重 &#xff0c;牵扯到了用户态和内核态的切换,效率不高。 public class T3 {volatile int number 0…

JMeter 进行函数助手MD5加密

JMeter 函数助手 MD5 加密 JMeter函数助手中&#xff0c;提供了MD5加密的方法&#xff0c;如图所示&#xff0c;我们将内容 “123456”进行加密&#xff0c;可以看到加密成功了。 下面我们来看看项目接口的请求参数。 这是一个认证接口&#xff0c;我们可以看到请求的参数中包…

MySQL-MVCC多版本控制及事务的隔离性

MySQL事务的启动方式 隐式&#xff1a;执行SQL语句自动提交&#xff08;前提MySQL使用SET AUTOCOMMIT1开启自动提交&#xff09;显式&#xff1a;begin/start transaction; update user set username timi where id 1; commit; begin/start transaction命令并不是一个事务的起…