目录
1.Vue 是什么
概念:Vue 是一个用于 构建用户界面①的 渐进式②框架3
Vue 的两种使用方式:
- ① Vue 核心包开发场景:局部 模块改造
- ② Vue 核心包 & Vue 插件 工程化开发场景:整站 开发
插值表达式 {{ }}:
插值表达式是一种 Vue 的模板语法
1.作用:利用表达式进行插值,染到页面中表达式:是可以被求值的代码,JS引擎会将其计算出一个结果
极简插件:
2.Vue 指令
1.什么是 Vue 指令呢?
指令就是带有 v- 前缀 的特殊 属性,不同属性 对应 不同的功能学习不同指令 →解决不同业务场景需求Vue指令 v-html:
如果需要动态解析标签,可以用哪个指令?语法?
v-html="表达式"→动态设置元素 innerHTMLVue指令 v-show v-if:
v-show
- 1.作用: 控制元素显示隐藏
- 2.语法: v-show="表达式"表达式值 true 显示, false 隐藏
- 3.原理:切换 display:none 控制显示隐藏
- 4.场景:频繁切换显示/隐藏的场景
V-if
- 1.作用: 控制元素显示隐藏(条件渲染)
- 2.语法: v-if="表达式"表达式值 true 显示, false 隐藏
- .原理:基于条件判断,是否 创建 或 移除 元素节点
- 4.场景:要么显示,要么隐藏,不频繁切换的场景
Vue指令 v-else v-else-if:
- 1.作用:辅助 v-if 进行判断渲染
- 2.语法: v-elsev-else-if="表达式
- 3.注意: 需要紧挨着 v-if 一起使用
Vue指令 v-on :
简写:
注意:methods函数内的 this 指向 Vue 实例
Vue 指令 v-on 调用传参:
Vue 指令 v-bind
- 1.作用:动态的设置html的标签属性→>src url title
- 2.语法: v-bind:属性名="表达式
- 省略:v-bind => :
v-bind 对于样式控制的增强 - 操作class:
Vue 指令 v-for:
1.作用: 基于数据循环,多次渲染整个元素→ 数组、对象、数字..
省略: index: v-for="item in 数组"
v-for 中的 key:
语法:key属性="唯一标识"
作用:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用
注意点:
- 1.key 的值只能是 字符串 或 数字类型
- 2.key 的值必须具有 唯一性
- 3.推荐使用 id 作为 key(唯一),不推荐使用 index作为 key(会变化,不对应)
v-for 中的 key-不加 key
v-for 的默认行为会尝试 原地修改元素(就地复用)Vue 指令 v-model:
v-model 应用于其他表单元素:
常见的表单元素都可以用 v-model绑定关联 → 快速 获取 或 设置 表单元素的值它会根据 控件类型 自动选取 正确的方法 来更新元素
- 输入框 input:text -> value
- 文本域 textarea -> value
- 复选框 input:checkbox -> checked
- 单选框 input:radio -> checked
- 下拉菜单 select -> value
Vue 指令的修饰符:
通过""指明一些指令 后缀,不同 后缀 封装了不同的处理操作 → 简化代码
- ① 按键修饰符
@keyup.enter -> 键盘回车监听
- ②v-model修饰符
v-model.trim -> 去除首尾空格
v-model.number -> 转数字
- ③ 事件修饰符
阻止冒泡 -> @事件名.stop
阻止默认行为 -> @事件名.prevent
计算属性:computed
computed 计算属性 vs methods 方法:
computed 计算属性:
作用:封装了一段对于数据的处理,求得一个结果。语法:
- ① 写在 computed 配置项中
- ② 作为属性,直接使用 →this.计算属性 {{计算属性 }}
methods 方法:
作用:给实例提供一个方法,调用以处理业务逻辑。
语法:
- ① 写在 methods 配置项中
- ② 作为方法,需要调用 → this.方法名(){{方法名()}} @事件名="方法名
缓存特性(提升性能):
计算属性会对计算出来的结果缓存,再次使用直接读取缓依赖项变化了,会自动重新计算 →并再次缓存计算属性完整写法:
watch 侦听器(监视器):
- 简单写法 →简单类型数据,直接监视
2.完整写法 →添加额外配置项
3.生命周期
Vue 生命周期 和 生命周期的四个阶段思考:什么时候可以发送初始化渲染请求?(越早越好)什么时候可以开始操作dom??(至少dom得渲染出来)Vue生命周期:-个Vue实例从 创建到 销毁 的整个过程。生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁
Vue 生命周期函数(钩子函数):
Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】→ 让开发者可以在【特定阶段】运行自己的代码
4.工程化开发 &脚手架 Vue CLI & 组件
在文件中shift+右键 ->
创建 -> 导入 -> 注册 -> 使用
组件的样式冲突 scoped:
默认情况:写在组件中的样式会 全局生效→ 因此很容易造成多个组件之间的样式冲突问题,
- 全局样式:默认组件中的样式会作用到全局
- 局部样式:可以给组件加上 scoped 属性,可以让样式只作用于当前组件
data是一个函数:
组件通信:
prop:
5.V-model 原理
.sync 修饰符:
6.自定义指令
自定义指令:自己定义的指令,可以封装一些 dom 操作,扩展额外功能
自定义指令 v-loading指令封装:
7.插槽
8.单页应用程序:
SPA-Single Page Application
9.路由
在vue应用中使用路由功能,需要安装Vue-Router:
注:创建完带有路由功能的前端项目后,在工程中会生成一个路由文件,如下所示:
关于路由的配置,主要就是在这个路由文件中完成的。
为了能够使用路由功能,在前端项目的入口文件main.js中,创建Vue实例时需要指定路由对象:
2.2 路由配置
首先了解一下路由组成:
VueRouter:路由器,根据路由请求在路由视图中动态渲染对应的视图组件
<router-link>:路由链接组件,浏览器会解析成<a>
<router-view>:路由视图组件,用来展示与路由路径匹配的视图组件
具体配置方式:
在路由文件中router index.js 配置路由路径和视图的对应关系:
import Vue from 'vue' import VueRouter from 'vue-router' import HomeView from '../views/HomeView.vue' Vue.use(VueRouter) //维护路由表,某个路由路径对应哪个视图组件 const routes = [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue') } , { path: '/404', component: () => import('../views/404View.vue') }, { path: '*', redirect: '/404' } ] const router = new VueRouter({ routes }) export default router
在视图组件中配置 router-link标签,用于生成超链接
<router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/test">Test</router-link> |
在视图组件汇总配置router-view标签
<!--视图组件展示的位置--> <router-view/>
要实现路由跳转,可以通过标签式和编程式两种:
标签式:<router-link to="/about">About</router-link>
编程式:this.$router.push('/about')
问题思考:如果用户访问的路由地址不存在,该如何处理?
可以通过配置一个404视图组件,当访问的路由地址不存在时,则重定向到此视图组件,具体配置如下:
{ path: '/404', component: () => import('../views/404View.vue') }, { path: '*', redirect: '/404' //重定向 }
2.3 嵌套路由
嵌套路由:组件内要切换内容,就需要用到嵌套路由(子路由),效果如下:
在App.vue视图组件中有<router-view>标签,其他视图组件可以展示在此
ContainerView.vue组件可以展示在App.vue视图
组件的<router-view>位置
ContainerView.vue组件进行了区域划分(分为上、左、右),在右边编写了<router-view>标签,点击左侧菜单时,可以将对应的子视图组件展示在此
实现步骤:
第一步:安装并导入 elementui,实现页面布局(Container 布局容器)---ContainerView.vue
<template> <el-container> <el-header>Header</el-header> <el-container> <el-aside width="200px"> </el-aside> <el-main> </el-main> </el-container> </el-container> </template> <script> export default { } </script> <style> .el-header, .el-footer { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; } .el-aside { background-color: #D3DCE6; color: #333; text-align: center; line-height: 200px; } .el-main { background-color: #E9EEF3; color: #333; text-align: center; line-height: 160px; } body > .el-container { margin-bottom: 40px; } .el-container:nth-child(5) .el-aside, .el-container:nth-child(6) .el-aside { line-height: 260px; } .el-container:nth-child(7) .el-aside { line-height: 320px; } </style>
第二步:提供子视图组件,用于效果展示 ---P1View.vue、P2View.vue、P3View.vue
<template> <div> 这是P1 View </div> </template> <script> export default { } </script> <style> .el-header, .el-footer { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; } .el-aside { background-color: #D3DCE6; color: #333; text-align: center; line-height: 200px; } .el-main { background-color: #E9EEF3; color: #333; text-align: center; line-height: 160px; } body > .el-container { margin-bottom: 40px; } .el-container:nth-child(5) .el-aside, .el-container:nth-child(6) .el-aside { line-height: 260px; } .el-container:nth-child(7) .el-aside { line-height: 320px; } </style>
第三步:在 src/router/index.js 中配置路由映射规则(嵌套路由配置)
{ path: '/c', component: () => import('../views/container/ContainerView.vue'), //嵌套路由(子路由),对应的组件会展示在当前组件内部 children: [//通过children属性指定子路由相关信息(path、component) { path: '/c/p1', component: () => import('../views/container/P1View.vue') }, { path: '/c/p2', component: () => import('../views/container/P2View.vue') }, { path: '/c/p3', component: () => import('../views/container/P3View.vue') } ] }
第四步:在ContainerView.vue 布局容器视图中添加<router-view>,实现子视图组件展示
<el-main> <router-view/> </el-main>
第五步:在ContainerView.vue 布局容器视图中添加<router-link>,实现路由请求
<el-aside width="200px"> <router-link to="/c/p1">P1</router-link><br> <router-link to="/c/p2">P2</router-link><br> <router-link to="/c/p3">P3</router-link><br> </el-aside>
注意:子路由变化,切换的是【ContainerView 组件】中
<router-view></router-view>
部分的内容问题思考:
1.对于前面的案例,如果用户访问的路由是 /c,会有什么效果呢?
2.如何实现在访问 /c 时,默认就展示某个子视图组件呢?
配置重定向,当访问/c时,直接重定向到/c/p1即可,如下配置:
Vue中路由:路径 和 组件 的 映射 关系
编程式导航-基本跳转:
编程式导航-路由传参:
10.ESlint 代码规范
11.vuex概述
vuex 是一个专为 Vue.js 应用程序开发的状态管理库
vuex 可以在多个组件之间共享数据,并且共享的数据是响应式的,即数据的变更能及时渲染到模板
vuex 采用集中式存储管理所有组件的状态
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
安装vuex:npm install vuex@next --save
vuex中的几个核心概念:
state:状态对象,集中定义各个组件共享的数据
mutations:类似于一个事件,用于修改共享数据,要求必须是同步函数
actions:类似于mutation,可以包含异步操作,通过调用mutation来改变共享数据
3.2 使用方式
本章节通过一个案例来学习vuex的使用方式,具体操作步骤如下:
第一步:创建带有vuex功能的前端项目
![]()
注:在创建的前端工程中,可以发现自动创建了vuex相关的文件(src/store/index.js),并且在main.js中创建Vue实例时,需要将store对象传入,代码如下:
import Vue from 'vue' import App from './App.vue' import store from './store' Vue.config.productionTip = false new Vue({ store,//使用vuex功能 render: h => h(App) }).$mount('#app')
第二步:在src/store/index.js文件中集中定义和管理共享数据
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) //集中管理多个组件共享的数据 export default new Vuex.Store({ //集中定义共享数据 state: { name: '未登录游客' }, getters: { }, //通过当前属性中定义的函数修改共享数据,必须都是同步操作 mutations: { }, //通过actions调用mutation,在actions中可以进行异步操作 actions: { }, modules: { } })
第三步:在视图组件中展示共享数据
<template> <div class="hello"> <h1>欢迎你,{{$store.state.name}}</h1> </div> </template>
注:$store.state为固定写法,用于访问共享数据
第四步:在mutations中定义函数,用于修改共享数据
//通过当前属性中定义的函数修改共享数据,必须都是同步操作 mutations: { setName(state,newName) { state.name = newName } },
第五步:在视图组件中调用 mutations 中定义的函数
![]()
注:mutations中定义的函数不能直接调用,必须通过状态对象的 commit 方法来调用
第六步:如果在修改共享数据的过程中有异步操作,则需要将异步操作的代码编写在actions的函数中
//通过actions调用mutation,在actions中可以进行异步操作 actions: { setNameByAxios(context){ axios({ //异步请求 url: '/api/admin/employee/login', method: 'post', data: { username: 'admin', password: '123456' } }).then(res => { if(res.data.code == 1){ //异步请求后,需要修改共享数据 //在actions中调用mutation中定义的setName函数 context.commit('setName',res.data.data.name) } }) } },
注:在actions中定义的函数可以声明context参数,通过此参数可以调用mutations中定义的函数
第七步:在视图组件中调用actions中定义的函数
![]()
注:在actions中定义的函数不能直接调用,必须通过 this.$store.dispatch('函数名称') 这种方式调用
12.vue3
- 1.setup选项的执行时机?
- beforecreate钩子之前 自动执行
- 2.setup写代码的特点是什么?
- 定义数据+函数 然后以对象方式return
- 3.<script setup>解决了什么问题?
- 经过语法糖的封装更简单的使用组合式API
- 4.setup中的this还指向组件实例吗?
- 指向undefined
本质:是在原有传入数据的基础上,外层包了一层对象,包成了复杂类型
底层,包成复杂类型之后,再借助reactive 实现的响应式
注意点:访问数据,需要通过.value
推荐:以后声明数据,统一用ref
deep 深度监视,默认 watch 进行的是 浅层监视
- const ref1 =ref(简单类型)可以直接监视
- const ref2=ref(复杂类型)监视不到复杂类型内部数据的变化
模板引用的概念:
通过ref标识获取真实的dom对象或者组件实例对象