一、初探Vue
1.1、vue介绍
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式 JavaScript框架。
它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助开发者高效地开发用户界面,无论项目是简单还是复杂。
渐进式 JavaScript框架:就像是一个可以逐步升级的工具箱。它允许你从一个简单的工具开始,然后随着需要添加更多的工具。
在使用开发项目时开发者可以一点点来引入和使用Vue,而不一定需要全部Vue来开发整个项目
1.2、Vue前端地位
目前前端最流行的是框架:Vue、React
百度指数近一年国内前端对比
github数据
vue2数据
vue3数据
如果你学好了Vue知识,你一定可以找到一份不错的工作。
1.3、学习vue2还是vue3呢?
vue3版本是兼容vue2的,对于学习vue来说,直接学习vue3就可以了。
1.4、声明式
Vue的声明式编程就像是一种用代码来描述你想要什么,而不是你想要如何得到它的编程方式。例如,如果你想用 Vue构建一个简单页面展示,你可以写出以下代码:
<div>
<h1>{{ title }}</h1>
</div>
在这个代码中,<div> 元素是页面的根元素,<h1> 元素是页面的标题元素。{{ title }}是 Vue框架提供的指令,它将 title数据绑定到 <h1>元素的内容上。
当 title数据发生变化时,Vue会自动更新 <h1>元素的内容。你不需要显式地告诉 Vue如何更新这些元素,它会自动为你完成。
这就是 Vue的声明式编程,你只需要声明你想要什么,Vue 会自动帮你实现它。
1.5、组件化
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。几乎任意类型的应用界面都可以抽象为一个组件树。
组件特点:隔离性[默认数据不关联],在vue中一个组件包含 html、js、css
组件化好处:复用和便于维护
tag:div
children:[
…
{
tag:div,
children:[ { ] } ] }
把此dom称之为虚拟dom,虚拟dom它就是js对象
vue为什么要使用虚拟Dom ?
虚拟 DOM (Virtual DOM) 是一种编程概念,在这个概念里,我们用 JavaScript 对象来描述真实 DOM 的状态。当状态变化时,我们生成一个新的虚拟 DOM,并和旧的虚拟 DOM 进行对比,然后将这个差异应用到真实的 DOM 上,从而避免直接操作 DOM 带来的性能问题。
Vue.js 使用虚拟 DOM 主要有以下几个原因:
- 提高性能:直接操作 DOM 的成本很高。每一次操作,无论多小,都会导致浏览器重新计算布局,重新绘制页面。相比之下,操作 JavaScript 对象的成本很低。通过在虚拟 DOM 上进行操作,我们可以最小化对真实 DOM 的操作,从而提高性能。
- 跨平台:虚拟 DOM 不仅可以在浏览器中运行,也可以在其他环境中运行,如服务器、移动设备等。这使得 Vue.js 能够支持跨平台应用,如服务器端渲染、移动应用等。
- 方便测试:因为虚拟 DOM 是纯粹的 JavaScript 对象,所以我们可以在没有浏览器环境的情况下进行测试,使测试更加方便。
Vue中虚拟 DOM 的工作原理如下:
- 当数据变化时,Vue 会生成一个新的虚拟 DOM。
- 然后Vue会用一个算法比较新旧虚拟 DOM【diff比对】
- 这个算法会通过一系列的复杂规则,找出两个虚拟 DOM 之间的最小差异。
- 最后会使用这个差异,通过最少的操作来更新真实的 DOM。
这就是 Vue.js 中虚拟 DOM 的工作原理,这种方式可以大大提高应用的性能,使用户的体验更好。
1.6、MVVM
MVVM(Model-View-ViewModel)是一种软件架构模式,它将应用程序划分为三个部分:模型(Model)、视图(View)和视图模型(ViewModel)。
模型(Model): 模型是应用程序的数据部分。它包含应用程序的所有数据,包括业务逻辑和数据操作。
视图(View): 视图是应用程序的用户界面部分。它负责将数据呈现给用户,并允许用户与应用程序交互。
视图模型(ViewModel): 视图模型是连接模型和视图的桥梁。它负责将模型中的数据转换为视图可以理解的形式,并处理来自视图的事件。
MVVM 的主要优点是它可以将应用程序的逻辑部分(模型)与表示部分(视图)分离。这使得应用程序更容易维护和扩展。
MVVM 是一个非常流行的软件架构模式,它被广泛用于构建 Web 应用程序和移动应用程序。
Vue框架就是基于MVVM框架。
基于Proxy实现简易mvvm
// 模型(Model)
const model = {
message: 'Hello, world!'
}
// 视图模型(ViewModel)
const viewModel = new Proxy(model, {
get(target, property) {
return target[property]
},
set(target, property, value) {
target[property] = value
// 通知视图更新
updateView()
return true
}
})
// 视图(View)
const view = document.getElementById('app')
function updateView() {
view.innerHTML = `<h1>${viewModel.message}</h1>`
}
// 初始化视图
updateView()
// 用户交互(例如,点击按钮)
document.getElementById('button').addEventListener('click', () => {
viewModel.message = 'Hello, Vue.js!'
})
在这个示例中,模型(model)是一个简单的对象,它包含一个 message 属性。视图模型(viewModel)是一个 Proxy 对象,它代理了模型对象。当视图模型的属性发生变化时,它会自动触发 updateView() 函数,从而更新视图。
当用户点击按钮时,视图模型的 message 属性被更新为 "Hello, Vue.js!",这会触发 updateView() 函数,从而更新视图,在页面上显示 "Hello, Vue.js!"。
二、使用Vue
1.1、引入vue
- 下载Vue的JavaScript文件,并且自己手动页面中通过script引入
https://unpkg.com/vue@3/dist/vue.global.js
- 通过Vue命令行工具,创建项目 -- 推荐方式
1.2、Vue初体验
通过script方式来进行初体验vue学习
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">{{ message }}</div>
<script>
Vue.createApp({
// 初始化数据
// data中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫持中被处理
// data中声明的数据具备响应式,数据的修改会触发视图更新
// 在Vue3.x中,必须传入一个函数且必须要返回一个对象
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
1.3、插件安装
通过chrome中的谷歌插件商店安装Vue Devtools工具,此工具帮助我们进行vue数据调试所用,一定要安装。
chrome应用商店:https://chrome.google.com/webstore?utm_source=chrome-ntp-icon
国内镜像站:https://chrome.zzzmh.cn/
- 在vscode中安装插件
三、模板语法
1.1、数据绑定
vue框架提供的一种在html模板中绑定数据的方式,使用{{变量名}}方式绑定Vue实例中data中的数据变量。会将绑定的数据实时的显示出来。【Mustache语法】
<div id="app">
<h3>{{name}}</h3>
<h3>{{name + '--好的'}}</h3>
<h3>{{ 1 + 1 }}</h3>
<!-- 使用函数 -->
<h3>{{title.substr(0,6)}}</h3>
<!-- 三目运算 -->
<h3>{{ age>22 ? '成年':'未成年'}}</h3>
</div>
注:{{}}括起来的区域,就是一个就是js语法区域,在里面可以写部份的js语法。不能写 var a = 10; 分支语句 循环语句
1.2、内置指令
Vue.js 内置了许多指令,可以帮助开发者更方便地操作 DOM 元素和响应用户交互。
Vue.js中它规定标签中的属性要是以v-开头的属性,称为指令
Vue.js 的指令具有以下优势:
- 简化开发: 指令可以帮助开发者更轻松地操作 DOM 元素和响应用户交互,从而简化开发过程。
- 提高性能: 指令可以帮助 Vue.js 更有效地更新 DOM,从而提高应用程序的性能。
- 增强可读性: 指令可以使代码更加简洁和可读,从而增强代码的可维护性。
1.2.1、v-text和v-html
v-text: 更新元素的文本内容
<span v-text="msg"></span>
<!-- 等同于 -->
<span>{{msg}}</span>
v-html: 更新元素的 innerHTML。
<div v-html="html"></div>
注:
在你的站点上动态渲染任意的 HTML 是非常危险的,因为它很容易导致XSS攻击。请只对可信内容使用 HTML内容使用此指令进行渲染
1.2.2、v-cloak
解决浏览器在加载页面时因存在时间差而产生的“闪动”问题
# css中设置
[v-cloak] {
display: none;
}
# html
<div v-cloak>
{{ message }}
</div>
1.2.3、v-pre
跳过该元素及其所有子元素的编译。 提升性能指令
<span v-pre>不需要编译,直接可以运行</span>
1.2.4、v-once
仅渲染元素和组件一次,并跳过之后的更新。
<div id="app">
<h3>{{message}}</h3>
<hr>
<!-- 动态修改message值,此绑定将不会发生改变 -->
<div v-once>{{message}}</div>
</div>
1.2.5、v-if和v-show
根据表达式的布尔值(true/false)进行判断是否渲染该元素
<div id="app">
<!--
v-if是对dom元素的移除和创建
v-show是通过修改标签的display值
-->
<!-- 如果isShow的值是true ,就显示p标签 -->
<p v-if="isShow">我是p标签中的内容</p>
<p v-show="isShow">我是p标签中的内容</p>
</div>
注:v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
# 多条件判断
v-if … v-else-if v-else
1.2.6、v-bind
动态地绑定一个或多个属性值
<!-- v-bind绑定href属性值 -->
<a v-bind:href='url'>跳转</a>
<!-- v-bind绑定href属性值(简写形式) -->
<a :href='url'>跳转</a>
1.2.7、v-on
绑定事件监听器(事件绑定)
<!-- 常规写法 -->
<button v-on:click="事件实现方法()"></button>
<!-- 缩写 -->
<button @click="事件实现方法()"></button>
# 绑定好事件实现方法后需要在Vue对象中的methods对象中实现对应的绑定方法
methods: {
functionName(arg1,arg2,arg3,...){
// something to do
},
....
}
- 事件处理函数传参 -- 事件对象--- event对象
<!-- 事件处理函数调用:直接写函数名 -->
<button @click="say"></button>
<!-- 事件处理函数调用:常规调用 -->
<button @click="say($event)"></button>
# 注:如果没有参数时,可以不写小括号,默认就会把event事件对象绑定到实现的方法中,如果需要传参数时,则通过 $event 来手动传递到实现的方法中
- 事件修饰符
用来处理事件的特定行为
<!-- 阻止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<a @click.prevent="doThis"></a>
<!-- 只执行一次 -->
<div @click.once="incr()">自增一下</div>
<!-- 绑定的元素本身触发时才触发回调 -->
<ul @click.self="incr()">
<li>你好世界</li>
</ul>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
- 按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。
<!-- 只有在 `key` 是 `Enter` 回车键的时候调用 -->
<input @keyup.enter="submit">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
1.2.8、v-for
根据一组数组或对象的选项列表进行渲染。
v-for指令需要使用 (item,index) in 数组或对象 形式的特殊语法,同时还需要指定key值,key的作用在vue进行新旧数据比对渲染页面里,如果有key值会提升比对性能,加快渲染,key使用唯一的值来赋值。
key值尽量不要使用索引值,索引会有塌陷问题
<div v-for="(item, index) in items" :key="item.id"></div>
<div v-for="(item, key, index) in object" :key="item.id"></div>
注:同时使用 v-if 和 v-for 是不推荐的,因为这样二者的优先级不明显。
vue3中 v-if优先级高于v-for,vue则反之
<!-- 这会抛出一个错误,因为属性 todo 此时 没有在该实例上定义 -->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
正确写法通过template包裹一层
<template v-for="todo in todos">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
Diff比对
vue中当数据发生改变的时候,对应监听的set方法会执行,调用数据中的Dep.notify方法通知所有的订阅者,订阅者就会通过patch函数对比新旧虚拟节点是否一样,如果用新的虚拟节点则整个替换老节点,如果不是使用新节点,则根据子节点情况来进行同层比较。
patch主要做4个判断
①、没有新节点,直接触发旧节点的destory钩子,进行销毁。
②、没有旧节点,此时根本不需要比较了,直接全部都是新建
③、旧节点和新节点一样时,直接调用 patchVnode 去处理这两个节点 (比较属性,子元素,文本(直接换)只要保证key相同就不会被销毁,Key不相同就会销毁
④、旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点
- 没有key的比较
- 有key值标识比较
两个索引值,一个从开头一个从末尾开始(两端向中间循环)
key值的作用:在使用diff算法比较新旧dom树的时候,可以更准确更快得找到oldDom树中对应的节点。(利用key的唯一性生成map对象来获取对应节点,比遍历方式更快)
1.2.9、样式绑定
1.2.9.1、class样式处理
- 对象语法
.active {
color: red;
}
<div v-bind:class="{active: isActive}">class样式</div>
data: {
isActive: true
}
数组语法
.active {
color: red;
}
<div v-bind:class="[activeClass]">数组写法</div>
data: {
activeClass: 'active'
}
1.2.9.2、绑定style
- 对象语法
<div:style="{color: redColor, fontSize: '20px'}">对象写法</div>
data: {
redColor: 'red'
}
- 数组语法
<div v-bind:style="[color, fontSize]">数组写法</div>
data: {
color: {
color: 'red'
},
fontSize: {
'font-size': '20px'
}
}
1.3、v-model
作用: 表单元素的绑定,实现了双向数据绑定,通过表单项可以更改数据。
v-model会忽略所有表单元素的value/checked特性的初始值,而总是将Vue实例的数据作为数据来源,应该在data选项中声明初始值。
v-model它是一个语法糖 value/checked 属性 input/change
- 绑定文本框
<p>{{message}}</p>
<input type='text' v-model='message'>
<!-- v-model其实是语法糖,它是下面这种写法的简写 -->
<!-- 语法糖:这种语法对语言的功能并没有影响,但是更方便程序员使用 -->
<input v-bind:value='message' v-on:input='message = $event.target.value' />
data: {
message: 'message默认值'
}
- 绑定多行文本框
<textarea v-model="message"></textarea>
data: {
message: '我是多行文本内容'
}
注意:多行文本框中使用插值表达式 无效
- 绑定单个复选框
# 绑定一个复选框
<input type="checkbox" v-model="checked">
data:{
checked:true
}
- 绑定多个复选框
此种方式需要input标签提供value属性
<input type="checkbox" value="html" v-model="checkedNames">
<input type="checkbox" value="css" v-model="checkedNames">
<input type="checkbox" value="js" v-model="checkedNames">
data:{
// 如果数组中有对应的value值,则此checkbox会被选中
checkedNames:[]
}
- 绑定单选框
需要input提供value属性的值
男<input type="radio" value="男" v-model="sex">
女<input type="radio" value="女" v-model="sex">
data: {
sex: ''
}
- 绑定下拉框
<select v-model="selected">
<option value="0">请选择</option>
<option value="1">HTML</option>
<option value="2">CSS</option>
<option value="3">JS</option>
</select>
data: {
selected: ''
}
- 修饰符
.lazy 失去焦点时触发(延时更新数据源)
.number 输入值转为数值类型
.trim 自动过滤用户输入的首尾空白字符
四、自定义指令
除了核心功能默认内置的指令,Vue也允许注册自定义指令。有的情况下,对普通 DOM 元素进行底层操作,这时候就会用到自定义指令绑定到元素上执行相关操作。
自定义指令分为:全局指令和局部指令,当全局指令和局部指令同名时以局部指令为准。
el:指令绑定到的元素。这可以用于直接操作 DOM
binding:一个对象
vnode:代表绑定元素的底层 Vnode
prevNode:代表之前的渲染中指令所绑定元素的 VNode
// 在绑定元素的 attribute 前 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
定义全局指令
const app = createApp({})
// 使 v-focus 在所有组件中都可用
app.directive('focus', {
/* ... */
})
// 简化形式
app.directive('color', (el, binding) => {
// 这会在 `mounted` 和 `updated` 时都调用
el.style.color = binding.value
})
五、计算属性 - computed
模板中放入太多的逻辑会让模板过重且难以维护,使用计算属性可以让模板变得简洁易于维护。计算属性是基于它们的响应式依赖进行缓存的,计算属性比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化。
计算属性定义在Vue对象中,通过关键词computed属性对象中定义一个个函数,并返回一个值,使用计算属性时和data中的数据使用方式一致
<div id="app">
<!-- 当多次调用 cfn计算属性时只要里面的 num值不改变,它会把第一次计算的结果直接返回直到data中的num值改变 计算属性才会重新发生计算 -->
<div>{{ cfn }}</div>
<div>{{ cfn }}</div>
<!-- 调用methods中的方法的时候 他每次会重新调用 -->
<div>{{ fn() }}</div>
<div>{{ fn() }}</div>
</div>
<script type="text/javascript">
// 计算属性
computed: {
cfn() {
console.log('computed')
return this.num
}
}
</script>
注:只要依赖的数据源不发生改变,我就调用1次,其它使用缓存
六、侦听器 - watch
使用watch来侦听data中数据的变化,watch中的属性一定是data 中已经存在的数据。
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
<div id="app">
<input type="text" v-model="username">
</div>
<script>
watch: {
username(newVal, oldVal) {
console.log(newVal, oldVal)
}
}
</script>
--------------------------------------------------------
# 对象侦听
七、混入 - Mixins
混入(mixins)是一种分发Vue组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
混入分为:全局和局部
# 全局混入
const app = Vue.createApp({})
app.mixin({
created(){},
methods:{}
})
# 局部混入
let mixinObj = {}
Vue.createApp({
created() {
console.log(2)
},
mixins: [mixinObj]
})
八、自定义指令的钩子函数
除了核心功能默认内置的指令,Vue也允许注册自定义指令。有的情况下,对普通 DOM 元素进行底层操作,这时候就会用到自定义指令绑定到元素上执行相关操作。
自定义指令分为:全局指令和局部指令,当全局指令和局部指令同名时以局部指令为准。
el:指令绑定到的元素。这可以用于直接操作 DOM
binding:一个对象
vnode:代表绑定元素的底层 Vnode
prevNode:代表之前的渲染中指令所绑定元素的 Vnode
// 在绑定元素的 attribute 前 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
定义全局指令
const app = createApp({})
// 使 v-focus 在所有组件中都可用
app.directive('focus', {
/* ... */
})
// 简化形式
app.directive('color', (el, binding) => {
// 这会在 `mounted` 和 `updated` 时都调用
el.style.color = binding.value
})
<div v-test>{{title}}</div>
九、计算属性 - computed
模板中放入太多的逻辑会让模板过重且难以维护,使用计算属性可以让模板变得简洁易于维护。计算属性是基于它们的响应式依赖进行缓存的,计算属性比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化。
计算属性定义在Vue对象中,通过关键词computed属性对象中定义一个个函数,并返回一个值,使用计算属性时和data中的数据使用方式一致
<div id="app">
<!-- 当多次调用 cfn计算属性时只要里面的 num值不改变,它会把第一次计算的结果直接返回直到data中的num值改变 计算属性才会重新发生计算 -->
<div>{{ cfn }}</div>
<div>{{ cfn }}</div>
<!-- 调用methods中的方法的时候 他每次会重新调用 -->
<div>{{ fn() }}</div>
<div>{{ fn() }}</div>
</div>
<script type="text/javascript">
// 计算属性
computed: {
cfn() {
console.log('computed')
return this.num
}
}
</script>
注:只要依赖的数据源不发生改变,我就调用1次,其它使用缓存
十、侦听器 - watch
使用watch来侦听data中数据的变化,watch中的属性一定是data 中已经存在的数据。
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
<div id="app">
<input type="text" v-model="username">
</div>
<script>
watch: {
username(newVal, oldVal) {
console.log(newVal, oldVal)
}
}
</script>
# 对象侦听
<div id="app">
<input type="text" v-model="obj.username">
</div>
<script >
watch: {
obj: {
handler(newVal, oldVal) {
console.log(newVal, oldVal)
},
// 深度侦听
deep: true,
// 初始化执行
immediate:true
}
</script>
十一、实例生命周期
每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如需要设置数据监听、编译模板、挂载实例到 DOM、在数据变化时更新 DOM 等。同时在这个过程中会主动的运行一些叫做生命周期钩子的函数,给予用户机会在一些特定的场景下添加他们编写自己的代码。
|
十二、网络请求
Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是同一套代码可以运行在浏览器和node.js中。在服务端它使用原生 node.js的http模块, 而在客户端 (浏览端) 则使用 XMLHttpRequest。
特性
- 从浏览器创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF【跨站请求攻击】
############ 使用语法
# GET
## 方法1
axios.get('/user?ID=12345').then(res=>{})
## 方法2
axios.get('/user', {
params: {
ID: 12345
}
}).then(res=>{})
# POST
axios.post('/user', {
firstName: 'aa',
lastName: 'bb'
}).then(res=>{})
# 标准写法
axios({
method: 'post',
url: '/user/12345',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'},
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
})
# axios 全局配置
# 配置公共的请求头
axios.defaults.baseURL = 'https://api.example.com';
# 配置 超时时间 毫秒数(0 表示无超时时间)
axios.defaults.timeout = 1000;
# 配置公共的请求头
axios.defaults.headers['token'] = token;
### 拦截器
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
十三、vue工程化
1.1、介绍
Vue工程化是指在 Vue 项目中应用工程化技术,提高开发效率、代码质量、可维护性等。
Vue 工程化技术包括以下几个方面:
- 模块化:将项目拆分为多个模块,每个模块负责一个功能或业务。
- 构建工具:使用构建工具来编译、打包、压缩代码,并生成可部署的文件。
- 测试:使用单元测试、集成测试等方法来验证代码的正确性。
- 持续集成/持续部署(CI/CD):自动化代码部署流程,提高部署效率。
Vue 工程化可以为开发者,提高开发效率,完善的构建过程,模块化的文件系统,高亮的语法提示和npm工程的支持,可以让开发者专注于某个模块的开发,构建工具可以自动编译、打包、压缩代码帮助开发者快速发现和修复错误。
1.2、vue-cli创建项目
## 一定要安装此工具
npm i -g @vue/cli
## 安装成功后,检查
vue --version
# 首先需要进入到对应的目录中(英文目录不要有空格),执行如下命令
项目名称(创建时会自己以对应的项目名称生成目录)
vue create mya
1.3、vite创建项目
vue3推荐方案 create-vue
npm create vue
cd myapp
npm i
npm run dev
十四、vue组件
1.1、概述
组件 (Component) 是 Vue.js 最强大的功能之一,它是html、css、js等的一个聚合体。
组件化
- 将一个具备完整功能的项目的一部分分割多处使用
- 加快项目的进度
- 可以进行项目的复用
组件分为:全局组件 和 局部组件(单文件组件)
1.2、全局组件
app.component('组件名称', { })第1个参数是标签名称,第2个参数是一个选项对象。全局组件注册后,任何vue实例都可以用。
组件注意事项:
- 构造 Vue 实例时传入的各种选项大多数都可以在组件里使用,只有一个例外:data必须是函数,同时这个函数要求返回一个对象 ,数据唯一性
- 组件模板必须是单个根元素(html标签)
- 组件模板的内容可以是模板字符串
import {h} from 'vue'
app.component('HelloWorld', {
data: function(){
return {
msg: 'HelloWorld'
}
},
render: ()=>h('div',{}, 'hello')
});
1.3、局部组件(单文件组件)
把一个组件全部内容汇合到一个文件中,文件名字是以 .vue 结尾的就称作vue单文件组件。
在使用时,进行导入然后进行注册才可以使用
<template>
<div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
1.4、动态组件
通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换
<component v-bind:is="currentView"></component>
<script>
var vm = Vue.createApp({
el: '#root',
data: {
currentView: 'home'
},
components: {
home,
posts
}
})
</script>
- keep-alive
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
<script>
var vm = Vue.createApp({
el: '#root',
data: {
currentView: 'posts'
},
components: {
home,
posts
}
})
</script>
注:父组件没有挂载完毕之前生命周期都是先执行,只有mounted等着所有的子组件完成挂载后才执行。
十五、组件间传值
1.1、父组件向子组件传值
- 父组件以属性的形式绑定值到子组件身上
- 子组件通过使用属性props接收(props是单向数据流(只读属性):当父组件的属性变化时,将传导给子组件,但是反过来不会)
1.2、子组件向父组件传值
- 子组件用$emit()定义自定义事件,$emit()第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
- 父组件用v-on(@)绑定子组件定义的自定义事件名,监听子组件的事件,实现通信
父子间传值
通过属性可以传递任意类型,把修改的方法通过属性传给子组件,在子组件中调用方式来完成父子间通过
1.3、兄弟通信
状态提升
1.4、Ref
ref被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
this.$nextTick
# 普通dom元素上
<p ref="p">hello</p>
# 子组件上
<child-comp ref="child"></child-comp>
# 调用
this.$refs.引用名
1.5、root/parent
获取父组件对象或子组件对象集合
this.$root 获取根组件 App.vue实例
this.$parent 获取子组件的父组件实例
在vue2中还有一个 this.$children 获取父组件下面所有的子组件列表 []
1.6、provide/inject
provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
var Provider = {
provide: {
foo: 'bar'
},
// ...
}
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
// ...
}
1.7、v-model
<CustomInput
:model-value="searchText"
@update:model-value="newValue => searchText = newValue"
/>
<CustomInput v-model="searchText" />
<!-- CustomInput.vue -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
## v-model参数
<MyComponent v-model:title="bookTitle" />
<!-- MyComponent.vue -->
<script>
export default {
props: ['title'],
emits: ['update:title']
}
</script>
<template>
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>
1.8、$attrs
获取所有的剩余属性,它只接受没有定义在props配置中的属性,在vue3中它还可以接受class和style属性,在vue2中不可以。
十六、组件插槽
组件的最大特性就是复用性,而用好插槽能大大提高组件的可复用能力
1.1、单个插槽
当子组件模板只有一个没有属性的插槽时,父组件传入的整个内容片段将插入到插槽所在的 DOM 位置,并替换掉插槽标签本身。
# 子组件
<div>
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。默认值
</slot>
</div>
# 父组件
<div>
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
</div>
1.2、具名插槽
有时我们需要多个插槽,来完成对应的数据自定义显示。
一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
自2.6.0 起有所更新。已废弃的使用 slot
# 子组件
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
</div>
# 父组件
<app-layout>
// 老写法
<h1 slot="header">这里可能是一个页面标题</h1>
// 新写法
// v-slot 只能添加在 <template> 上
// 简写 v-slot:header == #header
<template v-slot:header>
<h1>这里可能是一个页面标题</h1>
</template>
<p>主要内容的一个段落。</p>
</app-layout>
1.3、作用域插槽
作用域插槽是一种特殊类型的插槽,用作一个 (能被传递数据的)可重用模板,来代替已经渲染好的元素。在子组件中,只需将数据传递到插槽,就像你将 prop 传递给组件一样
# 子组件中
Vue.component('child', {
template: `
<div class="child">
<slot name="default" text="我是子组件中的内容"></slot>
</div>
`
})
# 父组件中
<div class="parent">
<child>
// 老写法
<div name="default" slot-scope="props">
<div>父组件</div>
<h3>{{ props.text }}</h3>
</div>
// 新写法
<template #default="props"
<div>
<div>父组件</div>
<h3>{{ props.text }}</h3>
</div>
</child>
</div>