Vue3中的核心知识:ref与reactive响应式、CompositionAPI、customRef
vue3.0最大的核心就是Composition API
view文件一般存放需要路由跳变的组件,component一般存放普通组件
utils文件夹存放自己封装的工具类函数
Vue
是一套构建用户界面(往页面里填数据)的框架(现成的解决方案)
特性:
数据驱动视图
ViewModel就是vue的实例
1. 内容渲染指令
v-text
指令的缺点:会覆盖元素内部原有的内容!
{{ }}
插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!
v-html
指令的作用:可以把带标签的字符串,渲染成真正的 HTML 内容!
v-pre 用于跳过元素和它的子元素的编译过程,显示原始的Mustache标签: 跳过不需要编译的节点,加快编译的速度;
v-once 用于指定元素或者组件只渲染一次
v-cloak 避免未编译到显示{{message}}后再解析成数据,编译结束后指令消失
2. 属性绑定指令:动态绑定属性、绑定一个对象
注意:插值表达式 {{ }} 只能用在元素的内容节点中,不能用在元素的属性节点中!
使用 v-bind:
指令,为元素的属性动态绑定值;(单向绑定:仅数据渲染视图)
语法糖 —— 冒号:
在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:
这是一个 div
data中的属性最好不要在data中的其他对象引用
CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 ’kebab-case‘来命名
3. 事件绑定
v-on:
简写是 @
语法格式为:
//也可以传参add(n) methods: { //没有传参时,这里的e是鼠标事件 传参时被覆盖,引出$event add(e) { //add:function()简写 // 如果在方法中要修改 data 中的数据,可以通过 this 访问到 //vm.count用this代替 //vm === this为true this.count += 1; //e.target是触发事件的事件源 这里e为点击事件MouseEvent e.target.style.backgroundColor = 'red } }
$event(vue的内置变量)
的应用场景:如果默认的事件对象 e 被覆盖(需要传参时使用e)了,则可以手动传递一个 $event。例如:
methods: { add(n, e) { // 如果在方法中要修改 data 中的数据,可以通过 this 访问到 this.count += 1 } }
事件修饰符:
.prevent
防止默认行为:链接跳转
原生:show(e){
e.preventDefault();
}
.stop
阻止冒泡 点击子对象时 冒泡到父对象,为了阻止父对象响应
原生:event.stopPropagation();
不常用:
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyAlias} - 仅当事件是从特定键触发时才触发回调。
.once - 只触发一次回调。
.left - 只当点击鼠标左键时触发。
.right - 只当点击鼠标右键时触发。
.middle - 只当点击鼠标中键时触发。
.passive - { passive: true } 模式添加侦听器
3. 按键修饰符
@submit.stop.prevent
@keyup = ' ' 每次按下键盘都响应
@keyup.enter/13 键盘回车
@keyup.esc = ' '
4.双向绑定 v-model 指令
只能用于表单元素,div不行:
input 输入框
- type="radio"
- type="checkbox"
- type="xxxx"
2. textarea
3. select
v-model的修饰符
5. 条件渲染指令:主要用于显示和隐藏
v-show
的原理是:动态为元素添加或移除 display: none
样式,来实现元素的显示和隐藏
(不支持template,不能和v-else一起用)
v-if(
常与template一起用,与v-else使用) 的原理是:每次动态创建或移除元素,实现元素的显示和隐藏
在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!
vue是先把整个页面编译成js再渲染Dom结构
v-if 指令在使用的时候,有两种方式:
直接给定一个布尔值 true 或 false
被 v-if 控制的元素
给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏
良好
还可以和v-else一起使用(极少数用到v-else-if)
6. 列表渲染指令 v-for,可以结合template使用
④input的check框和索引是相关联的,添加数组会造成选中框的混乱,而id是唯一的
定义全局过滤器(常用):
Vue.filter(’名‘,function(过滤器前面的值){
return 结果
}
调用:{{ message | fliter名}}
要定义到 filters 节点下,本质是一个函数
在过滤器函数中,一定要有 return 值
在过滤器的形参中,可以获取到“管道符”前面待处理的那个值
如果全局过滤器和私有过滤器名字一致,此时按照“就近原则”,调用的是”私有过滤器“
直接定义filters ,称为“私有过滤器”,它只能在当前 vm 实例的 el 区域内使用。
全局过滤器实现获取时间并格式化
其他:
传参,第一个被占用
监视数据的变化,做特定的操作。
侦听data中数据的变化,且进行一些逻辑处理,比如网络请求
一般不侦听计算属性
newvalue和oldvalue打印出一个proxy
应用场景:
注册用户判断是否被占用 newVal为空时会报错,所以加一个if
方法二:
1、方法格式的侦听器
参数新值在前,旧值在后
缺点1:无法在刚进入页面的时候,自动触发!!!只有在数据变化时触发
解决:immediate
缺点2:如果侦听的是一个对象,如果对象中的属性发生了变化,不会触发侦听器!!!
解决:deep,但是改为newvalue无法获取对象oldvalue的值,因为引用类型获取的是地址(解决:深拷贝一份放入data)
2、对象格式的侦听器(常用)
好处1:可以通过 immediate 选项,让侦听器在页面初次渲染好自动触发!!!
好处2:可以通过 deep 选项,让侦听器深度监听对象中每个属性的变化!!!
如果 watch 侦听的是一个对象,对象中的属性值发生变化,此时使用deep
handle是固定函数
方法二:vue3文档删掉了
实现立即触发 :对象格式 + immediate
在watch中 a:“someMethod”,someMethod是写在methods的方法,相当于把watch写在methods
不常用的另一种写法:数组帮助多个函数逐个调用
另一种API:$watch
1、第一个参数是要侦听的源;
2、第二个参数是侦听的回调函数callback;
3、第三个参数是额外的其他选项,比如deep、immediate;
这里的箭头函数内部的this没有问题,因为箭头函数是去上层作用域找this,找到的是created函数,函数在js中是有自己的作用域的,所以内部的this相当于调用的this,不会出现问题
如果在created中给侦听器赋值,可以调用,有取消的作用
计算属性指的是通过一系列运算之后,最终得到一个属性值。
这个动态计算出来的属性值可以被模板结构或 methods 方法使用。
特点:
computed是一个属性,声明的时候必须是方法,但是在vue中被当作属性
多次使用只调用一次 ,计算属性使用会缓存(缓存体现在多次调用只console.log一次)
属性的getter方法,相当于:
rgb:{
get: function() {
return ...
},
set: function(value) {
console.log(value)
}
}
其实也可以有set方法,当methods中 this.rgb = xxx 赋值,浏览器也会打印
获取属性的方法统称为getter方法,设置属性的方法统称为setter方法
函数只有getter,对象有setter
好处
实现了代码的复用
只要计算属性中依赖的数据源变化,就会自动重新求值
axios固定返回六个属性
解构赋值
await axios是一个对象,包含六个属性,把引用赋值给result
result = { },result只想拿到其中的data属性,利用解构赋值
{ data } = await axios
解构出data:
返回的{data}
获取解构赋值data的data
重命名解构赋值为res
介绍 | Vue CLI
查询版本 vue -V
原型开发: 下载一个额外配置,就可以在命令中创建简单的vue-cli
单页面应用程序SPA:一个Web网站中只有一个html页面
是vue.js开发的标准工具,简化了webpack创建工程化配置的过程,快速生成一个项目
只选择这三项
然后create创建
按照上面提示敲完,不用把项目名称敲全,可以tab键补全
实时监听代码变化(webpack-dev-serve)
如果不小心关闭中断,去vscode中断运行npm run serve 实际上是运行后面的具体
类似于html-webpack-plguin,会自动把生成打包好的bundle.js注入
vue 项目中 src 目录的构成:
assets 文件夹:存放项目中用到的静态资源文件,例如:css 样式表、图片资源 components 文件夹:程序员封装的、可复用的组件,都要放到 components 目录下 main.js 是项目的入口文件(entry)。整个项目的运行,要先执行 main.js App.vue 是项目的根组件,定义UI结构的
index.html中id为app的标签会被App.vue覆盖(此文件不得改动)
① App.vue 用来编写待渲染的模板结构
② index.html 中需要预留一个 el 区域
③ main.js 把 App.vue 渲染到了 index.html 所预留的区域中
这里的$mount和el的作用是一样的
根组件:Test
- 安装插件:快速创建模板 Vuter 、Vue 3 Snippets、Auto Close Tag补全标签
组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件
1、每新建一个vue组件默认在script写上export default { }
2、data不能像之前一样指向对象,必须是一个函数
3、 this表示组件实例对象
4、里只能有一个根节点,只能有一个div
组件在被封装,是相互独立的,不存在父子关系
使用组件的时候,才形成了父子关系、兄弟关系
Left是 ‘Left’:Left的简写
① 为什么 F 不能用在组件 C 中? C组件没有使用components注册F
② 怎样才能在组件 C 中使用 F ? 在组件C中也用components注册F
组件名称大写
三种方法:
①
事件函数只有一行的话,可以简写 @click=“count += 1”
②全局Vue组件定义的三种方式_sherlockkid7的博客-CSDN博客
根div 取class = "组件名 - container"
子 class = "子组件名 - box"
作用:子组件在封装给父组件时初始化(需求)不同,此时需要props提高组件的可复用性
格式:数组 / 对象
对象类型的其他写法
如果type是Object,default一定要是函数,要返回一个值,因为多个组件可能调用的是同一个引用类型的地址,修改其中一个时会影响到其他组件
props的数据可以直接在模板结构中当作普通属性使用,可以被this获取到
左:封装者 右:使用者
全局组件在自定义属性后,从使用者获取被赋予的数据
命名时使用驼峰,赋值时官方建议使用 -
在设置初始值时需要数字型怎么办?
加v-bind,v-bind 中写的是js,js中的9是数字
:init=“ 9 ” 这里的9是数字
init = “9” 这里的9是字符串
如果要传父组件的data里的值,需要加v-bind,赋值的是数据的引用
一般都使用v-bind绑定,且当命名格式为驼峰,使用时应该写成 - 短横连接
以下是错误写法
使用者可能没有使用,需要给自定义属性一个默认值
- 定义多个类型
- 与类型不匹配时报错
- 为object类型时需要返回函数
使用者必须传值,否则报错
自定义title属性,使用者给什么标题就改什么,组件复用的只是UI结构
写在 .vue 组件中的样式会全局生效,造成多个组件之间的样式冲突问题
根本原因:
① 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
② 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
解决办法:
1、通过属性选择器来控制样式的作用域
2、简便方法:为 style 添加 scoped 属性(原理:自动添加data属性绑定)
3、/deep/ 样式穿透: 用于导入第三方组件需要覆盖子组件样式时
使用>>>也可以,这些都是css的深度作用选择器。
可以使用这种选择器修改element ui等框架难以修改的样式
生命周期函数的分类
整个项目的运行是从main.js开始的,子组件连成一个vue树,打包完生成这个文件
但在此阶段组件的模板结构尚未生成,无法操作Dom
result返回值:
默认显示为0
创建模板结构
- 生成的模板结构只处于内存中,未被渲染,此时仍无法获取dom结构
mounted 才能操作dom
总结:
beforeUpdate
由图可知,当数据变化时触发beforeUpdate。
但是当初打开页面时也能触发,是因为初次获取数据也发生改变
此时还未重新渲染到结构
(左父 右子)
message是普通数据类型,传的是字符串的值,和msg是不相关的
userinfo对象是引用数据类型,这里传的是引用,和user是同一个指向
如果这样赋值一个对象,user会指向新的地址,应该修改user.data这样来修改
props的值都不建议修改!!
理解click事件
created生命周期函数,此时methods、data等被创建
EventBus 的使用步骤
① 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
② 在数据发送方,调用 bus.$emit('事件名称', 要发送的数据) 方法触发自定义事件
③ 在数据接收方,调用 bus.$on('事件名称', 事件处理函数) 方法注册一个自定义事件
使用:
给元素加上属性 ref = ’ 自定义名 ‘,名字不能重复,后面的会覆盖前面的
然后通过this.$refs.自定义名获取Dom元素
案例:
一个input框和button按钮,点击按钮时按钮隐藏,输入框显示,失焦时输入框隐藏,按钮显示。
@blur是失焦
会把 cb 回调(操作)推迟到下一个 DOM 更新周期(生命周期中mount的那个圈)之后执行。
通俗的理解是:等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。
Vue 在更新 DOM 时是异步执行的。也就是说数据变化后,DOM不会马上更新
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
this.$nextTick()可以用作局部的数据更新后DOM更新结束后的操作全局的可以用updated生命周期函数
使用场景:
由于v-if会销毁整个元素,当数据更新为true时,视图还未完全更新,此时将获焦行为延后执行。
为什么不可以在生命周期updated中用?
因为update在每次更新数据时都会触发,在input销毁时再次更新数据,会出现无法获取焦点报错
通过is把组件放到component的位置 data中name:自定义组件名
使用场景:小程序栏
为了解决动态切换时销毁旧组件 :用
当组件被缓存时,自动触发 deactivated 生命周期函数
当组件被激活时,自动触发 activated 生命周期函数
组件第一次被创建时, 既执行 created 生命周期,也会执行 deactivated 生命周期
include 指定名称匹配的组件会被缓存
exclude排除
但不能同时使用
多个组件名之间使用英文的逗号分隔
如果组件提供name属性,就按照name名称
name与component注册组件的名称不相干(注册的名称只用于标签)
插槽(Slot)是 vue 为组件的封装者提供的能力。
允许开发者在封装组件时,把不确定的、用户可以自定义的部分定义为插槽
理解为游戏机卡槽
可以把插槽认为是组件封装期间,为用户预留的内容的占位符
官方规定,slot必须要有一个name属性定义名称
当唯一时,不写name默认为default
如果要把内容填充到指定名称的插槽中,需要使用v-slot
v-slot不能直接用在元素上,只能放在或者component,所以可以在组件中添加(不会被渲染成任何实质性的html元素)包裹
后备内容
当slot未被用户指定内容时,使slot中有默认内容,直接在
具名插槽(多个插槽时命名)
作用域插槽:为预留的 插槽绑定 props 数据
通过scope接收对象
通过解构赋值(需要什么解构什么)
$event是指当前触发的是什么事件(鼠标事件,键盘事件等)
$event.target则指的是事件触发的目标,即哪一个元素触发了事件,这将直接获取该dom元素
1 - 私有自定义指令(仅当前组件可使用,子组件也不可使用)
定义:
使用:
私有自定义组件
也可以直接给v-color赋值:
’red‘ ”> 私有自定义组件
注意要给red添加单引号,否则是从data中寻找red
为私有自定义指令动态绑定参数 v-color=“color”
bind :只在第一次绑定时调用
update函数: 在数据更新时调用
由于 bind 函数只调用 1 次,当指令第一次绑定到元素时调用,DOM更新时bind函数不再触发
我们使用 update 函数,它在每次 DOM 更新时被调用。
函数简写:当bind和update的逻辑完全相同时,color的对象格式可简写成函数格式
2 - 全局自定义指令(常用)
通过“Vue.directive()”进行声明
提供代码规范并检验
安装:
ESLint不允许多个换行、空格
语法规则:
可单独禁用某个文件,从报错里找到配置信息
可以在配置文件全局修改参数
在 setting.json中添加
以prettier开头的都是它的配置
配置prettier,文件放入电脑路径
黑马程序员Vue2.0+Vue3.0入门到精通,大厂前端岗位必备技能_哔哩哔哩_bilibili
eslint更像语法检测但不会修改你的行为,prettier则会修改行为
在每个组件里如果使用axios都要先在main.js中引入
然后在组件中import axios from 'axios'
优化1:导入优化
组件相当于一个vue实例
在main.js中添加axios原型可直接用this调用
由于vue内置的成员都用$开头,所以可以命名为$http
然后就可以在组件中直接通过this.$http调用
优化2:get和post请求的路径的复用,方便维护
在jQuery中是使用 $.ajaxPrefilter()
vue中在main.js配置 使用 axios.defaults.baseURL = ’路径‘
组件中就可以不用写根路径了
缺点:此方法不利于API接口的复用
在前端中,指的是哈希地址(#锚链接)与组件之间的对应关系
不同组件之间的切换需要通过前端路由来实现
SPA单页面应用程序(类似于小程序切换):所有功能的切换基于一个页面完成
#锚链接,不会刷新页面,但是会导致历史记录的变化,页面的上下跳转
location.href:完整URL地址
location.hash: #b4 (哈希地址)
1、用户点击了页面上的路由链接(a链接)导致URL地址栏中hash值变化
2、前端路由监听hash地址变化
3、前端路由把hash地址对应的组件渲染到页面上
实现简易的前端路由 (仅了解)
#/ 斜线代表路径 方便
window.onhashchange监听hash地址的变化x
console.log(location.hash) // #/home
vue.js 官方给出的路由解决方案,能够轻松的管理 SPA 项目 中组件的切换。
vue-router 的官方文档地址:https://router.vuejs.org/zh/
vue-router 安装和配置的步骤
① 安装 vue-router 包
② 创建路由模块(安装时可勾选路由,就不用自己配置了)
在 src 源代码目录下,新建 router/index.js 路由模块,并初始化如下的代码:
vue.use()装插件用
写出router的对应关系
③ 导入并挂载路由模块
这里@/couter可以不用写全@/couter/index.js
因为模块化导入如果是文件夹,默认导入文件夹下的index.js,找不到时报错
④ 声明路由链接
和占位符 只要项目中安装和配置了vue-router就可以在 src/App.vue 组件中使用:
1、占位符(展示出口):
用于存放匹配hash地址变化匹配的组件
2、声明路由链接
用于替换a标签,省略了a标签中herf使用引入的#号,因为会自动加
在访问地址 A 的时候,强制用户跳转到地址 C 展示特定的组件页面
通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向
子组件路由的嵌套实现:
1、声明子路由链接和子路由占位符
在 About.vue 组件中,声明 tab1 和 tab2 的子路由链接以及子路由占位符
2、通过 children 属性声明子路由规则
在 src/router/index.js 路由模块中,导入需要的组件,使用 children 属性声明子路由规则:
注意子path不用加斜线/
凡涉及规则,必须有path和component
3、可重定向
4、默认子路由(扩展)
当子路由中path为空字符串,则这条路由规则被称为默认子路由
就无需重定向了
- 缺点:复用性差 解决方案:
动态路由指的是:将可可变的部分定义为参数项,提高路由规则的复用性,使用(:)定义
这里的(:id)是动态参数项
那么如何通过id动态匹配?
方式一:this.$route.params
在点击不同链接时,可以通过this.$route.params访问到path定义的动态参数(this可省略)
黑马程序员Vue2.0+Vue3.0入门到精通,大厂前端岗位必备技能_哔哩哔哩_bilibili
$route:路由的参数对象
$router:路由的导航对象
方式二:props
使用 props 接收路由参数
为了简化路由参数的获取形式,vue-router 允许在路由规则中开启 props 传参
接收props参数:
注意之间的关系:在规则里要展示哪个组件,就在哪个组件里接收
其中App.vue中的...movie/1...的 /1 是路径参数
拓展query和fullPath
查询参数:hash地址中,路径参数后的(?name=zs&age=20)
在参数对象中需要使用this.$route.query访问查询参数
this.$route.params访问路径参数
path只是部分参数,fullPath是完整路径
- 声明式导航:浏览器中,通过点击链接实现导航的方式
普通网页中点击链接,vue中点击
- 编程式导航:浏览器中,调用API实现导航的方式
普通网页中点击 location.href 跳转到新页面
vue-router 中的编程式导航 API
导航对象$router
this.$router.push(‘hash地址’)跳转并增加一条历史记录
this.$router.replace(‘hash地址’)跳转,替换记录
this.$router.go(数值n) -1 往上一个跳转,2往浏览过的下下个跳转
但一般只前进或后退,引入两个方法
$router.back()
$router.forward()
注意:写在行内不能加this,会报错,写在methods方法里需要加this
使用场景:需要登陆的页面和未登录的页面
全局前置守卫
在每次页面跳转时都会触发全局前置守卫,在全局前置守卫中,可以控制每个路由的访问权限
// 创建路由实例对象
const router = new VueRouter({ })
//调用beforeEach 即声明全局前置守卫
//每次发生路由导航跳转时,都会触发fn“回调函数”
router.beforeEach(function(to,from,next){
console.log(to,from );
//next()表示放行
next();
})
next的三种情况:
next()放行,next('/login')登陆页面,next(false)不跳转
控制后台主页的访问权限
1、判断是否访问后台主页
2、判断是否登陆过
router.beforeEach (function (to, from, next) {
if (to.path === '/main'){
const token = localStorage.getItem ('token');
//如果登陆过,会有一个token
if (token){
next(); }
else{
next('login'); }
}
else{
next(); } //访问的不是后台主页,直接放行
})
黑马程序员Vue2.0+Vue3.0入门到精通,大厂前端岗位必备技能_哔哩哔哩_bilibili
案例:封装articleAPI
List 组件通过 loading
和 finished
两个变量控制加载状态,当组件滚动到底部时,会触发 load
事件并将 loading
设置成 true
。此时可以发起异步操作并更新数据,数据更新完毕后,将 loading
设置成 false
即可。若数据已全部加载完毕,则直接将 finished
设置成 true
即可。
Vant - Mobile UI Components built on Vue
黑马程序员Vue2.0+Vue3.0入门到精通,大厂前端岗位必备技能_哔哩哔哩_bilibili
定制主题:修改引入的less文件,less变量的覆盖
按照文档配置vue.config.js(只有vue-cli才有这个文件)
vue.config.js:对整个项目的打包和配置
less:可编程样式 (声明用@)
Less 快速入门 | Less.js 中文文档 - Less 中文网
修改定制主题的两种方法:
1、根据文档在根目录下创建vue.config.js配置文件,直接覆盖
缺点:每次修改都要重新run,麻烦
2、在src新建less文件,导入到vue.config.js文件中
因为webpack在打包时,底层用到了node.js,所以在vue.config.js配置文件中,可以导入并使用node.js的核心模块(path),node用到common.js
const path = require(‘path’) //得到path模块
const theme = path.join(__dirname, './src/theme.less')
// path.join拼接 __dirname表示此文件的目录
然后在配置文件中使用模板字符串以及${}拼接
hack: `true; @import "${themePath}";`
在less文件中按照文档配置
@blue: orange;
@nav-bar-background-color: @blue;
@nav-bar-title-text-color: white;
项目的打包生成:
npm run build生成dist文件
dist文件只能通过http协议打开,现在使用的时file协议
查看cli文档配置如下:
publicPath: ' ', // 空字符串或者'./'才可以在任意协议显示,不能为'/'
这样才能打开dist文件查看
文档中devSever可以修改8080端口号等
页面离开时缓存
路由配置中原信息保存,记录top值
滚动核心
滚动的事件监听
防抖以及记录滚动数据
鲁大师:提供了许多类似节流防抖、操作数组、对象的一系列函数(浅拷贝、深拷贝)