文章目录
一.Vue介绍
1.什么是Vue
Vue是一套用于构建用户界面的前端框架
- 构建用户界面:往html中填充数据,方便。
- 框架:一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务能力。
学习vue就是学习vue框架中规定的用法
2.vue的特性
(1).数据驱动视图
在使用vue的页面中,vue会监听数据的变化,从而自动重新渲染页面的结构
- 好处:不需要再在代码中频繁地去操作dom
(2).双向数据绑定
简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化。
- 好处:开发者不再需要用手动操作DOM元素,来获取表单元素的最新值。
注意:Vue的两个特性的底层原理是MVVM(Mode数据源、View视图、ViewModel即Vue的实例)
二.vue3.0的基本使用
创建方法:
1.使用命令行工具vue-cli 创建
Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。
对于 Vue 3,你应该使用 npm 上可用的 Vue CLI v4.5 作为 @vue/cli,可以用以下命令查看@vue/cli版本:
vue --version
使用以下命令安装或者升级你的@vue/cli
npm install -g @vue/cli
创建一个新的项目projectName
vue create projectName
传送到项目目录下:
cd projectName
启动项目:
npm run serve
2.使用 vite 创建
Vite 是一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。
以下命令创建名为projectName的工程:
# npm 6.x版本
$ npm init vite@latest projectName --template vue
# npm 7+版本,需要加上额外的双短横线
$ npm init vite@latest projecName -- --template vue
然后进入工程目录:
cd projecName
然后安装依赖:
npm install
然后运行项目
npm run dev
三.组合式 API
1.setup组件选项
新的 setup
选项在组件创建之前执行,一旦 props
被解析,就将作为组合式 API 的入口
- 组件中所用到的:数据、方法等等,均要配置在setup中。
- setup函数的两种返回值:
- 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
- 若返回一个渲染函数:则可以自定义渲染内容。(了解)
需要注意的点:
- setup执行的时机
- 在beforeCreate之前执行一次,this是undefined。
- setup的两个参数
- props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
- context:上下文对象
- attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于
this.$attrs
。 - slots: 收到的插槽内容, 相当于
this.$slots
。 - emit: 分发自定义事件的函数, 相当于
this.$emit
。
- attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于
四.响应性API
1.带 ref 的响应式变量
ref
函数可以使任何响应式变量在任何地方起作用
使用前需要引入,创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。语法:
import { ref } from 'vue'
const xxx = ref(initValue)
ref 接收参数并将其包裹在一个带有 value
property 的对象中返回,然后可以使用该 property 访问或更改响应式变量的值,例:
<template>
<h1>一数字</h1>
<h2>大小:{{num}}</h2>
<button @click="changeInfo">加一</button>
</template>
<script>
import {ref} from 'vue'
export default {
setup(){
let num=ref(0)
function changeInfo(){
num.value++
}
return{
num,
changeInfo
}
}
}
</script>
例子中点击按钮响应式改变数值的大小
注意:
- 模板中读取数据: 不需要.value,直接:
<div>{{xxx}}</div>
- 接收的数据可以是:基本类型、也可以是对象类型。
- 基本类型的数据:响应式依然是靠
Object.defineProperty()
的get
与set
完成的。 - 对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数——
reactive
函数。
将值封装在一个对象中,看似没有必要,但为了保持 JavaScript 中不同数据类型的行为统一,这是必须的。
2.reactive函数
与ref()类似,但reactive函数定义的是一个对象类型的响应式数据(基本类型不要用它,要用ref
函数)
语法:const 代理对象= reactive(源对象)
接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
注意:
- reactive定义的响应式数据是“深层次的”。
- reactive 将解包所有深层的 refs,同时维持 ref 的响应性。
例:
const count = ref(1)
const obj = reactive({ count })
// ref 会被解包
console.log(obj.count === count.value) // true
// 它会更新 `obj.count`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2
// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3
3.reactive与ref的对比
- 从定义数据角度对比:
- ref用来定义:基本类型数据
- reactive用来定义:对象(或数组)类型数据、
- 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过
reactive
转为代理对象。
- 从原理角度对比:
- ref通过
Object.defineProperty()
的get
与set
来实现响应式(数据劫持)。 - reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
- ref通过
- 从使用角度对比:
- ref定义的数据:操作数据需要
.value
,读取数据时模板中直接读取不需要.value
。 - reactive定义的数据:操作数据与读取数据:均不需要
.value
。
- ref定义的数据:操作数据需要
4.computed
接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式ref
对象。或者,接受一个具有 get
和set
函数的对象,用来创建可写的 ref
对象。
例:
<template>
前部分:<input type="text" v-model="abc.head">
<br>
后部分:<input type="text" v-model="abc.tail">
<br>
结果:
<input type="text" v-model="abc.result">
</template>
<script>
import {reactive,computed} from 'vue'
export default {
name: 'App',
setup(){
let abc=reactive({
head:'qian',
tail:'hou'
})
//计算属性,完整的写法(考虑了读和写)
//传入一个具有 get 和 set 函数的对象
abc.result=computed({
get(){
return abc.head+'-'+abc.tail
},
set(value){
const abcArr = value.split('-')
abc.head=abcArr[0]
abc.tail=abcArr[1]
}
})
return{
abc
}
}
}
</script>
在例子中,两个输入与结果的输入输出绑定,修改两个输入的值会修改结果的值。而修改结果的值也会同步两个输入的值。
5.watch函数
watch
需要侦听特定的数据源,并在回调函数中执行副作用。
语法:
watch(WatcherSource, Callback, [WatchOptions])
共有三个参数:
- WatcherSource: 用于指定要侦听的响应式变量。WatcherSource可传入ref响应式数据,reactive响应式对象要写成函数的形式。
- Callback: 执行的回调函数,可依次接收当前值newValue,先前值oldValue作为入参。
- WatchOptions:支持 deep、immediate。当需要对响应式对象进行深度监听时,设置deep: true;默认情况下watch是惰性的,当我们设置immediate: true时,watch会在初始化时立即执行回调函数。
使用场景:
- 监听单个数据
<template>
<h2>当前和为:{{sum}}</h2>
<button @click="sum++">点击值+1</button>
</template>
<script>
import {ref,watch} from 'vue'
export default {
name: 'App',
setup(){
let sum=ref(0)
//情况一:监视ref所定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log('sum的值改变了',newValue,oldValue)
})
return{
sum
}
}
}
</script>
- 监听多个数据源
<template>
<h2>当前和为:{{sum}}</h2>
<button @click="sum++">点击值+1</button>
<h2>{{msg}}</h2>
<button @click="msg+='!'">修改</button>
</template>
<script>
import {ref,watch} from 'vue'
export default {
name: 'App',
setup(){
let sum=ref(0)
let msg=ref("Hello world!")
//情况二:监视ref所定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log('sum的值改变了',newValue,oldValue)
},{immediate:true})
//immediate:true的作用是初始化时执行回调
return{
sum,
msg
}
}
}
</script>
- 监听reactive对象
<template>
<h2>当前和为:{{sum}}</h2>
<button @click="sum++">点击值+1</button>
<hr>
<h2>{{msg}}</h2>
<button @click="msg+='!'">修改</button>
<hr>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">年龄增长</button>
</template>
<script>
import {ref,watch,reactive} from 'vue'
export default {
name: 'App',
setup(){
let sum=ref(0)
let msg=ref("Hello world!")
let person=reactive({
name:'张三',
age:18
})
//情况三:监视reactive对象
watch(person,(newValue,oldValue)=>{
//注意此处无法正确获取oldValue的值,oldVlaue的值和newValue的值一样
console.log('个人信息的值改变了',newValue,oldValue)
},{immediate:true})
return{
sum,
msg,
person
}
}
}
</script>
- 监视reactive对象中的某一个属性
监视某个属性要用用一个函数的返回值,如:()=>
//情况四:监视reactive对象中的某一个属性
watch(()=>person.age,(newValue,oldValue)=>{
console.log('个人年龄的值改变了',newValue,oldValue)
})
注意:当要监视reactive中的某些属性时用到数组,如:[()=>person.age,()=>person.name]
- 监视ref创建的对象
共有两种方法:
- 根据ref对象的定义,用xxx.value
- 在参数使用
deep:true
<template>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">年龄增长</button>
</template>
<script>
import {ref,watch,reactive} from 'vue'
export default {
name: 'App',
setup(){
let msg=ref("Hello world!")
let person=ref({
name:'张三',
age:18
})
//方法一
watch(person.value,(newValue,oldValue)=>{
console.log('个人信息的值改变了',newValue,oldValue)
})
//方法二
watch(person,(newValue,oldValue)=>{
console.log('个人信息的值改变了',newValue,oldValue)
},{deep:true})
return{
person
}
}
}
</script>
- watch()函数总结
两个小坑:
- 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时:deep配置有效。
6.watchEffect函数
立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。即不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。例:
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> logs 0
setTimeout(() => {
count.value++
// -> logs 1
}, 100)
7.watchEffect与computed的对比
- computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。