1.vue是什么
Vue是一个用于 构建用户界面 的 渐进式 框架
1.构建用户界面:基于数据动态渲染页面
2.渐进式:循序渐进的学习
3.框架:一套完整的项目解决方案,提升开发效率(理解记忆规则)
2.快速上手
安装插件:vue-devtools
- 直接访问谷歌商店, 搜索并安装
- 打开极简插件官网, 下载后, 拖拽至扩展程序中安装
3.el与data
el的两种写法
<!-- 直接绑定 -->
<script>
const app = new Vue({
el:'#app' //第一种写法,直接绑定
data: {
msg:'hello world'
}
})
</script>
<!-- 使用mount函数 -->
<script>
const app = new Vue({
data: {
msg:'hello world'
}
})
app.$mount('#app')
</script>
data两种写法
<!-- 对象式 -->
<script>
const app = new Vue({
el:'#app'
data: {
msg:'hello world'
}
})
</script>
<!-- 函数式 -->
<script>
const app = new Vue({
el:'#app'
data:function(){
return {
msg:'hello world'
}
}
})
</script>
4.MVVM模型
MVVM 是 Vue 实现数据驱动视图和双向数据绑定的核心原理。MVVM 指的是 Model、View 和 ViewModel,它把每个 HTML 页面都拆分成了这三个部分,如图所示:
Model:表示当前页面渲染时所依赖的数据源
View:表示当前页面所渲染的 DOM 结构
ViewModel:表示 vue 的实例,它是 MVVM 的核心
ViewModel 作为 MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起
当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构
当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中
5.vue的相关指令
5.1作用:
①Vue 会根据不同的指令实现不同的功能
②可以把指令看做一个特殊的 HTML 属性, 都是以 v- 开头
5.2相关指令
| 作用 | 示例 | 注意事项 | |
|---|---|---|---|
| v-html | 设置元素的 innerHTML | <div v-html="表达式"></div> | |
| v-if 和 v-show | 控制元素显示隐藏 | <div v-if="表达式"></div> <div v-show="表达式"></div> | v-show 是控制 display: none 来实现显示隐藏的, 适合频繁切换显示隐藏的场景。 v-if 是创建/删除 DOM 元素来实现显示隐藏的, 适合初始状态就确定显示隐藏的场景 |
| v-else 和 v-else-if | v-if 的多分支结构 | v-else 必须紧贴着 v-if 或 v-else-if, 中间不能间隔其他元素, 注释除外 | |
| v-on(简写@click) | 绑定事件 | 内联语句=》<button v-on:事件名="内联语句" /> | 绑定事件处理函数 <button v-on:事件名="事件处理函数" /> 需要在 methods 中声明事件处理函数 new Vue({ el: '#app', data: {}, |
| v-bind简写 :属性名 | 动态设置 HTML 属性(src href title ...) | <img v-bind:属性名="表达式" /> | |
| v-for | 循环渲染标签元素的 | v-for="(每一项, 索引) in 数组" | v-for 写在哪个标签上就代表循环渲染哪个标签 |
| v-model | 主要用于表单元素的双向数据绑定 | 语法:v-model="vue 变量" | 效果:数据变化, 视图会自动更新 用户输入内容, 数据自动更新 |
| key属性 | 唯一标识, 用于让 Vue 来区分数据项, 自动进行排列顺序的 | 如果没设置 key 则默认按照就地更新策略, 尽可能复用标签, 从而不删除当前元素 | 字符串或数字 类型必须是唯一的, 不能重复 推荐使用 id 作为 key |
6.指令修饰符
简介:通过"."指明一些指令后缀,不同后缀封装了不同的处理操作
6.1 按键修饰符
@keyup.enter
6.2 v-model修饰符
v-model.trim 去除首尾空格
v-model.number 转数字
6.3 事件修饰符
Vue中的事件修饰符:
1.prevent:阻止默认行为(常用)
阻止a标签的跳转
方法1:@事件名.prevent=》阻止默认行为
方法2:event.preventDefault()
2.stop:阻止事件冒泡(常用)
方法1:@事件名.stop=》阻止冒泡
方法2:event.stopPropagation()
3.once:事件只触发一次(常用)
4.capture:使用事件的捕获模式
5.self:只有event.target是当前操作的元素时才触发事件
6.passive:事件的默认行为立即执行,无需等待事件回调执行完成
7.v-bind对于样式操作的增强
5.1 class类名
:class="{类名1:布尔值,类名2:布尔值}" 适用场景:一个类名,来回切换
:class="[类名1,类名2,类名3]" 适用场景:批量添加或删除类
5.2 style行内样式
:style="{css属性名1:css属性值,css属性名2:css属性值}" :style="{width:100px}"
8.v-model应用于其他表单元素
常见的表单元素都可以用v-model绑定关联_->快速获取或设置表单元素
输入框 input:text value
文本框 textarea value
复选框 input:checkbox ①绑定的是数组,向数组中添加value
②绑定的是布尔值,改变的是checked
单选框 input:radio value
下拉菜单 select value
9.computed计算属性
9.1 概念:基于现有的数据,计算出来的新属性,依赖的数据变化,自动重新计算
9.2 语法:
①声明在computed配置项中,一个计算属性对应一个函数
②使用起来和普通属性一样使用{{计算属性名}}
computed: {
计算属性名 () {
//基于现有数据,编写求值逻辑
return 结果
}
},
计算属性默认简写,只能访问,不能修改。如果要修改,需要使用完整写法
- 完整写法:计算属性是一个对象,对象中拥有两个方法(get / set),get 相当于以前的简写函数
- 当计算属性被赋值时,计算属性的
set会执行
computed: {
计算属性名: {
get() {
//一段代码逻辑(计算逻辑)
return 结果
},
set(修改的值) {
//一段代码逻辑(修改逻辑)
}
}
}
计算属性与普通方法的区别在于:computed具有缓存特性、自动依赖追踪,适用于衍生数据的计算;而methods没有缓存和自动追踪依赖,适用于执行函数操作和处理事件
10.watch侦听器
watch 侦听器用于监视数据变化,执行一些业务逻辑或异步操作
- 简写
- 监听器名需要和数据名完全相同,当数据变化时自动执行该函数
- 简单类型数据,直接监视
- 数据是一个对象的属性,可以把函数名定义成:
对象.属性
watch: {
数据属性名(newValue, oldValue) {
//一些业务逻辑 或 异步操作
},
'对象.属性名'(newValue, oldValue) {
//一些业务逻辑 或 异步操作
}
}
完整写法(添加额外配置项)
deep: true对复杂类型深度监视immediate: true初始化立刻执行一次handler方法
watch: {
数据属性名: {
deep: true, // 深度监视(针对复杂类型)
immediate: true, // 是否立刻执行一次handler
handler (newValue, oldValue) {
console.log(newValue, oldValue)
}
}
}
11.vue的生命周期
vue里面的生命周期函数有哪些?Vue父子组件生命周期顺序?
它是指vue的实例对象从创建到销毁的过程,有四个周期八个钩子函数。一般在created函数中发送ajax请求获取
数据,在mounted中获取挂载完毕的真实dom,destroy中销毁定时器,延时器或绑定的一些事件。
初始化、挂载、更新、销毁。beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
创建的时候有4个: beforeCreate created beforeMount mounted
更新的时候 是 beforeUpdate updated
销毁的时候 是 beforeDestroy destroyed
如果组件有缓存,就是加上了keep-alive以后,会多两个生命周期函数, activeted deactiveted
在父子组件里面的生命周期:
先执行父组件的3个钩子函数 -- 然后执行完子组件的创建时期的4个钩子函数 --- 最后再执行父组件的mounted钩
子函数 (Parent beforeCreate -> Parent Created -> Parent BeforeMount -> Child BeforeCreate -> Child
Created -> Child BeforeMount -> Child Mounted -> Parent Mounted)
12.工程化开发和脚手架
1.开发vue的两种方式
- 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。
- 工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。
工程化开发模式优点:
提高编码效率,比如使用JS新语法、Less/Sass、Typescript等通过webpack都可以编译成浏览器识别的ES3/ES5/CSS等
工程化开发模式问题:
- webpack配置不简单
- 雷同的基础配置
- 缺乏统一的标准
为了解决以上问题,所以我们需要一个工具,生成标准化的配置
2.脚手架Vue CLI
基本介绍:
Vue CLI 是Vue官方提供的一个全局命令工具
可以帮助我们快速创建一个开发Vue项目的标准化基础架子。【集成了webpack配置】
好处:
- 开箱即用,零配置
- 内置babel等工具
- 标准化的webpack配置
使用步骤:
- 全局安装(只需安装一次即可) yarn global add @vue/cli 或者 npm i @vue/cli -g
- 查看vue/cli版本: vue --version
- 创建项目架子:vue create project-name(项目名不能使用中文)
- 启动项目:yarn serve 或者 npm run serve(命令不固定,找package.json)
13.项目目录介绍和运行流程
1.项目目录
虽然脚手架中的文件有很多,目前咱们只需人事三个文件即可
- main.js 入口文件
- App.vue App根组件
- index.html 模板文件
2.运行流程
3.关于不同版本的Vue
- vue.js与vue.runtime.xxx.js的区别:
(1)vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2)vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
-
因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的
createElement函数去指定具体内容。
4.vue.config.js配置文件
使用
vue inspect > output.js可以查看Vue脚手架的默认配置。使用vue.config.js可以对脚手架进行个性化定制,详情见:cli.vuejs.org/zh
14.组件化
1.好处
便于维护,利于复用。
把页面拆分成一个个组件来开发
2.组件是什么
定义:.vue结尾的文件就是一个组件
组成:template,script,style
template 有且只能有一个根元素
script
style lang设置less预处理器,记得装包 npm i less less-loader -g
3.组件的使用
分为局部注册和全局注册
4.组件三大组成部分的注意点
结构:有且只能有一个根元素
样式:默认全局样式,加上scoped局部样式
逻辑:data是一个函数,保证数据独立
15.scoped的原理
1.给当前组件的所有标签添加自定义属性data-v-hash,当前组件的hash值与其他组件的hash不相等2.
2.css样式是属性交集选择器,改变当前组件的样式其他组件不受影响
16.vue路由模式=>hash和history
区别:
路由有两种模式:hash和history
1、hash有#号 ,history没有#号
2、hash不会刷新页面,不会向服务器发送请求【刷新没有任何影响】。history会刷新页面,向这个地址发送请求。
【刷新页面】===因为会向服务器请求这个地址
3、hash上线不需要任何操作没有任何影响,但是history会出现页面找不到,因为会向服务器发送请求,所以需要服务器帮助解决。
原理:hash:hashchange history:popState replaceState
跳转方式2种:声明式导航和编程式导航跳转。
声明式导航跳转是route-link,to里面的是地址
编程式跳转用this.$router.push('跳转的路径')
传参方式有2种:query传参(有?号)和params传参(没有?号)。
query用$route.query.参数名 接收参数,
params是用$route.params.参数名 来接收参数
导航守卫钩子函数:beforeEach,afterEach
nginx配置:
17.vuex的几个概念?
Vuex 的核心概念包括:State(状态)、Mutation(变化)、Action(动作)、Getter(获取器)、Module(模块)
State
State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 中的 State 中存储。在 state 对象中可以添加我们要共享的数据
mutations
state 数据的修改只能通过 mutations,并且 mutations 必须是同步的。mutations 是一个对象,对象中存放修改 state 的方法
actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态
- Action 可以包含任意异步操作
getters
获取器用于从状态中派生出新的状态。它可以将现有的状态进行计算和转换,并提供一个类似于计算属性的方式来访问这些派生状态
modules
Module(模块): 模块可以将整个状态树分割成更小的模块,每个模块都有自己的状态(state)、变化(mutation)、动作(action) 和获取器(getter)。这样可以将复杂的应用程序拆分成可维护和可测试的模块。通过模块化的方式,可以更好地组织和维护大型的状态管理
18.vuex在组件里面怎么使用
在vuex里面 先要定义修改数据的mutations,以及发请求的actions,在actions函数里面去 commit提交mutations
在业务组件里面,直接通过dispatch分发我们的actions
19.组件通信
定义:就是指组件与组件之间的数据传递
注意点:组件的数据是独立的,无法直接访问其他组件的数据。
想用其他组件的数据->组件通信
1.props/$emit父子组件通信
父传子=》首先在父组件中子组件定义自定义属性,在子组件里通过props接收父组件传递的数据。
子传父=》子组件用$emit来触发自定义事件,并且可以传递参数给父组件。父组件通过监听子组件的自定义事件来获取传递的数据
2.ref与children适用父子组件通信
3.EventBus(on)兄弟组件传值
【main.js=>原型对象上 vue.prototype.Bus.emit() 弟:this.$Bus.on】
在全局使用emit/on,来传值
4.provide/inject适用后代组件通信
provide/inject
5.listeners适用于隔代组件通信
6.Vuex适用于父子、隔代、兄弟组件通信
Vuex 的核心概念包括:State(状态)、Mutation(变化)、Action(动作)、Getter(获取器)、Module(模块)
20.插槽
默认插槽
默认插槽的主要作用是让组件内部的一些结构支持自定义
- 组件内需要定制的结构部分,改用
<slot></slot>占位 - 使用组件时, 在组件标签内部传入自定义结构来替换
slot
<!-- 在Card组件中 -->
<template>
<div class="card">
<div class="card-header">标题</div>
<div class="card-body">
<!-- 这里是默认插槽的位置 -->
<slot></slot>
</div>
</div>
</template>
<!-- 使用Card组件 -->
<Card>
<!-- 此处会替换slot -->
<p>这是卡片的主要内容</p>
<p>可以是文本、图片等各种元素</p>
</Card>
插槽后备内容(默认值):
- 封装组件时,可以为预留的
<slot>插槽提供后备内容(默认内容) - 外部使用组件时,不传内容,则
slot会显示后备内容;外部使用组件时,传入内容,则slot整体会被替换
<!-- 在Card组件中 -->
<template>
<div class="card">
<div class="card-header">标题</div>
<div class="card-body">
<slot><p>这是插槽后备内容</p></slot>
</div>
</div>
</template>
具名插槽
具名插槽,顾名思义就是具有名字的插槽,可以将一个组件中的多处结构进行定制
具名插槽语法:
- 多个 slot 使用 name 属性区分名字(子组件中)
<div class="dialog-header">
<slot name="head"></slot>
</div>
<div class="dialog-content">
<slot name="content"></slot>
</div>
<div class="dialog-footer">
<slot name="footer"></slot>
</div>
- template 配合
v-slot:插槽名来分发对应标签(父组件中)
<MyDialog>
<!-- v-slot 只能用在template上(官网有一种特殊情况) -->
<template v-slot:head>
大标题
</template>
<template v-slot:content>
内容文本
</template>
<template v-slot:footer>
<button>按钮</button>
</template>
</MyDialog>
v-slot:插槽名可以简化成 #插槽名,此外插槽默认名为 default
作用域插槽
定义slot插槽的同时是可以传值的。插槽上可以绑定数据,将来使用组件时可以使用
作用域插槽:将数据从子组件通过插槽传递给父组件
- 在子组件的
slot上绑定数据 - 在父组件中使用
template配合v-slot取值
为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 <slot> 元素的一个属性绑定上去:
<span>
<!-- :user 相当于往插槽上加了一个属性, 最终以对象包裹属性的形式传递过去{ user: user} -->
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 <slot> 元素上的属性被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:
<current-user>
<!-- <template #default="slotProps"> -->
<!-- 如果不用 # 也可以不指定名字, 直接写为 v-slot="变量名",不过使用多个插槽时不能这么做 -->
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,也可以使用任意命名。此外,插槽也是可以解构的
21.vue2响应式的原理
vue响应式也叫作数据双向绑定,大致原理阐述:
vue响应式的原理是通过数据劫持+发布者-订阅者模式的方式来实现的,首先是通过ES5提供的
Object.defineProperty()方法来劫持(监听)各属性的getter、setter,并在当监听的属性发生变动时通知订阅者,是
否需要更新,若更新就会执行对应的更新函数。
数据代理:
Object.defineProperty(对象,属性名,配置项)
<script type="text/javascript">
let number=18
let person={
name:'张三',
sex:'男',
}
Object.defineProperty(person,'age',{
//value:18,
//enumerable:true,//控制属性是否可以枚举,默认值是false
//writable:true,//控制属性是否被修改,默认值是false
//configurable:true,//控制属性是否被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
console.log('有人读取了age属性了')
return number
},
//当有人修改person的age的属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number=value
}
})
</script>
扩展:vue3响应式的原理是通过proxy代理来实现的
什么是数据劫持
数据劫持比较好理解,通常我们利用Object.defineProperty劫持对象的访问器,在属性值发生变化时我们可以获
取变化,从而进行进一步操作
22.vue2和vue3的区别
①响应式原理不同
vue2是利用ES5的object.definePropert()对数据进行监听和结合发布订阅模式的方式来实现的
vue3中使用了ES6的proxy对数据代理
②组合API
vue2采用选项式API对比vue3组合式API
vue3中没有this,没有beforecreate和created,它们的功能放在了setup中
③根节点
vue2只能有一个根节点,vue3可以有多个根节点
vue2若想新增或者修改一个需求,就需要分别修改:data、methods、computed,不便于维护和复用
vue3的优点
1.首次渲染更快
2.diff算法更快
3.内存占用更少
4.打包体积更小
5.更好的支持TypeScript
6.Composition API
vue3不同点:
1.组件一个根节点非必需
2.创建应用挂载到根容器
3.入口页面,ESM(模块化)加载资源
23.vue3的注意事项
1.setup函数中不能使用this。vue为了避免我们错误的使用,直接将setup函数中的this修改成了undefined
2.setup函数中的props是响应式的,当传入新的prop时,他将被更新。但是,因为props是响应式的,你不能使
用ES6解构,因为它会消除prop的响应式,如果需要解构prop,可以使用setup函数中的toRefs来完成此操作。
24.组件通信方式eventBus原理
EventBus 是一种用于在不同的组件或模块之间传递事件的方法。它通常通过一个中央事件总线来实现,该事件总线可以连接不同的组件或模块,使得它们可以进行松耦合通信。
以下是使用 EventBus 的一个简单示例:
首先,你需要安装 EventBus 库,如果你使用的是 Node.js,可以通过 npm 安装:
npm install eventbus
然后,你可以创建一个 EventBus 实例并使用它来发送和监听事件:
// 引入 EventBus
const EventBus = require('eventbus');
// 创建 EventBus 实例
const bus = new EventBus();
// 组件 A 监听事件
bus.on('eventName', (data) => {
console.log('Event received in Component A with data:', data);
});
// 组件 B 触发事件
bus.emit('eventName', { message: 'Hello from Component B!' });
在这个例子中,组件 A 通过 bus.on 监听名为 'eventName' 的事件,而组件 B 通过 bus.emit 触发同样名为 'eventName' 的事件,并附带数据。当事件被触发时,监听该事件的所有组件都会接收到数据并执行相应的回调函数。
这就是 EventBus 的基本使用方法。实际应用中,你可能需要根据具体情况扩展和定制 EventBus,例如添加事件命名空间、支持异步事件监听器等。
25.vue-router路由钩子有哪些
全局钩子beforeEach、afterEach
单个路由里面的钩子:beforeEnter、beforeLeave
组件路由:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave