vue基础+双元学习笔记

目录

 

1 webpack模块打包工具

1.1 webpack基本概念

1.1.1 为什么学webpack

1.1.2 webpack的基本概述

1.2 webpack使用步骤

1.2.1 环境准备

1.2.2 webpack的基本使用

1.3 webpack的配置

1.3.1 webpack的入口和出口

1.3.2 _yarn build执行流程图

1.3.3 隔行变色

1.3.4 webpack的插件

1.3.5 webpack打包css问题

1.3.6 webpack使用加载器css-loader,style-loader

1.3.7 webpack使用加载器less-loader

1.3.8 webpack处理图片文件

1.3.9 webpack加载文件的优缺点

1.3.10 加载字体图标

1.3.11 webpack对JS语法降级加载器

1.4 webpack开发服务器web-dev-server

1.4.1 webpack-dev-server模块的使用

1.4.2 webpack开发服务器改变配置

2 Vue基础

2.1 Vue 的基本概念

2.1.1 为什么学vue

2.1.2 Vue学习方式

2.2 @vue/cli脚手架工程化

2.2.1 脚手架的好处

2.2.2 安装

2.2.3 创建项目

2.2.4 脚手架目录和代码分析

2.2.5 项目架构了解

2.2.6 脚手架自定义配置

2.2.7 eslint检查代码

2.2.8 但vue文件讲解

2.2.9 脚手架项目,清理欢迎页面

2.3 Vue指令

2.3.1 vue插值表达式

2.3.2 vue基础-mvvm设计模式

2.3.3 vue指定-v-bind

2.3.4 Vue指令-v-on

2.3.5 Vue事件处理函数中,拿到事件对象

2.3.6 vue指令-v-on修饰符

2.3.7 按键修饰符

2.3.8 v-model双向绑定

2.3.9 v-model修饰符

2.3.10 Vue指令v-text和v-html

2.3.11 v-show和v-if

2.3.12 Vue指令v-for

3 Vue基础(key, 计算属性, 过滤器, 侦听器)

3.1 Vue基础 _更新监测, key作用

3.1.1 v-for就地更新

3.1.2 虚拟DOM

3.1.3 diff算法

3.1.4 diff算法-key

3.1.4 有key,值唯一不重复的字符串或数字

3.1.5 动态class

3.1.6 动态style

3.2 过滤器

3.2.1 过滤器的更多用法

3.3 计算属性 computed

3.3.1 计算属性缓存

3.3.2 计算属性的完整写法

3.4 侦听器

4 组件

4.1 组件概念,创建和使用

4.1.1 组件的概念

4.1.2 组件的基础使用

4.1.3 scoped作用

4.2 组件通信

4.2.1 组件通信_父传子_props

4.2.2 组件通信_父向子_配合通讯

4.2.3 单项数据流

4.2.4 组件通信_子向父传值_自定义事件

4.2.5 组件通信_EventBus

4.3 vue生命周期讲解

4.3.1 vue生命周期

4.3.2 钩子函数

4.3.3 钩子函数-初始化阶段

4.3.4 挂载阶段

4.3.5 更新阶段

4.3.6 销毁阶段

5 axios

5.1 axios的介绍

5.2 axios使用

5.3 get传参

5.4 post请求与传参

5.5 axios全局配置

6 $refs和$nextTick使用

6.1 获取DOM

​6.2 获取组件对象

6.3 $nextTick

6.4 组件name属性使用

7 Vue组件-进阶

7.1 动态组件

7.2 组件缓存

7.3 组件缓存-激活的钩子函数

7.4 组件插槽

7.4.1 插槽默认内容

7.4.2 具名插槽

7.4.3 作用域插槽

7.5 自定义指令

7.5.1 自定义指令的传值

8 Vue路由系统

8.1 Vue路由简介和基础使用

8.1.1 使用路由的原因

8.1.2 vue-router

8.1.3 组件分类

8.1.4 vue-router模块

8.2 声明式导航

8.2.1 声明式导航的基础使用

8.2.2 声明式导航-跳转传参

8.3 路由重定向

8.3.1 路由-404配置

8.3.2 路由-模式设置

8.4 编程式导航

8.4.1 编程式导航-跳转传参

8.5 路由嵌套

8.5.1 声明式导航-激活类名的区别

8.5.2 导航守卫

9 vant组件库

10 跨域解决方案--反向代理


  >  >  >  

1 webpack模块打包工具

1.1 webpack基本概念

1.1.1 为什么学webpack

  • 减少文件数量
  • 缩减代码体积
  • 提高浏览器打开的速度

webpack官网地址

1.1.2 webpack的基本概述

webpack本质是,一个第三方模块包,用于分析并打包代码

  • 支持所有类型文件的打包
  • 支持less/sass => css
  • 支持ES6/7/8 => ES5(高级的语法进行降级,兼容低版本浏览器)
  • 压缩代码,提高加载速度

1.2 webpack使用步骤

1.2.1 环境准备

(1) 初始化包环境

yarn init

(2) 安装依赖包

yarn add webpack webpack-cli -D

(3) 配置script(自定义命令)

"script": {

        "bulid": "webpack"

}

1.2.2 webpack的基本使用

(1) 首次打包

需求: 2个js文件 ->打包成1个js文件

分析:

①:新建src下的资源

②:add.js – 定义求和函数并导出

③:index.js – 引入add模块并使用函数输出结果

④:执行 `yarn build` 自定义命令, 进行打包 (确保终端路径在src的父级文件夹)

⑤:打包后默认生成dist和main.js, 观察其中代码

(2) 再次打包

需求:代码更多后, 如何打包呢?

分析:

①:src下新建tool/tool.js

②:定义数组求和函数导出

③:index.js – 引入tool模块的函数并使用, 打印结果

④:执行 `yarn build` 自定义命令, 进行打包 (确保终端路径在src的父级文件夹)

⑤:打包后默认生成dist和main.js, 观察其中代码

代码修改了要重新打包,且路径正确

process.env访问开发或者产品环境配置文件

1.3 webpack的配置

1.3.1 webpack的入口和出口

(1) 配置

默认入口: ./src/index.js

默认出口: ./dist/main.js

webpack配置 - webpack.config.js(默认)

  • 新建src并列处, webpack.config.js

  • 填入配置项

        const path = require("path")

        module.exports = {
            entry: "./src/main.js", // 入口
            output: { 
                path: path.join(__dirname, "dist"), // 出口路径
                filename: "bundle.js" // 出口文件名
            }
        }

  • 修改package.json, 自定义打包命令 - 让webpack使用配置文件

1.3.2 _yarn build执行流程图

1.3.3 隔行变色

步骤:

①:从0准备环境, 初始化包环境, 下载webpack和webpack-cli包, 配置自定义命令build

②:yarn下载jquery, 新建public/index.html,准备一些li标签

③:src/main.js 引入jquery, 编写功能代码

④:执行打包命令

⑤:复制public/index.html到dist/, 然后引入打包后的js, 运行网页观察效果

重点:webpack打包后的js引入到html中使用

1.3.4 webpack的插件

_html-webpack-plugin

简化了html的创建

(1) 安装

yarn add html-webpack-plugin -D

(2) webpack.config.js添加配置

1.3.5 webpack打包css问题

新建 - src/css/index.css

编写去除li圆点样式代码

(重要) 一定要引入到入口才会被webpack打包

执行打包命令观察效果

报错: 因为webpack默认只能处理js文件

1.3.6 webpack使用加载器css-loader,style-loader

css-loader 让webpack能处理css类型文件

style-loader 把css插入到DOM中

(1) 下载安装加载器

yarn add style-loader css-loader -D

(2) 配置

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

module.exports = {
    // ...其他代码
    module: { 
        rules: [ // loader的规则
          {
            test: /\.css$/, // 匹配所有的css文件
            // use数组里从右向左运行
            // 先用 css-loader 让webpack能够识别 css 文件的内容并打包
            // 再用 style-loader 将样式, 把css插入到dom中
            use: [ "style-loader", "css-loader"]
          }
        ]
    }
}

总结: 万物皆模块, 引到入口, 才会被webpack打包, css打包进js中, 然后被嵌入在style标签插入dom上

1.3.7 webpack使用加载器less-loader

(1) 安装

yarn add less less-loader -D

(2) 配置

module: {
  rules: [ // loader的规则
    // ...省略其他
    {
        test: /\.less$/,
        // 使用less-loader, 让webpack处理less文件, 内置还会用less翻译less代码成css内容
        use: [ "style-loader", "css-loader", 'less-loader']
    }
  ]
}

1.3.8 webpack处理图片文件

资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。

直接入口文件导入打包会报错,因为webpack无法自己处理图片文件

webpack5, 使用asset module技术实现字体文件和图片文件处理, 无需配置额外loader

以前用url-loader和file-loader来处理 现在webpack.config.js – 针对图片文件设置type: “assets“

再次打包观察效果 小于8KB文件, 文件转base64打包在js中, 大于8KB, 文件自动命名输出到dist下, 打包观察效果和2图区别

1.3.9 webpack加载文件的优缺点

图片翻译成了base64,放在js文件中

好处:浏览器不用发请求了,直接可以读取, 速度快

坏处: 图片太大,再转`base64`就会让图片的体积增大 30% 左右, 得不偿失

yarn install下载package.json中的所有包

1.3.10 加载字体图标

src/assets 下放入fonts字体相关文件夹(预习资料里)

src/main.js 引入 assets/fonts/iconfont.css

src/main.js 创建一个i标签, 使用字体图标标签添加到body上

添加针对字体文件的加载器规则, 使用asset/resource(直接输出文件并配置路径)

打包后运行网页观察效果

1.3.11 webpack对JS语法降级加载器

babel官网: https://www.babeljs.cn/

babel-loader文档: https://webpack.docschina.org/loaders/babel-loader/

  • babel: 一个javascript编译器, 把高版本js语法降级处理输出兼容的低版本语法
  • babel-loader: 可以让webpack转译打包的js代码
  • 在src/main.js – 定义箭头函数, 并打印箭头函数变量 (千万不能调用, 为了让webpack打包函数, 看降级效果)
// 高级语法
const fn = () => {
  console.log("你好babel");
}
console.log(fn) // 这里必须打印不能调用/不使用, 不然webpack会精简成一句打印不要函数了/不会编译未使用的代码
// 没有babel集成时, 原样直接打包进lib/bundle.js
// 有babel集成时, 会翻译成普通函数打包进lib/bundle.js
  • 下载加载器

yarn add -D babel-loader @babel/core @babel/preset-env

  • 配置到webpack.config.js上
{
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/, // 不去匹配这个文件夹下的js文件
        use: {
            loader: 'babel-loader', // 使用这个loader处理js文件
            options: { // 加载器选项
                presets: ['@babel/preset-env'] // 预设:转码规则(用bable开发环境本来预设的)
            }
        }
    }
  • 打包观察是否降级

1.4 webpack开发服务器web-dev-server

每次修改代码,重新yarn build打包,才能看到最新的效果,实际工作中,打包yarn build非常耗时

原因:

从0构建依赖

磁盘读取对应的文件到内存,webpack开始加载

再用对应的loader进行处理

将处理完的内容,输出到磁盘指定目录

解决:

起一个开发服务器,缓存一些已经打包的内容,只重新打包修改的文件,最终运行在内存中给浏览器使用

总结:

webpack开发服务器,把代码运行在内存中,自动更新,实时返回给浏览器显示

1.4.1 webpack-dev-server模块的使用

(1) 下载模块包

yarn add webpack-dev-server -D

(2) 自定义webpack开发服务器启动命令server-在package.json里

"script": {

        "build": "webpack",

        "server": "webpack serve"

}

(3) 启动当前工程里的webpack开发服务器

yarn server

(4) 重新编写代码,观察控制台和浏览器是否自动和更新

1.4.2 webpack开发服务器改变配置

(1) 配置端口号devServer.port

webpack.config.js中

devServer: {

        port: 3000

}

2 Vue基础

2.1 Vue 的基本概念

2.1.1 为什么学vue

  • 开发速度快,更高效
  • 企业开发都在使用
  • 前端工程师必备

(1) Vue是什么

渐进式的js框架,一套拥有自己规则的语法

官网地址:http://cn.vuejs.org/ (作者:尤雨溪)

(2) Vue里的渐进式概念

Vue从基础开始,会循序渐进向前学习,可以逐渐进行使用

(3) 库和框架

库: 封装的属性或方法(例如jQuery)

框架: 拥有自己的规则和元素,比库强大的多(Vue)

2.1.2 Vue学习方式

传统开发方式: 基于html文件开发Vue

工程化开发方式: 在webpack环境中开发Vue,这是最推荐最常用的

2.2 @vue/cli脚手架工程化

@vue/cli是Vue官方提供的一个全局模块包(得到vue命令), 此包用于创建脚手架项目

脚手架是为了保证各施工过程顺利进行而搭设的工作平台

2.2.1 脚手架的好处

开箱即用

0配置webpack

        babel支持

        css, less支持

        开发服务器支持

2.2.2 安装

(1) 安装

yarn global add @vue/cli

(2) 查看是否成功

vue -V //显示脚手架的版本

2.2.3 创建项目

(1) 创建项目

vue create vuecli-demo 注意: 项目名称不能有大写字母,中文和特殊字符

(2) 选择模板和包管理器,等待脚手架项目创建完成

(3) 启动开发服务器

cd 进入项目下,启动内置的webpack本地热更新开发服务器-浏览器项目页面

cd vuecli-demo

yarn serve

2.2.4 脚手架目录和代码分析

2.2.5 项目架构了解

目标: 知道项目入口,以及代码执行顺序和引入关系

main.js和App.vue, 以及index.html作用和关系?

  • main.js – 项目打包主入口 – Vue初始化
  • App.vue – Vue页面主入口
  • index.html – 浏览器运行的文件
  • App.vue => main.js => index.html

2.2.6 脚手架自定义配置

项目中没有webpack.config.js文件,因为Vue脚手架项目用的vue.config.js

src并列处新建vue.config.js, 填入配置, 重启webpack开发服务器

2.2.7 eslint检查代码

目标:是一种代码检查的工具

如果写代码违反了eslint的规则-报错(代码格式有没有问题,冗余)

演示: 在main.js中随便定义变量 – 不使用 – 观察eslint报错

方式1: 手动解决掉错误, 以后项目中会讲如何自动解决

方式2: 暂时关闭eslint检查(因为现在主要精力在学习Vue语法上), 在vue.config.js中配置后重启服务

module.exports = {

        lintOnSave: false // 关闭exlint检查

}

2.2.8 单vue文件讲解

vue推荐采用.vue文件来开发项目

template里只能有一个根标签

js独立作用域互不影响

style配合scoped属性,保证样式只针对当前template内标签生效

vue文件配合webpack,把他们打包起来插入到index.html

(2) 插件Vetur插件(vscode插件)

代码高亮提示和智能补全

2.2.9 脚手架项目,清理欢迎页面

assets和components 文件夹下的一切都删除掉 (不要默认的欢迎页面)

src/App.vue默认有很多内容, 可以全部删除留下template和script和style的框

2.3 Vue指令

2.3.1 vue插值表达式

在dom标签中,直接插入vue数据变量

又叫: 声明式渲染/文本插值

语法: {{ 表达式(三元表达式,变量等) }}

msg和obj是vue数据变量

要在js中data函数里声明

vue中变量声明在data函数return中:变量: value

2.3.2 vue基础-mvvm设计模式

目标: 转变思维,用数据驱动视图改变,操作dom的事,vue源码内干了

设计模式: 是一套被反复使用的,多数人知晓得,经过分类编目的,代码设计经验的总结

双向数据绑定: v变了m会自动变,m变了,v会自动变

数据驱动思想: vue不推荐操作DOM,直接操作数据

好处: 减少代码数,提高开发效率

2.3.3 vue指定-v-bind

目标: 给标签属性设置vue变量的值

v-bind语法和简写

语法:v-bind:属性名="vue变量"

简写:  :属性名="vue变量"

2.3.4 Vue指令-v-on

目标: 给标签绑定事件

语法

v-on: 事件名="要执行的少量代码"

v-on: 事件名=“methods中的函数名"

v-on: 事件名=“methods中的函数名(实参)"

@事件名=...简写形式

方法在methods选项定义

this指向的是export default后面的组件对象(vue创建的实例对象)(data和methods里的属性或方法都直接挂在它的身上)

2.3.5 Vue事件处理函数中,拿到事件对象

语法:

无传参,通过形参直接接受,直接在函数定义时书写e

传参,通过$event指代事件对象传给事件处理函数,后写e(调用时默认传参$event,声明时用e形参可以接受

形参和实参需要一一对应

2.3.6 vue指令-v-on修饰符

目标: 在事件后面.修饰符名 - 给事件带来更强大的功能

语法

  • @事件名.修饰符="methods里函数"

修饰符列表

  • .stop - 阻止事件冒泡
  • .prevent - 阻止默认行为
  • .once - 程序运行期间, 只触发一次事件处理函数(事件还触发,只是事件处理函数只执行一次)

2.3.7 按键修饰符

目标: 给键盘事件,添加修饰符,增强能力(keydown和keyup用法一致)

语法:

@keyup.enter - 监测回车按键

@keyup.esc - 监测返回按键

更多修饰符: https://cn.vuejs.org/v2/guide/events.html

2.3.8 v-model双向绑定(相当于mvvm)

value属性和vue数据变量,双向绑定到一起

语法: v-model="Vue数据变量"

双向数据绑定(双向指定的value属性-vue变量,暂时只能用在表单标签,后期可以用在组件中)

变量变化 -> 视图自动同步

视图变化 -> 变量自动同步

vue变量的初始值会影响表单的默认数据

(2) 复选框,单选框,下拉菜单,文本域的用法

  • 下拉菜单: v-model要绑定在select上,当选择相应的选项时,option项的value就绑定给变量
  • 复选框: v-model直接书写在标签上,当我们遇到复选框时,v-model的变量如果是非数组,它关联的是复选框checked属性(true和false),数组类型时,关联的是复选框的value属性
  • 单选框: 当写的变量名和表单的value属性匹配,可以实现默认绑定
  • 文本域: 文本域不用书写value,在标签内部书写内容

(3) v-model内部默认的绑定的是input事件,绑定的属性名是value

v-model的本质:v-bind(变量改变标签使用的变量跟随变化(属性名)) + v-on(标签事件改变时定义变量跟随改变(事件名))

可以使用model来修改model底层绑定的事件名和属性名(当一个组件只能使用一次,有很多次时可以使用.sync修饰符)

说到底就是需要在value值改变后将它赋值给中间变量,而value又是绑定在此变量上,所以就实现了数据的双向绑定

2.3.9 v-model修饰符

语法: v-model.修饰符

  • .number 让parseFloat(只转数字样式的字符串)转成数字类型赋值给Vue变量
  • .trim 去除首尾空白字符(不去除中间的空格)
  • .lazy 在change(失去焦点内容改变时)时触发而非input时

2.3.10 Vue指令v-text和v-html

语法:

  • v-text="Vue数据变量",用的较多
  • v-html="Vue数据变量",用的较少,因为有安全风险

注意: 会覆盖插值表达式

插值表达式和v-text用法相似

2.3.11 v-show和v-if

控制标签的隐藏和出现

语法: 

  • v-show="Vue变量"
  • v-if="Vue变量" //两者都可以起到隐藏和出现的效果
  • Vue变量: true //显示, false//不显示

原理:

  • v-show隐藏的方式采用的是display:none // 频繁切换的时候
  • v-if隐藏的方式采用的是DOM树直接移除 // 移除的时候

高级: 

  • v-else: 和if else语法类似,和v-if互斥

2.3.12 Vue指令v-for

列表渲染, 所在标签结构, 按照数据数量, 循环生成

语法:

  • v-for="(值变量, 索引变量) in 目标结构"
  • v-for="值变量 in 目标结构"

注意: 

  • 想要谁循环就放在谁身上(根据遍历到的数据动态生成标签)
  • 目标结构可以是数组/对象/字符串(可遍历结构)
  • 循环都是独立执行的
  • v-for的临时变量名只能用在v-for范围内

3 Vue基础(key, 计算属性, 过滤器, 侦听器)

3.1 Vue基础 _更新监测, key作用

目标结构变化, 触发v-for的更新

数组变更方法,就会导致v-for更新,页面更新,但只改变一个值的时候不会触发v-for更新

数组的非变更方法,返回新数组,就不会导致v-for更新,可采用覆盖数组(改变多个值)或this.$set(更新的目标的结构, 更新的位置, 更新的值)

这些方法会触发数组改变, v-for会监测到并更新页面

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

这些方法不会触发v-for更新

  • slice()
  • filter()
  • concat()

3.1.1 v-for就地更新

新旧DOM产生后对比,然后决定复用真实DOM/更新内容(对DOM的销毁和创建减到最少)

3.1.2 虚拟DOM

真实的DOM树: HTML的节点关系

虚拟DOM:本质是保存节点的关键信息,属性和内容的一个JS对象  

真实的DOM的属性太多,浏览器每次翻译标签为DOM的时候需要消耗时间

虚拟DOM的好处:

  • 提高DOM的更新性能,不用频繁操作真实DOM

3.1.3 diff算法

同级比较-根元素变化-整个DOM树删除重建

vue用diff算法, 新虚拟dom, 和旧的虚拟dom比较

情况1: 根元素变了, 删除重建

情况2: 根元素没变, 属性改变, ==元素复用==, 更新属性

3.1.4 diff算法-key

情况3: 无key

最大限度尝试就地修改/复用相同类型元素

v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key 来提供一个排序提示

==性能不高, 从第二个li往后都更新了==

情况4: 有key,值为索引

有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素

先产生新旧虚拟DOM,根据key比较,还是就地更新

新虚拟DOM的产生是根据原来数组的插入规则来的

3.1.4 有key,值唯一不重复的字符串或数字

给每个数据换成对象, 准备id, 把id的值作为key

好处: 可以配合虚拟DOM提高更新的性能

在生成虚拟DOM后,渲染真实标签的时候,diff算法会比较新旧虚拟DOM,有key会用key来进行比较,没key就地更新内容(尝试最大限度复用li标签,一般只会添加和减少li标签或修改li标签内容)

虚拟DOM的对象中子标签对象不会影响父级的diff比较

v-for循环中一般都得加:key,一般情况下用id,没id时用索引

3.1.5 动态class

用v-bind给标签class设置动态的值(提前写好class类名样式,通过动态class配置)

语法 :class="{类名: 布尔值}"

布尔值为true代表生效(默认为true)

false为不生效

3.1.6 动态style

语法 :style="{css属性名: 值}"      

值是变量的时候直接写,不是变量的时候需要加单引号

3.2 过滤器

转换格式,过滤器就是一个函数,传入值返回处理后的值

过滤器只能用在,插值表达式和v-bind动态属性里

语法:

  • Vue.filter("过滤器名", (值) => {return "返回处理后的值"})   // 全局过滤器,可以生效在所有的vue文件中
  • filters: {过滤器名字: (值) => {return "返回处理后的值"}}   // 局部过滤器,只在当前vue文件中生效

使用: 变量名 | 过滤器名

3.2.1 过滤器的更多用法

可以同时使用多个过滤器,或者给过滤器传参

语法: 过滤器传参: vue变量 | 过滤器名(参数)

多个过滤器: vue变量 | 过滤器1 | 过滤器2

3.3 计算属性 computed

一个变量的值,依赖另外一些数据计算而来的结果

语法: computed: {

        "计算属性名"() {

                return "值"

        }

}

注意: 计算属性也是vue数据变量, 所以不要和data里重名, 用法和data相同,不需要调用,使用的时候和变量一致

使用this.计算属性名也可以使用该变量

计算属性将基于它们的响应依赖关系缓存。计算属性只会在相关响应式依赖发生改变时重新求值。这就意味着只要计算属性依赖值(非响应式数据获得的计算属性值将永远不发生改变)还没有发生改变,多次访问时计算属性会立即返回之前的计算结果,而不必再次执行函数。(当有需求实时的获取值得时候可以采用函数调用的形式得到值)

3.3.1 计算属性缓存

计算属性,基于依赖项的值进行缓存,依赖的变量不变,都直接从缓存取结果

计算属性的优势:

  • 带缓存
  • 计算属性对应函数执行后,会把return值缓存起来
  • 依赖项不变,多次调用都是从缓存取值
  • 依赖项值-变化,函数会"自动"重新执行-并缓存新的值

面试题补充:

计算属性和方法的区别:

计算属性带有缓存,只要计算属性中变量的值不发生变化就不会重复执行

方法不带缓存,每次调用都会执行

3.3.2 计算属性的完整写法

给计算属性赋值需要setter

// 给计算属性赋值触发set方法

// 使用计算属性的值,触发get方法

语法: computed: {

        "属性名": {

                set(值) {

                },

                get() {

                        return "值"

                }

        }

}

计算属性和data的区别:

计算属性是依据别的变量计算而来

data是直接定义来的

数组every方法: 查找数组里"不符合"条件,查找成功直接原地返回false

3.4 侦听器

可以侦听data/computed属性值的改变

语法1: 

watch: {

        "被侦听的属性名" (newVal, oldVal) {

        }

}

高级语法:

watch: {

        "要侦听的属性名": {

                immediate: true, // 立即执行        

                deep: true, // 深度侦听复杂数据类型内变化

                handler (newVal, oldVal) {}

        }

}

4 组件

4.1 组件概念,创建和使用

4.1.1 组件的概念

  • 组件是可复用的 Vue 实例, 封装标签, 样式和JS代码
  • 组件化 :封装的思想,把页面上 `可重用的部分` 封装为 `组件`,从而方便项目的开发 和 维护
  • 一个页面, 可以拆分成一个个组件,一个组件就是一个整体, 每个组件可以有自己独立的结构 样式 和 行为(html, css和js)
  • 各自独立,互不影响

4.1.2 组件的基础使用

每个组件都是一个独立的个体, 代码里体现为一个独立的.vue文件

  • 创建组件, 封装要复用的标签, 样式, JS代码
  • 注册组件(使用前需要引入)
    • 全局注册 – main.js中 – 语法如图
    • 局部注册 – 某.vue文件内 – 语法如图
  • 使用组件(组件名当template标签使用,组件对象代表引入时命名的对象)

4.1.3 scoped作用

style标签上的scoped作用:

当前组件内标签都被添加data-v-hash值的属性

获取:css选择器都被添加[data-v-hash值]的属性选择器

4.2 组件通信

4.2.1 组件通信_父传子_props

父组件->子组件 传值

首先明确父和子是谁,在父引入子 (被引入的是子) 

子组件内,定义变量,准备接收,然后使用变量

父组件(App.vue)内, 要展示封装的子组件(MyProduct.vue)

引入组件, 注册组件, 使用组件, 传值进去

4.2.2 组件通信_父向子_配合通讯

(1) 可以使用v-for循环组件标签吗

可以使用: 

每次循环组件独立执行,互不影响

(2) props获取路由组件传参(通过props解耦)

开启props传参,说白了就是把路由参数映射到组件之中

(3) props中接收的数据可以以对象的形式接收,其中具体的项也是对象,并可以添加效验规则

4.2.3 单项数据流

从父到子的数据流向,叫单向数据流

  • 子组件修改父传入的数据不通知父亲,会导致数据的不一致
  • props里的变量不能修改,是只读的
  • 复杂数据类型如果不修改地址,只修改其中的属性,可以无视单项数据流,父与子的数据一致

4.2.4 组件通信_子向父传值_自定义事件

子组件触发父自定义事件方法

需求:商品组件,实现砍价功能

前置补充, 父->索引->子组件(用于区分是哪个子组件)

  • 父组件内,绑定自定义事件和事件处理函数
    • 语法: @自定义事件名="父methods里函数名"
  • 子组件内,恰当的时机,触发父给我绑的自定义事件,导致父methods里事件处理函数执行

4.2.5 组件通信_EventBus

常用于跨组件通信时使用

语法: 

src/EventBus/index.js

  • 新建vue实例并导出:import Vue from 'vue'; module default new Vue()
  • 在要接收值的组件(List.vue) eventBus.$on('事件名', 函数体)
  • 在要传递值的组件(MyProduct.vue) eventBus.$emit('事件名', 值)
  • eventBus技术本质是一个空白vue对象
  • 每一个vue组件都是一个单独的vue实例对象

vue中通过$.on()给vue实例注册事件,通过$.emit发送信息并告知$.on()触发事件,eventbus中,两个不相关的组件之间,都引入eventbus组件,建立联系,注册与触发事件

4.3 vue生命周期讲解

4.3.1 vue生命周期

从创建到销毁的整个过程就是-vue实例的-生命周期

4.3.2 钩子函数

Vue框架内置函数,随着组件的生命周期阶段,自动执行

作用: 特定的时间点,执行特定的操作

场景: 组件创建完毕后,可以在created生命周期函数中发起Ajax请求,从而初始化data数据

分类:4大阶段8个方法

4.3.3 钩子函数-初始化阶段

  • new Vue() - Vue实例化(组件也是一个小的Vue实例)
  • Init Event & Lifecycle-初始化事件和生命周期函数
  • beforeCreate-生命周期钩子函数被执行
  • Init injections&reactivity-Vue内部添加data和methods等
    • data等中的变量挂载在vue实例上
  • created-生命周期钩子函数被执行,实例创建
  • 接下来是编译模板阶段-开始解析
  • Has el option? – 是否有el选项 – 检查要挂到哪里
    • 没有. 调用$mount()方法
    • 有, 继续检查template选项

一般情况下,created使用较多,

使用场景:网络请求,注册全局事件

4.3.4 挂载阶段

  • 检查template选项
    • 有 - 编译template返回render渲染函数
    • 无 – 编译el选项对应#app)作为template(要渲染的模板)
  • 虚拟DOM挂载成真实DOM之前
  • beforeMount-生命周期钩子函数执行
  • Create… – 把虚拟DOM和渲染的数据一并挂到真实DOM上
  • 真实DOM挂载完毕
  • mounted – 生命周期钩子函数被执行

4.3.5 更新阶段

  • 当data里数据改变,更新DOM之前
  • beforeUpdate-生命周期钩子函数被执行
  • Virtual DOM......-虚拟DOM重新渲染,打补丁到真实DOM
  • updated – 生命周期钩子函数被执行
  • 当有data数据改变 – 重复这个循环

4.3.6 销毁阶段

  • 当$destroy()被调用 – 比如组件DOM被移除(例v-if)
  • beforeDestroy – 生命周期钩子函数被执行
  • 拆卸数据监视器、子组件和事件侦听器
  • 实例销毁后, 最后触发一个钩子
  • destroyed – 生命周期钩子函数被执行

5 axios

5.1 axios的介绍

axios是一个专门用于发送ajax请求的库,一种前端异步请求后端的技术

原理

浏览器window接口的XMLHttpRequest

特点

  • 支持客户端发送ajax请求
  • 支持服务器端Node.js发送请求
  • 支持Promise相关的语法
  • 支持请求和响应的拦截器功能
  • 自动转换JSON数据

axios的底层还是原生js实现, 内部通过Promise封装的,通用于前后端的请求库

5.2 axios使用

获取所有图书信息

5.3 get传参

在url?拼接 – 查询字符串

在url路径上 – 需要后端特殊处理

在请求体 / 请求头 传参给后台

5.4 post请求与传参

5.5 axios全局配置

配置基础地质,统一管理

axios.defaults.baseURL = "xxx"(当没配置的时候是主机地址)

修改请求url/以后的请求都不用带前缀基地址了 – 运行时, axios的baseURL会自动拼在前

6 $refs和$nextTick使用

6.1 获取DOM

通过id或ref属性获取原生DOM

在mounted生命周期 – 2种方式获取原生DOM标签

目标标签-添加id/ref

<h1 ref="myh1" id="h">1</h1>

恰当时机, 通过id / 通过ref属性 获取目标标签


6.2 获取组件对象

通过ref属性获取组件对象

创建Dome组件,写一个方法

app.vue使用Domo组件,给ref属性-名字随意

<组件 ref="myDome"></组件>

恰当时机,通过ref属性,获取组件对象,可调用组件对象里方法等(子传父的特殊方法,比较非主流,不常用)

6.3 $nextTick

点击该data,获取原生DOM内容

  • 创建标签显示数据

  • 点击+1,马上获取原生DOM内容

  • 得到的结果仍是原来的count,因为vue检测数据更新,开启一个DOM更新队列(异步任务)
  • 等DOM更新后,触发次方法里函数体执行:
    • this.$nextTick(函数体)(一般情况下写的箭头函数,因为箭头函数没有this指向,使其this指向vue实例对象)
    • nextTick的函数内部是封装了一个promise函数(他也会原地返回一个promise对象),其中执行的函数体代表.then
    • nextTick是一个微任务,比起setTimeout的执行顺序要靠前(set是宏任务)
    • vue中,每一次的数据更新,底层都对应一个微任务,用于更新DOM

6.4 组件name属性使用

组件name可用作注册组件名字

组件定义nam属性和值

注册组件可用上面name的值

可以对props: {}声明变量的值,可以进行效验

7 Vue组件-进阶

7.1 动态组件

多个组件使用同一个挂载点,并动态切换

方法: 设置挂载点<component>,使用is属性来设置要显示哪个组件

<component :is="要显示的动态组件名"></component>

7.2 组件缓存

频繁的切换组件,会导致组件频繁的创建和销毁

语法: vue内置的keep-alive组件把<component>包裹起来,可以进行组件缓存,防止次问题,提搞性能

可以缓存所有组件,不局限于<component>

7.3 组件缓存-激活的钩子函数

扩展两个新的生命周期函数

activated – 激活时触发
deactivated – 失去激活状态触发

配合组件缓存和组件动态挂载存在

7.4 组件插槽

通过slot标签, 让组件内可以接收不同的标签结构显示

语法口诀:

组件内,用<slot></slot>占位

使用组件时,传入标签替换slot标签(插入什么就在slot位置显示什么)

7.4.1 插槽默认内容

  • 如果外面不给串,想给个默认显示内容
  • 口诀: <slot>内放置内容,作为默认内容
    • 不给组件传标签. slot内容显示
    • 给组件内传标签, 则slot整体(包括默认)被换掉

7.4.2 具名插槽

组件内有2处以上不确定标签时,可以给slot起个名字

语法: 

  • slot使用name属性区分名字
    • <slot name="content"></slot>

v-slot:可以简化成#

7.4.3 作用域插槽

  • template配合v-slot:名字来分发对应的标签
    • <template v-slot:content>需要分发标签</template>

使用插槽时,想要使用子组件内变量

口诀:

  • 子组件, 在slot上绑定属性和子组件内的值
  • 使用组件, 传入自定义标签, 用template和v-slot="自定义变量名"
  • scope变量名自动绑定slot上所有属性和值
  • scope = {row: defaultObj}
  • v-slot:name="scope"可以混用代表,作用域和名字

不能直接用另外一个组件里变量,所以需要用到作用域插槽,组件内标签可以随意定义和使用

作用域插槽子组件可以看做是一个局部作用域,其中通过自定义属性的方法,把其中变量赋值给自定义属性,使其可以被外部使用

7.5 自定义指令

获取标签,扩展额外的功能

全局注册-语法

Vue.directive("指令名", {

        inserted(el) {

                //可以对el标签扩展额外功能

        }

})

局部注册-语法:

directives: {

        "指令名字": {

                inserted(el) {//对el进行操作}

        }

}

// 使用v-指令名字激活指令

inserted方法----指令所在标签,被插入到网页中才会执行(一次)

update方法----当指令对应标签/数据发生更新时执行

通过自定义指令可以理解内置指令:例如v-if,v-for都可以看作是通过将标签作为参数传入到指令执行函数中,继而进行功能编写

7.5.1 自定义指令的传值

语法:

 

8 Vue路由系统

8.1 Vue路由简介和基础使用

(1) 映射: 相互对应的关系

(2) 路由: 映射关系

8.1.1 使用路由的原因

  • 单页面应用(SPA): 所有功能在一个html页面上实现
  • 前端路由作用: 实现业务场景切换
  • 优点:
    • 整体不刷新页面,用户体验更好
    • 数据传递容易, 开发效率高
  • 缺点:
    • 开发成本高(需要学习专门知识)
    • 首次加载会比较慢一点,不利于seo

8.1.2 vue-router

本质是一个第三方包

官网:Vue Router

vue-router模块包

  • 它和 Vue.js 深度集成
  • 可以定义 - 视图表(映射规则)
  • 模块化的
  • 提供2个内置全局组件
  • 声明式导航自动激活的 CSS class 的链接

8.1.3 组件分类

.vue文件分2类,一个是页面组件,一个是复用组件

.vue文件本质无区别,方便大家学习和理解,总结的一个经验

src/views文件夹

页面组件-页面显示-配合路由用

src/components文件夹

复用组件-展示数据/常用于复用

8.1.4 vue-router模块

使用步骤:

  • 下载vue-router模块到当前工程
  • 在main.js中引入VueRouter函数
  • 添加到Vue.use()身上-注册全局RouterLink和RouterView组件
  • 创建路由规则数组-路径和组件名对应关系
  • 用规则生成路由对象
  • 把路由对象注入到new Vue实例中
  • 用router-view作为挂载点, 切换不同的路由页面

@是src的绝对地址

8.2 声明式导航

8.2.1 声明式导航的基础使用

vue-router提供了一个全局组件 router-link

router-link实质上最终会渲染成a链接 to属性等价于提供 href属性(to无需#)

router-link提供了声明式导航高亮的功能(自带类名)

当你点击 <router-link> 时,内部会调用这个方法,所以点击 <router-link :to="..."> 相当于调用 router.push(...)

8.2.2 声明式导航-跳转传参

在router-link上的to属性传值,语法:

  • /path?参数名=值
  • /path/值 – 需要路由对象提前配置 path: “/path/参数名”

对应页面组件接收传递过来的值

  • $route.query.参数名
  • $route.params.参数名

8.3 路由重定向

匹配path后,强制跳转path路径

网页打开url默认hash值是/路径

redirect是设置要重定向到哪个路由路径 //浏览器url中#后的路径被改变成/find-重新匹配规则

8.3.1 路由-404配置

找不到路径给个提示页面

路由最后,path匹配*(任意路径)-前面不匹配就命中最后一个

8.3.2 路由-模式设置

修改路由在地址栏的模式

hash路由例如: http://localhost:8080/#/home

history路由例如: http://localhost:8080/home (以后上线需要服务器端支持, 否则找的是文件夹)

方式:

const router = new VueRouter({

        routes,

        mode: "history" //不写默认是hash路径

})


8.4 编程式导航

用JS代码来进行跳转

语法: path或者name任选一个

使用name时,需要给路由规则里添加name属性

name和path的使用场景:

无感知,易于扩展,方便修改用name属性(在页面上看不见随便定义)

path可以在url的hash值看到(尽量符合组内规范)

8.4.1 编程式导航-跳转传参

语法:

query和params任选一个

注意: 使用path会忽略params

推荐: name+query方式传参

注意: 如果当前url上"hash值和?参数"与你要跳转到的"hash值和?参数"一致,就会报出冗余导航的错误,不会跳转.

$touter.back()返回上一页

8.5 路由嵌套

(1)在现有的一级路由下,再嵌套二级路由

  • src/views/Find.vue -- 发现音乐页
  • src/views/My.vue -- 我的音乐页
  • src/views/Second/Recommend.vue -- 发现音乐页 / 推荐页面
  • src/views/Second/Ranking.vue -- 发现音乐页 / 排行榜页面
  • src/views/Second/SongList.vue -- 发现音乐页 / 歌单页面

(2) main.js-继续配置2级路由

  • 一级路由path从/开始定义
  • 二级路由往后path直接写名字, 无需/开头(在一级路由规则里用children里书写)
  • 嵌套路由在上级路由的children数组里编写路由信息对象

(3) 说明

  • App.vue的router-view负责发现音乐和我的音乐页面, 切换
  • Find.vue的的router-view负责发现音乐下的, 三个页面, 切换

(4) 注意

  • 二级路由path一般不写根路径
  • 跳转时路径要从/开始写全
  • 二级路由如果加/表示根路径,即和父路由路径无关,只看自己写的路径

8.5.1 声明式导航-激活类名的区别

url上hash值(#/home/recommend)包含导航的href值(#/home) - 当前a就有 "router-link-active"类名

(#/home/recommend)和href(#/home/recommend)完全一致,添加router-link-exact-active类名

8.5.2 导航守卫

(1) 全局前置守卫

路由跳转之前,会触发一个函数

语法: router.beforeEach((to, from, next) => {}) //next(false)表示阻止跳转(当你要对路由权限判断时可以使用)

参数: 

  • to是一个路由的对象信息,表示要去往的路由页面
  • from也是一个路由对象信息,表示从哪里跳转
  • next一个函数体--next()才会让路由正常跳转,next(false)在原地停留,next("强制修改到另一个路由路径上")
  • 注意:如果不调用next页面就留在原地

9 vant组件库

Vant是一个轻量、可靠的移动端 Vue 组件库, 开箱即用

Vant组件库: https://vant-contrib.gitee.io/vant/#/zh-CN/

参照文档即可

Vue.use表示执行模块的install方法,在Vue的内部挂载属性,方法或者注册全局组件

10 跨域解决方案--反向代理

本地node服务器开启cors,负责请求的转发和数据接收回传

跨域只是浏览器数据请求时会发生,服务器之间的请求不存在跨域问题

this.$route表示路由规则对象,当path发生变化时就转换对应path的对象,自定义的属性需要写在meta中,可根据需求填写

11 对于vue自定义事件$event的理解

在自定义事件中,子组件调用$emit,vue实例方法,来让父组件自定义的事件触发,在html页签上只需写@自定义事件名="事件处理函数"其中事件处理函数不传参的原因是,vue默认为事件处理函数传了一个参数$event,并在methods中通过形参来接收,所以也可以直接在html上写$event来接收子组件传来的数据,自定义事件与原生$event不同的是,它更多的是作为事件的传参,而不是事件对象

12 依赖注入

通过provide和inject实例对象可以实现父组件给所有子组件传值

在父组件中声明provide对象,以函数的形式返回一个对象中需要传递的数据,在子组件中使用inject接收(使用方式和props类似)

13 vuex模块化

vuex里的模块化属性:modules,相当于每一个小的vuex

访问方法:$store.state.模块名.state的属性名(可以通过vuex的getters属性返回此数据,以达到简写的目的)

修改数据的方法:通过模块内的mutations属性定义修改的函数,在未开启命名空间时,外部通过$commit("方法名", 实参);开启命名空间(namespaced:true),外部修改方式一:$commit("模块名/方法名", 实参)-----由于方法名中有/,所以只能用this.["模块名/方法名"]的方式来访问和调用,方式二:$commit("模块名", ["方法名"])-----this.方法名()即可实现访问和调用

14 Vue知识点补充

14.1 响应式

vue中不支持响应式的两种情况:1.直接通过数组下标来修改元素的内容 2.给对象追加新的属性并赋值

如果实际需求中必须要这样更改,通过this.$set(数组/对象,数组的索引/对象字段,具体的值)进行更改,这样就可以出发响应式了

14.2 vue组件的函数式

functional: true // 为true,表示该组件为一个函数式的组件(没有data,和响应式数据,只会接受props,没有this,它就是一个函数,在export default根对象中书写)

14.3 v-for的进阶用法

(1)循环元组

<li v-for="(movie, index) in [
  'Lion King',
  'Frozen',
  'The Princess Bride'
]">
  {{ index + 1 }} => {{ movie }}
</li>

(2)循环对象

<li v-for="(value, key) in {
  name: 'Lion King',
  released: 2019,
  director: 'Jon Favreau',
}">
  {{ key }}: {{ value }}
</li>

(3)循环对象(加上元组循环方式)

<li v-for="(value, key, index) in {
  name: 'Lion King',
  released: 2019,
  director: 'Jon Favreau',
}">
  {{ index + 1 }} => {{ key }}: {{ value }}
</li>

15 混入mixins

在vue组件中mixins属性可以将混入的obj对象中的属性和方法合并到vue组件中的存在的属性和方法(created,data...)中

格式为: mixins: [obj, obj2]

使用场景:在多个页面中使用同一个变量或方法时,可以定义混入组件,在main.js中引入

Vue.mixin({

        methods: {

                ...具体方法

        }

})

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值