Vue 是一套用于构建用户界面的前端框架。
1.1构建用户界面
前端开发者最主要的工作,就是为网站的使用者(又称为:网站的用户)构建出美观、舒适、好用的网页。
1.1构建用户界面的传统方式
在传统的 Web 前端开发中,是基于jQuery + 模板引擎 的方式来构建用户界面的。
1.1.2使用 vue 构建用户界面
使用 vue 构建用户界面,解决了 jQuery + 模板引擎 的诸多痛点,极大的提高了前端开发的效率和体验。
数据驱动视图(只要页面依赖的数据源变化,则页面自动重新渲染)
1.2框架
vue 的定位是前端框架,提供构建用户界面的整套解决方案(俗称 vue 全家桶):
以及辅助 vue 项目开发的一系列工具:
⚫ vue-cli(npm 全局包:一键生成工程化的 vue 项目-基于 webpack、大而全)
⚫ vite(npm 全局包:一键生成工程化的 vue 项目 - 小而巧)
⚫ vue-devtools(浏览器插件:辅助调试的工具)
⚫ vetur(vscode 插件:提供语法高亮和智能提示)
1.3 vue 的特性
vue 框架的特性,主要体现在如下两方面:
1.3.1 数据驱动视图
在使用vue 的页面中,vue 会监听数据的变化,从而自动重新渲染页面的结构。
好处:当页面数据发生变化时,页面会自动重新渲染!
注意:数据驱动视图是单向的数据绑定。
1.3.2 双向数据绑定
在填写表单时,双向数据绑定可以辅助开发者在不操作 DOM 的前提下,自动把用户填写的内容同步到数据源中。
1.3.3 MVVM
MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。它把每个 HTML 页面都拆分成了如下三个部分:
View 表示当前页面所渲染的 DOM 结构。
Model 表示当前页面渲染时所依赖的数据源。
ViewModel 表示 vue 的实例,它是 MVVM 的核心。
(1)MVVM 的工作原理
ViewModel 作为 MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。
当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构
当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到Model 数据源中
1.4 vue3.x 和 vue2.x 版本的对比
vue2.x 中绝大多数的 API 与特性,在 vue3.x 中同样支持。同时,vue3.x 中还新增了 3.x 所特有的功能、并废弃了某些 2.x 中的旧功能。
新增的功能例如:
组合式 API、多根节点组件、更好的 TypeScript 支持等
废弃的旧功能如下:
过滤器、不再支持 $on,$off 和 $once 实例方法等
详细的变更信息,请参考官方文档给出的迁移指南:
Vue.js - The Progressive JavaScript Framework | Vue.js
基本使用步骤
① 导入 vue.js 的 script 脚本文件
② 在页面中声明一个将要被 vue 所控制的 DOM 区域
③ 创建 vm 实例对象(vue 实例对象)
2.1 基本代码与 MVVM 的对应关系
const vm = new Vue({
//使用el属性,指定vue要控制的区域
el: '#app',
//数据源
data: {
username: 'zs'
}
})
3.1安装 vue-devtools 调试工具
vue 官方提供的 vue-devtools 调试工具,能够方便开发者对 vue 项目进行调试与开发。
Chrome 浏览器在线安装 vue-devtools
vue 2.x 调试工具:
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd
vue 3.x 调试工具:
https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg
注意:vue2 和 vue3 的浏览器调试工具不能交叉使用!
3.2配置 Chrome 浏览器中的 vue-devtools
点击 Chrome 浏览器右上角的 按钮,选择更多工具-> 扩展程序 -> Vue.js devtools 详细信息,并勾选相关选项。
3.3使用 vue-devtools 调试 vue 页面
在浏览器中访问一个使用了 vue 的页面,打开浏览器的开发者工具,切换到 Vue 面板,即可使用 vue-devtools调试当前的页面。
4.1 指令的概念
指令(Directives)是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。
vue 中的指令按照不同的用途可以分为如下 6 大类:
① 内容渲染指令
② 属性绑定指令
③ 事件绑定指令
④ 双向绑定指令
⑤ 条件渲染指令
⑥ 列表渲染指令
4.2常用指令
4.2.1 内容渲染指令
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下 3 个:
4.2.2 属性绑定指令
如果需要为元素的属性动态绑定属性值,则需要用到 v-bind 属性绑定指令。
由于 v-bind 指令在开发中使用频率非常高,因此,vue 官方为其提供了简写形式(简写为英文的 : )。
4.2.3使用 Javascript 表达式
在 vue 提供的模板渲染语法中,除了支持绑定简单的数据值之外,还支持Javascript 表达式的运算.
4.2.4事件绑定指令
vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。语法格式如下:
v-on:事件名称=”事件处理函数得名称”
注意:原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后,分别为:v-on:click、v-on:input、v-on:keyup
通过 v-on 绑定的事件处理函数,需要在 methods 节点中进行声明.
由于 v-on 指令在开发中使用频率非常高,因此,vue 官方为其提供了简写形式(简写为英文的 @ )
1、事件对象 event
(1)在原生的 DOM 事件绑定中,可以在事件处理函数的形参处,接收事件对象event。同理,在 v-on 指令(简写为 @ )所绑定的事件处理函数中,同样可以接收到事件对象 event。
(2)在使用 v-on 指令绑定事件时,可以使用 ( ) 进行传参。
(3)$event 是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。$event 可以解决事件参数对象event被覆盖的问题。
2、事件修饰符
在事件处理函数中调用preventDefault() 或 stopPropagation() 是非常常见的需求。因此,vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。
3、按键修饰符
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符。
4.2.5双向绑定指令
vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据。
注意:v-model 指令只能配合表单元素一起使用!
(1)v-model 指令的修饰符
为了方便对用户输入的内容进行处理,vue 为 v-model 指令提供了 3 个修饰符
.lazy即指在鼠标失去焦点的时候更新
4.2.6条件渲染指令
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
v-if 可以单独使用,或配合 v-else 指令一起使用;v-else-if 指令,顾名思义,充当 v-if 的“else-if 块”,可以连续使用
v-if 和 v-show 的区别
(1)实现原理不同:
(2)性能消耗不同:
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
4.2.7 列表渲染指令
vue 提供了 v-for 指令,用来辅助开发者基于一个数组来循环渲染相似的UI 结构。v-for 指令需要使用 item in items 的特殊语法,其中:
v-for 中的索引
v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为 (item, index) in items
注意:v-for 指令中的 item 和 index 索引都是形参,可以根据需要进行重命名。
4.2.8使用 key 维护列表的状态
当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的DOM 元素,从而提升渲染的性能。但这种默认的性能优化策略,会导致有状态的列表无法被正确更新。
为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能。此时,需要为每项提供一个唯一的 key 属性。
注意:
① key 的值只能是字符串或数字类型
② key 的值必须具有唯一性(即:key 的值不能重复)
③ 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
④ 使用 index 的值当作 key 的值没有任何意义(因为index 的值不具有唯一性)
⑤ 建议使用 v-for 指令时一定要指定 key 的值(既提升性能、又防止列表状态紊乱)
4.3过滤器
过滤器(Filters)常用于文本的格式化。例如:hello -> Hello过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用。
过滤器可以用在两个地方:插值表达式和v-bind 属性绑定。
4.3.1定义过滤器
在创建 vue 实例期间,可以在 filters 节点中定义过滤器,示例代码如下:
const vm = new Vue({
el: '#app',
data: {
message: 'hello vue.js',
info: 'title info',
},
filters: {
capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
}
})
4.3.2私有过滤器和全局过滤器
在 filters 节点下定义的过滤器,称为“私有过滤器”,因为它只能在当前vm 实例所控制的 el 区域内使用。如果希望在多个 vue 实例之间共享过滤器,则可以按照如下的格式定义全局过滤器:
Vue.filter('capitalize', (str) => {
return str.charAt(0).toUpperCase() + str.slice(1)
})
注意:要在创建 Vue 实例之前全局定义过滤器
过滤器可以串联地进行调用,直接使用管道符连续调用。
过滤器的本质是 JavaScript 函数,因此可以接收参数。
4.3.3过滤器的兼容性
过滤器仅在 vue 2.x 和 1.x 中受支持,在 vue 3.x 的版本中剔除了过滤器相关的功能。在企业级项目开发中:
1.1概念和特点
概念:单页面应用程序(英文名:Single Page Application)简称 SPA,顾名思义,指的是一个 Web 网站中只有唯一的一个 HTML 页面,所有的功能与交互都在这唯一的一个页面内完成。
特点:单页面应用程序将所有的功能局限于一个 web 页面中,仅在该 web 页面初始化时加载相应的资源( HTML、JavaScript 和 CSS)。一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转。而是利用 JavaScript 动态地变换HTML 的内容,从而实现页面与用户的交互。
SPA 单页面应用程序最显著的 3 个优点如下:
① 良好的交互体验
⚫ 单页应用的内容的改变不需要重新加载整个页面
⚫ 获取数据也是通过 Ajax 异步获取
⚫ 没有页面之间的跳转,不会出现“白屏现象”
② 良好的前后端工作分离模式
⚫ 后端专注于提供 API 接口,更易实现 API 接口的复用
⚫ 前端专注于页面的渲染,更利于前端工程化的发展
③ 减轻服务器的压力
⚫ 服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍
任何一种技术都有自己的局限性,对于 SPA 来说,主要的缺点有如下两个:
① 首屏加载慢
⚫ 路由懒加载
⚫ 代码压缩
⚫ CDN 加速
⚫ 网络传输压缩
② 不利于 SEO
⚫ SSR 服务器端渲染
1.2创建 vue 的 SPA 项目
vue 官方提供了两种快速创建工程化的 SPA 项目的方式:
① 基于 vite 创建 SPA 项目
② 基于 vue-cli 创建 SPA 项目
2.1创建 vite 的项目
按照顺序执行如下的命令,即可基于 vite 创建 vue 3.x 的工程化项目:
npm init vite-app 项目名称
cd 项目名称
npm install
npm run dev
2.2项目结构梳理
项目结构:
⚫ node_modules 目录用来存放第三方依赖包
⚫ public 是公共的静态资源目录
⚫ src 是项目的源代码目录(程序员写的所有代码都要放在此目录下)
⚫ .gitignore 是 Git 的忽略文件
⚫ index.html 是 SPA 单页面应用程序中唯一的HTML 页面
⚫ package.json 是项目的包管理配置文件
src项目结构:
⚫ assets 目录用来存放项目中所有的静态资源文件(css、fonts等)
⚫ components 目录用来存放项目中所有的自定义组件
⚫ App.vue 是项目的根组件
⚫ index.css 是项目的全局样式表文件
⚫ main.js 是整个项目的打包入口文件
2.3 vite项目的运行流程
在工程化的项目中,vue 要做的:通过 main.js 把 App.vue 渲染到 index.html 的指定区域中。
① App.vue 用来编写待渲染的模板结构
② index.html 中需要预留一个 el 区域
③ main.js 把 App.vue 渲染到了 index.html 所预留的区域中
3.1 组件化开发
组件化开发指的是:根据封装的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护。如:http://www.ibootstrap.cn/ 所展示的效果,就是组件化开发的思想。用户可以通过拖拽组件的方式,快速生成一个页面的布局结构。
3.2 组件化开发的好处
前端组件化开发的好处主要体现在以下两方面:
3. 3vue 中的组件化开发
vue 是一个完全支持组件化开发的框架。vue 中规定组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件。
4.1 vue 组件组成结构
每个 .vue 组件都由 3 部分构成,分别是:
其中,每个组件中必须包含 template 模板结构,而 script 行为和 style 样式是可选的组成部分。
4.2 组件的 template 节点
vue 规定:每个组件对应的模板结构,需要定义到 节点中。
注意: 是 vue 提供的容器标签,只起到包裹性质的作用,它不会被渲染为真正的 DOM 元素。
4.2.1在 template 中使用指令
在组件的 节点中,支持使用前面所学的指令语法,来辅助开发者渲染当前组件的DOM 结构。
4.2.2在 template 中定义根节点
在 vue 2.x 的版本中, 节点内的 DOM 结构仅支持单个根节点,但是,在 vue 3.x 的版本中, 中支持定义多个根节点。
4.3组件的 script 节点
vue 规定:组件内的
import Swiper from './components/01.globalReg/Swiper.vue'
import Test from './components/01.globalReg/Test.vue'、
const app = createApp(App)
app.component('my-swiper', Swiper)
app.component('my-test', Test)
app.mount('#app')
使用 app.component() 方法注册的全局组件,直接以标签的形式进行使用即可。
注意:注册组件一定要写在vue实际控制区域的函数前面
5.1.2局部注册和使用组件
见事例
5.1.3全局注册和局部注册的区别
应用场景:
如果某些组件在开发期间的使用频率很高,推荐进行全局注册;
如果某些组件只在特定的情况下会被用到,推荐进行局部注册。
5.2组件的基本使用
5.2.1组件注册时名称的大小写
在进行组件的注册时,定义组件注册名称的方式有两种:
① 使用 kebab-case 命名法(俗称短横线命名法,例如 my-swiper 和 my-search)
② 使用 PascalCase 命名法(俗称帕斯卡命名法或大驼峰命名法,例如 MySwiper 和 MySearch)
短横线命名法的特点:
帕斯卡命名法的特点:
注意:在实际开发中,推荐使用帕斯卡命名法为组件注册名称,因为它的适用性更强。
5.2.2通过 name 属性注册组件
在注册组件期间,除了可以直接提供组件的注册名称之外,还可以把组件的 name 属性作为注册后组件的名称
5.2.3组件之间的样式冲突问题
默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。导致组件之间样式冲突的根本原因是:
① 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
② 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
解决方法:
为每个组件分配唯一的自定义属性,在编写组件样式时,通过属性选择器来控制样式的作用域。
5.2.4 style 节点的 scoped 属性
为了提高开发效率和开发体验,vue 为 style 节点提供了 scoped 属性,用来自动为每个组件分配唯一的“自定义属性”。并自动为当前的DOM标签和style样式应用这个自定义属性,从而防止组件之间的样式冲突问题。
5.2.5 /deep/ 样式穿透
如果给当前组件的 style 节点添加了 scoped 属性,则当前组件的样式对其子组件是不生效的。如果想让某些样式对子组件生效,可以使用 /deep/ 深度选择器。
注意:/deep/ 是 vue2.x 中实现样式穿透的方案。在 vue3.x 中推荐使用 :deep() 替代 /deep/。
5.3组件的 props
为了提高组件的复用性,在封装 vue 组件时需要遵守如下的原则:
为了方便使用者为组件提供要展示的数据,vue 组件提供了 props 的概念。
组件的 props
props 是组件的自定义属性,组件的使用者可以通过 props 把数据传递到子组件内部,供子组件内部进行使用。
props 的作用:父组件通过 props 向子组件传递要展示的数据。
props 的好处:提高了组件的复用性。
组件中如果使用“camelCase(驼峰命名法)”声明了 props 属性的名称,则有两种方式为其绑定属性的值:驼峰命名法和短横线分隔命名均可
5.4 Class 与 Style 绑定:
在实际开发中经常会遇到动态操作元素样式的需求。因此,vue 允许开发者通过 v-bind 属性绑定指令,为元素动态绑定 class 属性的值和行内的 style 样式。
5.4.1 动态绑定 HTML 的 class
可以通过三元表达式,动态的为元素绑定class 的类名。
如果元素需要动态绑定多个 class 的类名,此时可以使用数组的语法格式,使用数组语法动态绑定class 会导致模板结构臃肿的问题。此时可以使用对象语法进行简化。
5.4.2以对象语法绑定内联的 style
:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名。
1、概念:
在封装组件时对外界传递过来的props 数据进行合法性的校验,从而防止数据不合法的问题。
用数组类型的 props 节点的缺点:无法为每个 prop 指定具体的数据类型。
2、对象类型的 props 节点
使用对象类型的 props 节点,可以对每个 prop 进行数据类型的校验使
3、props 验证
对象类型的 props 节点提供了多种数据验证方案,例如:
可以直接为组件的 prop 属性指定基础的校验类型,从而防止组件的使用者为其绑定错误类型的数据。
如果某个 prop 属性值的类型不唯一,此时可以通过数组的形式,为其指定多个可能的类型
如果组件某个 prop 属性是必填项,必须让组件使用者为其传递属性的值。
在封装组件时,可以为某个 prop 属性指定默认值。
在封装组件时,可以为prop 属性指定自定义的验证函数,从而对 prop 属性的值进行更加精确的控制
计算属性本质上就是一个 function 函数,它可以实时监听 data 中数据的变化,并 return 一个计算后的新值,供组件渲染 DOM 时使用。
计算属性需要以 function 函数的形式声明到组件的 computed 选项中。
注意:计算属性为得到一个计算的结果,因此计算属性中必须有 return 返回值!
3、计算属性的使用注意点
① 计算属性必须定义在 computed 节点中
② 计算属性必须是一个 function 函数
③ 计算属性必须有返回值
④ 计算属性必须当做普通属性使用
4、计算属性 vs 方法
相对于方法来说,计算属性会缓存计算的结果,只有计算属性的依赖项发生变化时,才会重新进行运算。因此计算属性的性能更好
1、概念:
在封装组件时,为了让组件的使用者可以监听到组件内状态的变化,此时需要用到组件的自定义事件。
2、自定义事件的 3 个使用步骤
在封装组件时:
开发者为自定义组件封装的自定义事件,必须事先在 emits 节点中声明。
在 emits 节点下声明的自定义事件,可以通过 this.$emit('自定义事件的名称') 方法进行触发。
在使用组件时:
在使用自定义的组件时,可以通过 v-on 的形式监听自定义事件。
在调用 this.$emit() 方法触发自定义事件时,可以通过第2 个参数为自定义事件传参。
1、为什么需要在组件上使用 v-model
v-model 是双向数据绑定指令,当需要维护组件内外数据的同步时,可以在组件上使用 v-model 指令。
⚫ 外界数据的变化会自动同步到 counter 组件中
⚫ counter 组件中数据的变化,也会自动同步到外界
2、在组件上使用 v-model 的步骤
父组件向子组件:
① 父组件通过 v-bind: 属性绑定的形式,把数据传递给子组件
② 子组件中,通过 props 接收父组件传递过来的数据
子组件向父组件:
① 在 v-bind: 指令之前添加 v-model 指令
② 在子组件中声明 emits 自定义事件,格式为 update:xxx
③ 调用 $emit() 触发自定义事件,更新父组件中的数据
1.1概念及用法
watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。例如,监视用户名的变化并发起请求,判断用户名是否可用。
2、watch 侦听器的基本语法
开发者需要在 watch 节点下,定义自己的侦听器。实例代码如下:
watch: {
username(newVal, oldVal) {
console.log(newVal, oldVal);
}
},
3、使用 watch 检测用户名是否可用
监听 username 值的变化,并使用 axios 发起 Ajax 请求,检测当前输入的用户名是否可用:
watch: {
async username(newVal, oldVal) {
console.log(newVal, oldVal);
const {data: res} = await axios.get("https://www.escook.cn/api/finduser/" + newVal)
console.log(res);
}
},
1.2高级选项
1、immediate 选项
默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项:
username: {
async handler(newVal, oldVal) {
const {data: res} = await axios.get("https://www.escook.cn/api/finduser/" + newVal)
console.log(res);
},
immediate: true,},
当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项:
info: {
async handler(newVal) {
const {data: res} = await axios.get("https://www.escook.cn/api/finduser/" + newVal.username)
console.log(res);
},
deep: true,} },
3、监听对象单个属性的变化
如果只想监听对象中单个属性的变化,则可以按照如下的方式定义 watch 侦听器:
'info.username': {
async handler(newVal) {
const {data: res} = await axios.get("https://www.escook.cn/api/finduser/" + newVal)
console.log(res);
},
deep: true, },
1.3计算属性 vs 侦听器
应用场景不同:
(1)计算属性侧重于监听多个值的变化,最终计算并返回一个新值
(2)侦听器侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值
2.1组件运行的过程
组件的生命周期指的是:组件从创建 -> 运行(渲染) -> 销毁的整个过程,强调的是一个时间段。
2.2组件的监听
vue 框架为组件内置了不同时刻的生命周期函数,生命周期函数会伴随着组件的运行而自动调用。例如:
① 当组件在内存中被创建完毕之后,会自动调用 created 函数
② 当组件被成功的渲染到页面上之后,会自动调用 mounted 函数
③ 当组件被销毁完毕之后,会自动调用 unmounted 函数
2、监听组件的更新
当组件的 data 数据更新之后,vue 会自动重新渲染组件的 DOM 结构,从而保证 View 视图展示的数据和Model 数据源保持一致。
当组件被重新渲染完毕之后,会自动调用updated 生命周期函数。
3、主要周期函数
注意:在实际开发中,created 是最常用的生命周期函数!
4、组件中全部的周期函数
3.1组件间关系
1、组件之间的关系
① 父子关系
② 兄弟关系
③ 后代关系
3.2数据共享
3.2.1父子组件关系之间的数据共享
1、父组件向子组件共享数据
父组件通过 v-bind 属性绑定向子组件共享数据。同时,子组件需要使用 props 接收数据。
2、子组件向父组件共享数据
子组件通过自定义事件的方式向父组件共享数据。
3、父子组件之间数据的双向同步
父组件在使用子组件期间,可以用 v-model 指令维护组件内外数据的双向同步。
3.2.2兄弟组件之间的数据共享
兄弟组件之间实现数据共享的方案是 EventBus。可以借助于第三方的包 mitt 来创建 eventBus 对象,从而实现兄弟组件之间的数据共享。
npm install mitt
import mitt from 'mitt'
const bus = mitt()
export default bus
3.2.3后代关系组件之间的数据共享
后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,可以使用 provide 和 inject 实现后代关系组件之间的数据共享。
注意:
(1)父节点使用 provide 向下共享数据时,可以结合computed 函数向下共享响应式的数据。
(2)如果父级节点共享的是响应式的数据,则子孙节点必须以 .value 的形式进行使用。
3.2.4 vuex
vuex 是终极的组件之间的数据共享方案。在企业级的 vue 项目开发中,vuex 可以让组件之间的数据共享变得高效、清晰、且易于维护。
⚫ 父子关系
① 父 -> 子 属性绑定
② 子 -> 父 事件绑定
③ 父 <-> 子 组件上的 v-model
⚫ 兄弟关系 ④ EventBus
⚫ 后代关系 ⑤ provide & inject
⚫ 全局数据共享 ⑥ vuex
在实际项目开发中,几乎每个组件中都会用到 axios 发起数据请求。此时会遇到如下两个问题:
① 每个组件中都需要导入axios(代码臃肿)
② 每次发请求都需要填写完整的请求路径(不利于后期的维护)
4.1全局配置 axios
在 main.js 入口文件中,通过 app.config.globalProperties 全局挂载 axios,示例代码如下
ref 用来辅助开发者在不依赖jQuery 的情况下,获取 DOM 元素或组件的引用。
每个 vue 的组件实例上,都包含一个$refs 对象,里面存储着对应的DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象。
5.1使用 ref 引用 DOM 元素
如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:
methods: {
getRefs() {
console.log(this.$refs);
this.$refs.myh1.style.color = "red";
}
}
5.2使用 ref 引用组件实例
使用 ref 引用页面上的组件实例,代码示例
1、控制文本框和按钮的按需切换
通过布尔值 inputVisible 来控制组件中的文本框与按钮的按需切换。
2、让文本框自动获得焦点
当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的.focus() 方法即可。
3、this.$nextTick(cb) 方法
组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。通俗的理解是:等组件的DOM 异步地重新渲染完成后,再执行 cb 回调函数。从而能保证cb 回调函数可以操作到最新的 DOM 元素。
动态组件指的是动态切换组件的显示与隐藏。vue 提供了一个内置的
①
② 通过 is 属性动态指定要渲染的组件名称
③
1、使用 keep-alive 保持状态
默认情况下,切换动态组件时无法保持组件的状态。此时可以使用vue 内置的
插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
可以把插槽认为是组件封装期间,为用户预留的内容的占位符。
7.1插槽的基础用法
在封装组件时,可以通过
注意:
7.2具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个
注意:没有指定 name 名称的插槽,会有隐含的名称叫做 “default”。
7.3作用域插槽
在封装组件的过程中,可以为预留的
1、解构作用域插槽的 Prop
作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程。
2、声明作用域插槽
在封装 MyTable 组件的过程中,可以通过作用域插槽把表格每一行的数据传递给组件的使用者。
3、使用作用域插槽
在使用 MyTable 组件时,自定义单元格的渲染方式,并接收作用域插槽对外提供的数据。
vue 官方提供了 v-for、v-model、v-if 等常用的内置指令。除此之外vue 还允许开发者自定义指令。
vue 中的自定义指令分为两类,分别是:
⚫ 私有自定义指令
⚫ 全局自定义指令
8.1私有自定义指令
1、声明私有自定义指令的语法
在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。自定义指令声明时不带-v,使用时需要带-v.
directives: {
focus: {
},
},
},
2、使用自定义指令
在使用自定义指令时,需要加上 v- 前缀。
directives: {
focus: {
mounted(el) {
el.focus()
},
},
},
8.2全局自定义指令
1、声明全局自定义指令的语法
全局共享的自定义指令需要通过“单页面应用程序的实例对象”进行声明,示例代码如下:
app.directive('focus', {
mounted(el) {
el.focus()
}
})
8.3 updated 函数
mounted 函数只在元素第一次插入 DOM 时被调用,当 DOM 更新时 mounted 函数不会被触发。 updated函数会在每次 DOM 更新完成后被调用。
注意:
add.directive('focus', (el) => {
el.focus()
})
路由(英文:router)就是对应关系。路由分为两大类:
① 后端路由
② 前端路由
后端路由指的是:请求方式、请求地址与function 处理函数之间的对应关系。
SPA 指的是一个 web 网站只有唯一的一个 HTML 页面,所有组件的展示与切换都在这唯一的一个页面内完成。此时,不同组件之间的切换需要通过前端路由来实现。
结论:在 SPA 项目中,不同功能之间的切换,要依赖于前端路由来完成!
前端路由:Hash 地址与组件之间的对应关系。
1.2前端路由的工作方式
① 用户点击了页面上的路由链接
② 导致了 URL 地址栏中的 Hash 值发生了变化
③ 前端路由监听了到 Hash 地址的变化
④ 前端路由把当前 Hash 地址对应的组件渲染到浏览器中
结论:前端路由,指的是 Hash 地址与组件之间的对应关系!
1.3实现简易的前端路由
created() {
window.onhashchange = () => {
switch (location.hash) {
case '#/home':
this.comName = 'MyHome'
break;
case '#/about':
this.comName = 'MyAbout'
break;
case '#/movie':
this.comName = 'MyMovie'
break;
}
}
},
vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目中组件的切换。
vue-router 的版本
vue-router 目前有 3.x 的版本和 4.x 的版本。其中:
⚫ vue-router 3.x 只能结合 vue2 进行使用
⚫ vue-router 4.x 只能结合 vue3 进行使用
vue-router 3.x 的官方文档地址:https://router.vuejs.org/zh/
vue-router 4.x 的官方文档地址:Vue Router
2.1 使用方法
vue-router 4.x 的基本使用步骤
(1)在项目中安装 vue-router
npm install vue-router@next -S
(2)定义路由组件
在项目中定义 MyHome.vue、MyMovie.vue、MyAbout.vue三个组件,将来要使用vue-router 来控制它们的展示与切换。
(3)声明路由链接和占位符
可以使用
(4)创建路由模块
在项目中创建 router.js 路由模块,在其中按照如下4 个步骤创建并得到路由的实例对象:
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes: [
{ path: '/home', component: Home },
{ path: '/movie', component: Movie },
{ path: '/about', component: About },
]
})
export default router
app.use(router)
import router from './components/02.start/router'
const app = createApp(App)
app.use(router)
3.1路由重定向
路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。
通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向。
3.2路由高亮
可以通过如下的两种方式,将激活的路由链接进行高亮显示:
① 使用默认的高亮 class 类
② 自定义路由高亮的 class 类
3.2.1默认的高亮 class 类
被激活的路由链接,默认会应用一个叫做 router-link-active 的类名。开发者可以使用此类名选择器,为激活的路由链接设置高亮的样式
3.2.2自定义路由高亮的 class 类
在创建路由的实例对象时,开发者可以基于 linkActiveClass 属性,自定义路由链接被激活时所应用的类名:
linkActiveClass: 'active-router',
3.3嵌套路由
通过路由实现组件的嵌套展示,叫做嵌套路由。
在 About.vue 组件中,声明 tab1 和 tab2 的子路由链接以及子路由占位符:
在 router.js 路由模块中,导入需要的组件,并使用children 属性声明子路由规则:{
path: '/about',
component: About,
children: [
{ path: 'tab1', component: Tabl },
{ path: 'tab2', component: Tab2 },
]
},
3.4动态路由的概念
动态路由指的是:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。
(1)在 vue-router 中使用英文的冒号(:)来定义路由的参数项。
(2)通过动态路由匹配的方式渲染出来的组件中,可以使用 $route.params 对象访问到动态匹配的参数值。
(3)为了简化路由参数的获取形式,vue-router 允许在路由规则中开启props 传参。
3.5编程式导航
通过调用 API 实现导航的方式,叫做编程式导航。与之对应的,通过点击链接实现导航的方式,叫做声明式导航。例如:
3.5.1vue-router 中的编程式导航 API
vue-router 提供了许多编程式导航的 API,其中最常用的两个 API 分别是:
① this.$router.push('hash 地址')
② this.$router.go(数值 n)
3.6命名路由
通过 name 属性为路由规则定义名称的方式,叫做命名路由。
注意:命名路由的 name 值不能重复,必须保证唯一性!
3.6.1使用命名路由实现声明式导航
为
3.6.2使用命名路由实现编程式导航
调用 push 函数期间指定一个配置对象,name是要跳转到的路由规则、params 是携带的路由参数
3.7导航守卫
导航守卫可以控制路由的访问权限。示意图如下:
1、声明全局导航守卫
全局导航守卫会拦截每个路由规则,从而对每个路由进行访问权限的控制。可以按照如下的方式定义全局导航守卫:
router.beforeEach(() => {
console.log('ok');
})
2、守卫方法的 3 个形参
全局导航守卫的守卫方法中接收 3 个形参,格式为:
router.beforeEach((to, from, next) => {
//to 目标路由对象
//from当前导航正要离开的对象
//next是一个函数,表示放行
})
注意:
① 在守卫方法中如果不声明 next 形参,则默认允许用户访问每一个路由!
② 在守卫方法中如果声明了 next 形参,则必须调用 next() 函数,否则不允许用户访问任何一个路由!
Next函数:
直接放行:next()
强制其停留在当前页面:next(false)
强制其跳转到登录页面:next('/login')
3、结合 token 控制后台主页的访问权限
const token = localStorage.getItem(‘token’)
If(to.path === ‘/main’ && !token) {
Next(‘/login’)
} else {
next()
}
1、概念
vue-cli(俗称:vue 脚手架)是 vue 官方提供的、快速生成 vue 工程化项目的工具。特点:
① 开箱即用
② 基于 webpack
③ 功能丰富且易于扩展
④ 支持创建 vue2 和 vue3 的项目
2、安装
vue-cli 是基于 Node.js 开发出来的工具,因此需要使用 npm 将它安装为全局可用的工具 npm install -g @vue/cli
3、创建项目
(1)vue create 项目名称
(2)vue ui
vue ui 的本质:通过可视化的面板采集到用户的配置信息后,在后台基于命令行的方式自动初始化项目
1. 什么是 vue 组件库
在实际开发中,前端开发者可以把自己封装的 .vue 组件整理、打包、并发布为 npm 的包,从而供其他人下载和使用。这种可以直接下载并在项目中使用的现成组件,就叫做 vue 组件库。
2. vue 组件库和 bootstrap 的区别
⚫ bootstrap 只提供了纯粹的原材料( css 样式、HTML 结构以及 JS 特效),需要由开发者做进一步的组装和改造
⚫ vue 组件库是遵循 vue 语法、高度定制的现成组件,开箱即用
3. 最常用的 vue 组件库
① PC 端
⚫ Element UI(https://element.eleme.cn/#/zh-CN)
⚫ View UI(http://v1.iviewui.com/)
② 移动端
⚫ Mint UI(http://mint-ui.github.io/#!/zh-cn)
⚫ Vant(https://vant-contrib.gitee.io/vant/#/zh-CN/)
4. Element UI
Element UI 是饿了么前端团队开源的一套 PC 端 vue 组件库。支持在 vue2 和 vue3 的项目中使用:
⚫ vue2 的项目使用旧版的 Element UI(https://element.eleme.cn/#/zh-CN)
⚫ vue3 的项目使用新版的 Element Plus(https://element-plus.gitee.io/#/zh-CN)