Webpack
Webpack是模块打包工具
作用:
1.减少文件数量
2.缩减代码体积
3.提高浏览器打开速度
webpack基本概述:
webpack本质是, 一个第三方模块包, 用于分析, 并打包代码的一个工具
1.支持所有类型文件的打包
2.支持less/sass => css
3.支持ES6/7/8 => ES5
4.压缩代码, 提高加载速度
环境准备
1. 初始化包环境(得到package.json文件)
npm init -y
2. 安装依赖包
npm install webpack webpack-cli -D
3. 配置scripts (自定义命令)
"bulid"可以修改
运行语句:
npm run build //bulid根据scripts对象里的那个来修改
使用webpack需要做哪些准备工作?
1.初始化文件夹包环境,得到package.json文件
2.下载webpack等模块包
3.在package.json自定义命令,为打包做准备
webpack如何使用
1.默认src/index.js–打包入口文件
2.需要将参与打包的文件引入到入口文件
3.执行package.json里build命令,执行webpack打包命令
4.默认输出dist/main.js的打包结果
代码增加后,如何打包呢?
1.确保在src/index.js引入和使用
2.重新执行npmbuild打包命令
3.0_webpack-入口和出口
配置文档:https://webpack.docschina.org/concepts/#entry
1.新建webpack.config.js
2.填入配置
3.修改入口文件名
4.打包观察效果
npm run build执行流程
总结npm run build后都做了什么:
1.执行webpack命令,找到配置文件,入口和依赖关系
2.打包代码输出到指定位置
html-webpack-plugin插件
配置文档:https://webpack.docschina.org/plugins/html-webpack-plugin/
1.下载插件
npm install html-webpack-plugin-D
2.webpack.config.js添加配置
总结:
如何让webpack打包时,自动生成html文件呢?
1.依赖html-webpack-plugin插件,npm下载此插件
2.在webpack.config.js配置写入即可
webpack-使用加载器
webpack如何支持css打包?打包后样式在哪里?如何生效?
下载 :npminstallcss-loaderstyle-loader-D
1.依赖css-loader和style-loader
2.css代码被打包进js文件中
3.style-loader会把css代码插入到head下style标签
webpack处理less文件
1.下载加载器来处理less文件 //npminstalllessless-loader-D
2.webpack.config.js针对less配置
3.新建src/less/index.less–设置li字体大小
4.把index.less引入到入口处
5.打包观察效果
webpack处理图片文件
文档:文档:https://webpack.docschina.org/guides/asset-modules/
webpack如何支持图片打包?对图片有哪2种处理方案?
1.webpack5,在rules里,针对图片文件设置type:asset
2.小于8KB转base64字符串进js里,大于8KB输出文件
webpack加载文件优缺点
1.好处是减少浏览器发送的请求次数,读取图片速度快
2.坏处是图片过大,转base64占空间会多30%左右
webpack处理字体图标
webpack5,使用assetmodule技术实现字体文件处理,无需额外的loader。
如下图添加针对字体文件的加载器规则,使用asset/resource(直接输出文件并配置路径)即可
1.src/assets下放入fonts字体相关文件夹(预习资料里)
2.src/main.js引入assets/fonts/iconfont.css
3.src/main.js创建一个i标签,使用字体图标标签添加到body上
4.打包后运行网页观察效果
type设置 'asset/resource' 会直接输出到dist下
webpack对JS语法降级
babel:一个javascript编译器,把高版本js语法降级处理输出兼容的低版本语法
babel-loader:可以让webpack转译打包的js代码
babel官网:https://www.babeljs.cn/
babel-loader文档:https://webpack.docschina.org/loaders/babel-loader/
1.下载加载器
npm install babel-loader @babel/core @babel/preset-env -D
2.配置到webpack.config.js上
3.在src/main.js–定义箭头函数,并打印箭头
webpack开发服务器
解决: 起一个开发服务器, 缓存一些已经打包过的内容, 只重新打包修改的文件, 最终运行在内存中给浏览器使用
总结: webpack开发服务器, 把代码运行在内存中, 自动更新, 实时返回给浏览器显示
webpack-dev-server模块使用
webpack-dev-server文档: https://webpack.docschina.org/configuration/dev-server/
1.下载模块包
npm install webpack-dev-server -D
2. 自定义webpack开发服务器启动命令serve – 在package.json里
3. 启动当前工程里的webpack开发服务器
npm run serve
4.如果运行后页面有报错 切换成开发者模式即可
在webpack.config.js里设置开发模式
Vue
Vue是什么?
答:渐进式javacript框架, 一套拥有自己规则的语法
什么是渐进式呢?
答:渐进式就是逐渐使用, 集成更多的功能
什么是库和框架呢?
答:库是方法的集合, 而框架是一套拥有自己规则的语法
@vue/cli和脚手架介绍
@vue/cli是Vue官方提供的一个全局模块包(得到vue命令), 此包用于创建脚手架项目
脚手架是为了保证各施工过程顺利进行而搭设的工作平台
好处:
不用自己配置Webpack,支持babel,css,less,开发服务器
@vue/cli安装
全局安装@vue/cli 模块包
npm install -g @vue/cli
安装完检查是否成功:
打开cmd小黑窗输入vue -V //显示版本号就算安装成功
@vue/cli 创建项目
1. 创建项目
vue create vuecli-demo //注意项目名不能有大写字母,中文和特殊符号
2. 选择模板和包管理器, 等待脚手架项目创建完毕
@vue/cli 启动开发服务
1. cd进入项目下, 启动内置的webpack本地热更新开发服务器 – 浏览项目页面
cd vuecli-demo
npm run serve //开启服务器
2. 如果未自动弹出浏览器, 手动打开输入提示的域名+端口浏览项目页面
@vue/cli 目录和代码分析
脚手架主要文件和作用
1. node_modules – 都是下载的第三方包
2. public/index.html – 浏览器运行的网页
3. src/main.js – webpack打包的入口
4. src/App.vue – Vue页面入口
5. package.json – 依赖包列表文件
项目架构了解
main.js和App.vue, 以及index.html作用和关系?
1. main.js – 项目打包主入口 – Vue初始化
2. App.vue – Vue页面主入口
3. index.html – 浏览器运行的文件
4. main.js => App.vue => index.html
@vue/cli 自定义配置
port是端口号,可以更改
open:true //true表示运行服务器自动打开浏览器
eslint检查代码
如果写代码违反了eslint的规则-报错 //例如定义了变量但不使用
处理eslint代码检查
单vue文件讲解
Vue推荐采用.vue文件来开发项目
ltemplate里只能有一个根标签
lvue文件-独立模块-作用域互不影响
lstyle配合scoped属性, 保证样式只针对当前template内标签生效
lvue文件配合webpack, 把他们打包起来插入到index.html
总结单vue文件
单vue文件好处?
独立作用域, 不再担心变量重名问题
单vue文件使用注意事项?
要注意template里只能有一个根标签
脚手架项目_清理欢迎界面
assets 和 components 文件夹下的一切都删除掉 (不要默认的欢迎页面)
lsrc/App.vue默认有很多内容, 可以全部删除留下template和script和style的框
Vue指令
Vue基础-插值表达式
什么是插值表达式?
双大括号, 可以把vue数据变量直接显示在标签内
Vue中变量声明在哪里?
data函数返回的对象上, 用key属性声明
vue基础-MVVM设计模式
简介:转变思维, 用数据驱动视图改变, 操作dom的事, vue源码内干了
设计模式: 是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结
什么是设计模式?
设计模式是对一般问题的通用解决方案
MVVM是什么?
MVVM(模型, 视图, 视图模型双向关联的一种设计模式)
MVVM好处?
减少DOM操作, 提高开发效率
Vue指令-v-bind
v-bind语法和简写
语法:v-bind:属性名="vue变量"
简写::属性名="vue变量"
Vue指令-v-on
语法
v-on:事件名=“要执行的少量代码"
v-on:事件名=“
methods中的函数名"
v-on:事件名=“methods中的函数名(实参)" //方法在methods选项定义
Vue指令-v-on
语法:
@事件名=“methods中的函数”
Vue指令-v-on事件对象
语法
无传参, 通过形参直接接收
传参, 通过$event指代事件对象传给事件处理函数
Vue事件处理函数, 如何拿到事件对象?
1. 无传参, 直接在形参接收
2. 有传参, 手动传入 对象
Vue指令-v-on修饰符
语法
@事件名.修饰符="methods里函数"
修饰符列表
.stop - 阻止事件冒泡
.prevent - 阻止默认行为
.once - 程序运行期间, 只触发一次事件处理函数
native 如果想在子组件中添加原生事件是行不通的,得添加native
Vue指令-v-on按键修饰符
语法:
@键盘事件.按键修饰符=“methods里函数名”
@keyup.enter - 监测回车按键
@keyup.esc - 监测返回按键
Vue指令-v-model
语法: v-model="Vue数据变量"
v-model用在哪里? //暂时只能用在表单标签上
v-model有什么作用? //把vue的数据变量和表单的value属性双向绑定在一起
作用1:双向绑定表单元素的value属性
作用2:v-model会自动绑定并接受input事件传递过来的值,并且把值同步给v-model绑定的变量
Vue指令-v-text和v-html
语法:
v-text="Vue数据变量"
!!!注意 :会覆盖插值表达式
v-text和v-html有什么作用?
都可以设置标签显示的内容
区别是什么?
v-text把值当成普通字符串显示
v-html把值当成标签进行解析显示
Vue指令-v-show和v-if
语法:
v-show="Vue变量"
v-if="Vue变量"
原理
v-show 用的display:none隐藏 (频繁切换使用)
v-if 直接从DOM树上移除
区别是什么?
v-show是用css方式隐藏标签
v-if直接从DOM树上移除
v-if 可以配合v-else或者v-else-if使用
Vue指令-v-for
语法:
v-for="(值变量, 索引变量) in 目标结构"
v-for="值变量 in 目标结构"
可以遍历数组 / 对象 / 数字 / 字符串 (可遍历结构)
!!!注意:v-for的临时变量名不能用到v-for范围外
流程:
v-for如何循环列表?
1. 谁想循环就把v-for写谁身上
2. v-for=“(值变量, 索引变量) in 目标结构”-一定注意
in两边必须有空格
3. 可以遍历数组 / 对象 / 固定数字
v-for注意事项?
值变量和索引变量不能用到v-for范围以外
v-for更新监测
数组方法会改变原数组, 就会导致v-for更新, 页面更新
数组方法不会改变原数组, 而是返回新数组, 就
不会导致v-for更新, 可采用覆盖数组或this.$set() //强制更新
v-for就地更新
就地更新原则,新旧DOM产生后对比, 然后决定是否复用真实DOM/更新内容
真实DOM
虚拟DOM
本质是保存节点关键信息的一个JS对象,比如保存属性和内容
虚拟DOM好处?
提高DOM更新的性能, 不频繁操作真实DOM, 在
内存中找到变化部分, 再更新真实DOM(打补丁)
V-for_无Key
v-for无key的情况下数据从第二个往后更新,性能不高
V-for_有key, 值为索引
有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素
语法:
V-for_有key, 值为索引
先产生新旧虚拟DOM, 根据key比较, 还是就地更新
V-for有key, 值唯一不重复的字符串或数字
有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素
给每个数据换成对象, 准备id, 把id的值作为key
V-for_有key, 值为id
先产生新旧虚拟DOM, 根据key比较
总结:使用v-for时有key用key且按照key更新没key就地更新,key得是唯一且不重复的字符串或者数值,有id用id,没id用v-for遍历出来的索引,好处是可以配合虚拟DOM提高性能
注意:数组采用会改变原始数据的更新方法时会导致v-for更新页面
动态class
语法 :class="{类名: 布尔值}"
动态style
语法 :style="{css属性名: 值}"
过滤器_定义使用
过滤器只能用在, 插值表达式和v-bind动态属性里
1.Vue中过滤器作用?
传入一个值, 处理后返回另外一个值
2.如何定义过滤器?
main.js – Vue.filter('过滤器名字', 函数体)
某.vue文件 – filters: {'过滤器名字': 函数体}
3. 如何使用过滤器?
Vue变量 | 过滤器名字
4. 过滤器注意事项?
插值表达式 / 动态属性
过滤器_传参和多过滤器
语法:
过滤器传参: vue变量 | 过滤器(实参)
多个过滤器: vue变量 | 过滤器1 | 过滤器2
计算属性_computed
简述:一个变量的值, 依赖另外一些数据计算而来的结果
语法:
特点:计算属性的依赖项发生改变的时候, 重新计算结
果返回
注意: 计算属性也是vue数据变量, 所以不要和data里重名, 用法和data相同
计算属性_缓存
计算属性, 基于依赖项的值进行缓存,依赖的变量不变, 都直接从缓存取结果
1.计算属性好处是?
带缓存
依赖项不变, 直接从缓存取
依赖项改变, 函数自动执行并重新缓存
2. 计算属性使用场景?
当变量值, 依赖其他变量计算而得来才用
计算属性_完整写法 //计算属性也是变量
语法:
1. 何时用计算属性完整写法?
给计算属性变量赋值时
2. set函数和get函数什么执行?
给计算属性赋值的时候触发set函数
获取计算属性的时候触发get函数
侦听器_watch
可以侦听data/computed属性值的改变
语法:
使用watch配置项, key是要侦听的data/计算属性名
侦听器_深度侦听和立即执行
1. 如何侦听一个对象/数组呢?
把侦听器写成对象形式, 给handler方法和deep:true
2. 侦听器函数马上执行?
immediate: true
Vue组件基础
组件概念:
组件是什么?
可复用的vue实例, 封装标签, 样式, JS
什么时候封装组件?
遇到重复标签, 可复用的时候
组件好处?
可复用,各自独立, 互不影响
组件_基础使用
简洁版:直接在需要用到的组件里面用尖括号<>>,括号里放入需要用到的组件名,然后根据提示按Tab 其余自动帮你生成
组件-scoped作用
准备: 会给当前组件内标签添加 data-v-hash值 的属性
获取: css选择器都被添加 [data-v-hash值] 的属性选择器
一般会加在页面里的Style标签上,防止跟其它组件一起使用时造成样式污染,加上后仅对自己页面的标签样式生效
组件通信_父传子_props
首先明确父和子是谁, 在父引入子 (被引入的是子)
1.子组件内, 定义变量, 准备接收, 然后使用变量
2. 父组件(App.vue)内, 要展示封装的子组件引入组件, 注册组件, 使用组件, 传值进去
总结:子组件内, props定义变量, 在子组件使用变量 父组件内, 使用子组件, 属性方式给props变量传值
补充:
通过value属性传值给子组件
自定义组件:当我们给自定义组件设置属性的时候,
这个属性会自动成为组件内根标签的属性。
(注意:这个属性必须不在子组件的props中,还有一些特殊属性也不会成为子组件根标签的属性,比如id。)
单向数据流 //从父到子的数据流向, 叫单向数据流
子组件修改, 不通知父级, 造成数据不一致性,会导致报错
Vue规定props里的变量, 本身是只读的
组件通信_子向父_自定义事件
1. 子组件内,当用户点击按钮的时候,自定义一个事件,并将数据通过该事件传递出去
子组件内, 恰当时机this.$emit('自定义事件名', 值 )
2 父组件内, 绑定子组件中的自定义事件和事件处理函数
语法: @自定义事件名="父methods里函数名"
组件通信-EventBus //常用于跨组件通信时使用
语法
src/EventBus/index.js – 创建空白Vue对象并导出
在要传递值的组件(a.vue) eventBus.$emit('事件名', 值)
在要接收值的组件(b.vue) eventBus.$on('事件名', 函数体)
什么时候使用eventBus技术?
当2个没有引用关系的组件之间要通信传值
eventBus技术本质是什么?
空白Vue对象, 只负责$on和$emit
Vue_生命周期
从Vue实例, 创建到销毁的过程
钩子函数
Vue 框架内置函数,随着组件的生命周期阶段,自动执行
作用: 特定的时间点,执行特定的操作
场景: 组件创建完毕后,可以在created 生命周期函数中发起Ajax 请求,从而初始化 data 数据
分类: 4大阶段8个方法
初始化
Vue实例从创建到编译模板执行了哪些钩子函数?
beforeCreate / created
created函数触发能获取data?
能获取data, 不能获取真实DOM
挂载
1. template选项检查
有 - 编译template返回render渲染函数
无 – 编译el选项对应标签作为template(要渲染的模板)
2. 虚拟DOM挂载成真实DOM之前
3. beforeMount – 生命周期钩子函数被执行
4. Create … – 把虚拟DOM和渲染的数据一并挂到真实DOM上
5. 真实DOM挂载完毕
6. mounted – 生命周期钩子函数被执行
------------------------------------------------------------
Vue实例从创建到显示都经历了哪些钩子函数?
beforeCreate / created / beforeMount / mounted
created函数里, 能获取真实DOM吗?
不能获取真实DOM
在什么钩子函数里可以获取真实DOM?
mounted
更新
1. 当data里数据改变, 更新DOM之前
2. beforeUpdate – 生命周期钩子函数被执行
3. Virtual DOM…… – 虚拟DOM重新渲染, 打补丁到真实DOM
4. updated – 生命周期钩子函数被执行
-------------------------------------
什么时候执行updated钩子函数
当数据发生变化并更新页面后
在哪可以获取更新后的DOM
在updated钩子函数里
销毁
1. 当$destroy()被调用 – 比如组件DOM被移除(例v-if)
2. beforeDestroy – 生命周期钩子函数被执行
3. 拆卸数据监视器、子组件和事件侦听器
4. 实例销毁后, 最后触发一个钩子函数
5. destroyed – 生命周期钩子函数被执行
----------------------------------------
一般在beforeDestroy/destroyed里做什么?
手动消除计时器/定时器/全局事件
axios使用 //axios 是一个专门用于发送ajax请求的库 基于原生ajax+Promise技术封装通用于前后端的请求库
axios 底层还是原生js实现, 内部通过Promise封装的
axios全局配置
$refs和$nextTick使用
获取DOM
在mounted生命周期 – 2种方式获取原生DOM标签
目标标签 – 添加id
获取组件对象
1. 创建Demo组件, 写一个方法
2. App.vue使用Demo组件, 给ref属性-名字随意
例:
Vue-异步更新DOM
注意:在vue中修改vue变量,是一种异步的行为,因此,同步的代码立马访问修改后的vue变量,拿到的是旧值,换句话说,vue中更新DOM是异步的
解决办法:可以使用$nextTick()方法,让DOM更新之后,我们再去访问新的值
data改变更新DOM是同步还是异步的?
异步
我们可以在哪里访问到更新后的DOM呢?
this.$nextTick里的函数体
Vue组件进阶
什么是动态组件?
在同一个挂载点, 可以切换显示不同组件
如何使用动态组件?
vue内置的component组件, 配合is属性
如何切换?
改变is属性的值, 为要显示的组件名即可
组件缓存
组件缓存好处?
不会频繁的创建和销毁组件, 页面更快呈现
语法:
Vue内置的keep-alive组件 包起来要频繁切换的组件
组件缓存好处?
不会频繁的创建和销毁组件, 页面更快呈现
组件激活和非激活
方法名:
activated – 激活时触发
deactivated – 失去激活状态触发
组件插槽
1. 组件内用
2. 使用组件时
组件进阶 - 插槽默认内容
不给组件传标签. slot内容原地显示
给组件内传标签, 则slot整体被换掉
组件进阶 – 具名插槽
1. slot使用name属性区分名字
2. template配合v-slot:名字来分发对应标签
v-slot:可以简化成#
作用域插槽
不能直接用另外一个组件里变量
如果想使用插槽时, 使用子组件内变量:
1. 子组件, 在slot上绑定属性和子组件内的值
2. 使用组件, 传入自定义标签, 用template和v-slot="自定义变量名"
3. scope变量名自动绑定slot上所有属性和值scope = {row: defaultObj}
自定义指令_注册
在Vue内置指令满足不了需求时, 可以自己定义使用
全局注册 - 语法
局部注册 – 语法
自定义指令_传值
语法:
在标签上使用 v-color="'red'"
Vue-Router 路由系统
Vue路由简介和基础使用
路由是什么呢? //路由是一种映射关系
Vue中的路由是什么? //路径和组件的映射关系
路由的优点:
整体不刷新页面,用户体验更好
数据传递容易, 开发效率高
路由的缺点:
开发成本高(需要学习专门知识)
首次加载会比较慢一点。不利于seo
什么是单页面应用?
所有的业务都在一个页面编写, 只有一个html
单页面应用好处?
开发效率高, 用户体验好
单页面如何切换场景?
依赖路由切换显示
vue-router模块
官网: https://router.vuejs.org/zh/
步骤:
1. 下载vue-router模块到当前工程
2. 在main.js中引入VueRouter函数
3. 添加到Vue.use()身上 – 注册全局RouterLink和RouterView组件
4. 创建路由规则数组 – 路径和组件名对应关系
5. 用规则生成路由对象
6. 把路由对象注入到new Vue实例中
7. 用router-view作为挂载点, 切换不同的路由页面
注意: 一切都要以url上hash值为准!!
声明式导航
1. vue-router提供了一个全局组件 router-link
2. router-link实质上最终会渲染成a链接 to属性等价于提供 href属性(to无需#)
3. router-link提供了声明式导航高亮的功能(自带类名)
声明式导航 - 跳转传参
在router-link上的to属性传值, 语法格式如下
/path?参数名=值
/path/值 – 需要路由对象提前配置 path: “/path/:参数名”
对应页面组件接收传递过来的值
$route.query.参数名
$route.params.参数名
路由 - 重定向
网页打开url默认hash值是/路径
redirect是设置要重定向到哪个路由路径
路由 - 404 //找不到路径给个提示页面
路由最后, path匹配*(任意路径) – 前面不匹配就命中最后这个 //注意要放在数组最后
路由 - 模式设置 //修改路由在地址栏的显示模式 有#跟无#
hash路由例如: http://localhost:8080/#/home
history路由例如: http://localhost:8080/home (以后上线需要服务器端支持, 否则找的是文件夹)
编程式导航 - 基础使用
语法: path或者name任选一个
编程式导航 -跳转传参
语法: query或者params任选一个
query传, $route.query接
params传, $route.params接
注意:不要用path和params搭配使用,因为使用path的时候会忽略params
路由 - 路由嵌套
1. 创建需要用的所有组件
创建需要的二级页面组件
路由规则里children中配置二级路由规则对象
一级页面中设置router-view显示二级路由页面
2. main.js– 继续配置2级路由
一级路由path从/开始定义
二级路由往后path直接写名字, 无需/开头
嵌套路由在上级路由的children数组里编写路由信息对象
声明式导航 – 类名区别
router-link激活时会有两个类名:
router-link-exact-active (精确匹配) url中hash值路径, 与href属性值完全相同, 设置此类名
router-link-active (模糊匹配) url中hash值, 包含href属性值这个路径
全局前置守卫 //路由跳转之前, 会触发beforeEach函数,这个函数就是路由守卫
语法: router.beforeEach((to, from, next) =>{})
一定要调next(), 才会跳转下一页,不调用就不显示
Vant组件库 //封装了很多的组件的集合
全部引入, 快速开始: https://vant-contrib.gitee.io/vant/#/zh-CN/quickstart
全部引入
1.下载Vant组件库到当前项目中
2.在main.js中全局导入所有组件
3.到某.vue内直接使用Vant组件名
按需引入 //实际开发最常用
手动单独引入, 快速开始: https://vant-contrib.gitee.io/vant/#/zh-CN/quickstart
例:
1.import 从vant库里引出某个组件
2.import 单独引出样式
3.在当前页面注册此组件名即可
自动按需引入
自动按需引入, 快速开始: https://vant-contrib.gitee.io/vant/#/zh-CN/quickstart
webpack依赖babel-plugin-import的插件
把import按需引入方式, 自动转成只引入某个组件方式
数据持久化
cookie 跟 localStorage 的区别
1.cookie 默认设定的时候可选设定过期时间, 如果不设定, 关闭页面就会丢失, localStorage 是永久存在除非被清理
2.cookie 容量比较小, 大概在 4k 左右, localStorage 大概 5m 左右
3.cookie 的原生 api 比较笨, 都会用第三方库来实现
4.如果是新建的项目, 没有特殊要求, 建议 localStorage 是比较合适
cookie使用方式跟localStorage没什么区别