快速上手 vue3
当前为vue3的基础知识点,为总结b站某视频的知识文章,在刚开始学习时自我保存在语雀,现在分享到博客。
目前找不到原视频文章地址了!!!要有兄弟看到原文地址:欢迎在下面评论!
Vue3新的特性
- Composition API(组合API)
- setup配置
- ref与reactive
- watch与watchEffect
- provide与inject
- 新的内置组件
- Fragment
- Teleport
- Suspense
- 其他改变
- 新的生命周期钩子
- data 选项应始终被声明为一个函数
- 移除keyCode支持作为 v-on 的修饰符
创建Vue3.0工程
1.使用 vue-cli 创建
官方文档:https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或者升级你的@vue/cli
npm install -g @vue/cli
## 创建
vue create vue_test
## 启动
cd vue_test
npm run serve
常用 Composition API
官方文档: https://v3.cn.vuejs.org/guide/composition-api-introduction.html
1.拉开序幕的setup
- 理解:Vue3.0中一个新的配置项,值为一个函数。
- setup是所有Composition API(组合API)“ 表演的舞台 ”。
- 组件中所用到的:数据、方法等等,均要配置在setup中。
- setup函数的两种返回值:
- 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
- 若返回一个渲染函数:则可以自定义渲染内容。(了解)
<template>
<h1>测试setup,拿数据</h1>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<button @click="sayHello">打招呼</button>
</template> <script>
// 渲染函数 要导入这个
import { h } from '@vue/runtime-core';
export default {
name: "TestSetup",
//此处只是测试setup, 不考虑响应式的问题
setup() {
//数据
let name = "张三",
age = 15;
//方法
function sayHello() {
alert(`我叫${name},我${age}岁了,你好!`);
}
//返回一个对象 (常用)
return {
name,
age,
sayHello,
};
//返回一个函数(渲染函数--了解)
// return ()=> h('h1','返回一个函数(渲染函数)')
},
};
</script> <style>
</style>
5.注意点:
- 尽量不要与Vue2.x配置混用
- Vue2.x配置(data、methos、computed...)中可以访问到setup中的属性、方法。
- 但在setup中不能访问到Vue2.x配置(data、methos、computed...)。
- 如果有重名, setup优先。
- setup不能是一个async函数,因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)
2.ref函数
- 作用: 定义一个响应式的数据
- 语法:
const xxx = ref(initValue)
- 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。
- JS中操作数据:
xxx.value
- 模板中读取数据: 不需要.value,直接:
<div>{{xxx}}</div>
- 备注:
- 接收的数据可以是:基本类型、也可以是对象类型。
- 基本类型的数据:响应式依然是靠
Object.defineProperty()
的get
与set
完成的。 - 对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数——
reactive
函数。
<template>
<h1>学习ref</h1>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<button @click="alterName">修改姓名</button>
</template> <script>
// 响应式 ref
import { ref } from '@vue/reactivity';
export default {
name: "testRef",
setup() {
//数据
let name = ref("张三"),
age = 15,
obj = ref({
type:'前端工程师',
salary:'5K'
}); //方法
function alterName() {
//成功
name.value = "修改姓名"
//对象
obj.value.type = "修改工作"
obj.value.salary = "60k"
//修改失败
age ="修改年龄"
} //返回一个对象 (常用)
return {
name,
age,
alterName,
};
},
};
</script> <style>
</style>
3.reactive函数
- 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用
ref
函数) - 语法:
const 代理对象= reactive(源对象)
接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象) - reactive定义的响应式数据是“深层次的”。
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。
<template>
<h1>学习reactive</h1>
<h3>工作:{{ obj.type }}</h3>
<h3>薪水:{{ obj.salary }}</h3>
<h3>爱好:{{ list }}</h3>
<button @click="alterName">修改姓名</button>
</template> <script>
/*
响应式
reactive 对象类型
*/
import { reactive } from "@vue/reactivity";
export default {
name: "testRef",
setup() {
//数据
let obj = reactive({
type: "前端工程师",
salary: "5K",
}),
list = reactive(['吃饭','睡觉','打豆豆']);
//方法
function alterName() {
//对象
obj.type = "修改工作";
obj.salary = "60k";
//数组
list[0] = '出去玩'
}
//返回一个对象 (常用)
return {
obj,
list,
alterName,
};
},
};
</script> <style>
</style>
4.reactive对比ref
- 从定义数据角度对比:
- ref用来定义:基本类型数据。
- reactive用来定义:对象(或数组)类型数据。
- 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过
reactive
转为代理对象。
- 从原理角度对比:
- ref通过
Object.defineProperty()
的get
与set
来实现响应式(数据劫持)。 - reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
- ref通过
- 从使用角度对比:
- ref定义的数据:操作数据需要
.value
,读取数据时模板中直接读取不需要.value
。 - reactive定义的数据:操作数据与读取数据:均不需要
.value
。
5.setup的两个注意点
- setup执行的时机
- 在beforeCreate之前执行一次,this是undefined。
- setup的参数
- props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
- context:上下文对象
- attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于
this.$attrs
。 - slots: 收到的插槽内容, 相当于
this.$slots
。 - emit: 分发自定义事件的函数, 相当于
this.$emit
。
6.组件传值,插槽,自定义事件
代码实例
//父页面
<template>
<Demo @hello="showHelloMsg" msg="你好啊" school="尚硅谷">
<template v-slot:qwe>
<span>尚硅谷</span>
</template>
<template v-slot:asd>
<span>尚硅谷</span>
</template>
</Demo>
</template> <script>
import Demo from './components/Demo'
export default {
name: 'App',
components:{Demo},
setup(){
function showHelloMsg(value){
alert(`你好啊,你触发了hello事件,我收到的参数是:${value}!`)
}
return {
showHelloMsg
}
}
}
</script> //组件
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="test">测试触发一下Demo组件的Hello事件</button>
</template> <script>
import {reactive} from 'vue'
export default {
name: 'Demo',
//接收参数
props:['msg','school'],
//声明接收 自定义事件
emits:['hello'],
//setup 的参数
setup(props,context){
// console.log('---setup---',props) //接收参数
// console.log('---setup---',context) //上下文
// console.log('---setup---',context.attrs) //相当与Vue2中的$attrs
// console.log('---setup---',context.emit) //触发自定义事件的。
console.log('---setup---',context.slots) //插槽
//数据
let person = reactive({
name:'张三',
age:18
}) //方法
function test(){
context.emit('hello',666)
} //返回一个对象(常用)
return {
person,
test
}
}
}
</script>
7.计算属性与监视
computed函数
- 与Vue2.x中computed配置功能一致
- 写法
<template>
<h1>一个人的信息</h1>
姓:<input type="text" v-model="person.firstName">
<br>
名:<input type="text" v-model="person.lastName">
<br>
<span>全名:{{person.fullName}}</span>
<br>
全名:<input type="text" v-model="person.fullName">
</template> <script>
//导入 computed 计算属性
import {reactive,computed} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let person = reactive({
firstName:'张',
lastName:'三'
})
//计算属性——简写(没有考虑计算属性被修改的情况)
/* person.fullName = computed(()=>{
return person.firstName + '-' + person.lastName
}) */ //计算属性——完整写法(考虑读和写)
person.fullName = computed({
get(){
return person.firstName + '-' + person.lastName
},
set(value){
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
}) //返回一个对象(常用)
return {
person
}
}
}
</script>
watch函数
- 与Vue2.x中watch配置功能一致
- 两个小“坑”:
- 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时:deep配置有效。
<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>
<h2>薪资:{{person.job.j1.salary}}K</h2>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template> <script>
import {ref,reactive,watch} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let sum = ref(0)
let msg = ref('你好啊')
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
}) //情况一:监视ref所定义的一个响应式数据
/* watch(sum,(newValue,oldValue)=>{
console.log('sum变了',newValue,oldValue)
},{immediate:true}) */ //情况二:监视ref所定义的多个响应式数据
/* watch([sum,msg],(newValue,oldValue)=>{
console.log('sum或msg变了',newValue,oldValue)
},{immediate:true}) */ /*
情况三:监视reactive所定义的一个响应式数据的全部属性
1.注意:此处无法正确的获取oldValue
2.注意:强制开启了深度监视(deep配置无效)
*/
/* watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{deep:false}) //此处的deep配置无效 */ //情况四:监视reactive所定义的一个响应式数据中的某个属性
/* watch(()=>person.name,(newValue,oldValue)=>{
console.log('person的name变化了',newValue,oldValue)
}) */ //情况五:监视reactive所定义的一个响应式数据中的某些属性
/* watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
console.log('person的name或age变化了',newValue,oldValue)
}) */ //特殊情况
/* watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效 */ //返回一个对象(常用)
return {
sum,
msg,
person
}
}
}
</script>
watch监视ref数据的说明
<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>
<h2>薪资:{{person.job.j1.salary}}K</h2>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template> <script>
import {ref,reactive,watch} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let sum = ref(0)
let msg = ref('你好啊')
let person = ref({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
}) console.log(person) watch(sum,(newValue,oldValue)=>{
console.log('sum的值变化了',newValue,oldValue)
}) /*
person 为 reactive 函数的对象
deep:true 需要开启深度监视 person.value 直接监视 reactive 函数的对象
可以参考上面 情况三
*/
watch(person,(newValue,oldValue)=>{
console.log('person的值变化了',newValue,oldValue)
},{deep:true}) //返回一个对象(常用)
return {
sum,
msg,
person
}
}
}
</script>
watchEffect函数
- watch的套路是:既要指明监视的属性,也要指明监视的回调。
- watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
- watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
<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>
<h2>薪资:{{person.job.j1.salary}}K</h2>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template> <script>
import {ref,reactive,watch,watchEffect} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let sum = ref(0)
let msg = ref('你好啊')
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
}) //监视watch('监视属性','回调','配置')
/* watch(sum,(newValue,oldValue)=>{
console.log('sum的值变化了',newValue,oldValue)
},{immediate:true}) */ //不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性
watchEffect(()=>{
const x1 = sum.value
const x2 = person.job.j1.salary
console.log('watchEffect所指定的回调执行了')
}) //返回一个对象(常用)
return {
sum,
msg,
person
}
}
}
</script>
8.生命周期
2.0与3.0对比
vue2 | vue3 |
|
setup()
|
|
setup()
|
|
|
|
|
|
|
|
|
|
|
|
|
代码实例
<template>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我+1</button>
</template> <script>
//导入生命周期
import {ref,onBeforeMount,onMounted,
onBeforeUpdate,onUpdated,
onBeforeUnmount,onUnmounted} from 'vue'
export default {
name: 'Demo',
setup(){
console.log('---setup---')
//数据
let sum = ref(0) //通过组合式API的形式去使用生命周期钩子 //先执行组合式 之后 配置项的形式 生命周期
onBeforeMount(()=>{
console.log('---onBeforeMount---')
})
onMounted(()=>{
console.log('---onMounted---')
})
onBeforeUpdate(()=>{
console.log('---onBeforeUpdate---')
})
onUpdated(()=>{
console.log('---onUpdated---')
})
onBeforeUnmount(()=>{
console.log('---onBeforeUnmount---')
})
onUnmounted(()=>{
console.log('---onUnmounted---')
}) //返回一个对象(常用)
return {sum}
},
//通过配置项的形式使用生命周期钩子
//先执行组合式 之后 配置项的形式 生命周期
//#region
beforeCreate() {
console.log('---beforeCreate---')
},
created() {
console.log('---created---')
},
beforeMount() {
console.log('---beforeMount---')
},
mounted() {
console.log('---mounted---')
},
beforeUpdate(){
console.log('---beforeUpdate---')
},
updated() {
console.log('---updated---')
},
beforeUnmount() {
console.log('---beforeUnmount---')
},
unmounted() {
console.log('---unmounted---')
},
//#endregion
}
</script>
快速上手 vue3的更多相关文章
- 想知道Vue3与Vue2的区别?五千字教程助你快速上手Vue3!
从Vue3发布以来,我就一直对其非常感兴趣,就一直想着将其投入公司的生产中,但是开始考虑到很多不确定性就暂时对一些很小的功能进行一些尝试:慢慢的发现组合式Api的形式非常适合开发(个人感觉),尤其是V ...
- vue3快速上手
前言 虽然Vue3肯定是未来的趋势,但还不是很成熟,实际开发中用的也不多,建议学Vue3之前先掌握Vue2,将Vue3作为未来的知识储备. Vue3快速上手 Vue3简介 2020年9月18日,Vue ...
- 十分钟快速上手NutUI
本文将会从 NutUI 初学者的使用入手,对 NutUI 做了一个快速的概述,希望能帮助新人在项目中快速上手. 文章包括以下主要内容 安装引入 NutUI NutUI 组件的使用 NutUI 主题和样 ...
- 【Python五篇慢慢弹】快速上手学python
快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...
- 快速上手Unity原生Json库
现在新版的Unity(印象中是从5.3开始)已经提供了原生的Json库,以前一直使用LitJson,研究了一下Unity用的JsonUtility工具类的使用,发现使用还挺方便的,所以打算把项目中的J ...
- [译]:Xamarin.Android开发入门——Hello,Android Multiscreen快速上手
原文链接:Hello, Android Multiscreen Quickstart. 译文链接:Hello,Android Multiscreen快速上手 本部分介绍利用Xamarin.Androi ...
- [译]:Xamarin.Android开发入门——Hello,Android快速上手
返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...
- 快速上手seajs——简单易用Seajs
快速上手seajs——简单易用Seajs 原文 http://www.cnblogs.com/xjchenhao/p/4021775.html 主题 SeaJS 简易手册 http://yslo ...
- Git版本控制Windows版快速上手
说到版本控制,之前用过VSS,SVN,Git接触不久,感觉用着还行.写篇博文给大家分享一下使用Git的小经验,让大家对Git快速上手. 说白了Git就是一个控制版本的工具,其实没想象中的那么复杂,咱在 ...
随机推荐
- Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Java中生成一个唯一值的方式
现总结几种生成一个唯一值的方式 第一种:采用nanoTime() // 理论上存在重复的可能,可以在后面再加上一个随机字符串 Random r = new Random(); for (int i = ...
- uniapp微信小程序保存base64格式图片的方法
uniapp保存base64格式图片的方法首先第一要先获取用户的权限 saveAlbum(){//获取权限保存相册 uni.getSetting({//获取用户的当前设置 success:(res)= ...
- 使用 fail2ban 保护 frp 服务
背景 我们一般会使用 fail2ban 来保护暴露到公网的提供密码登录的 ssh 连接等. 但使用 frp 穿透后所有的从外网访问都会变成 127.0.0.1 进入的,原本能用 fail2ban 保护 ...
- 2022GDUT寒训专题一I题
题目 题面 给一个长度为 N的数组,一个长为 K的滑动窗体从最左端移至最右端,你只能看到窗口中的 K 个数,每次窗体向右移动一位,如下图: 窗口位置 最小值 最大值 [1 3 -1] -3 5 3 6 ...
- 539. Minimum Time Difference
Given a list of 24-hour clock time points in "Hour:Minutes" format, find the minimum minut ...
- 运维利器-ClusterShell集群管理
在运维实战中,如果有若干台数据库服务器,想对这些服务器进行同等动作,比如查看它们当前的即时负载情况,查看它们的主机名,分发文件等等,这个时候该怎么办?一个个登陆服务器去操作,太傻帽了!写个shell去 ...
- React之react-router(connected-react-router/react-router-dom)
文档: react-router-dom官方文档:https://reacttraining.com/react-router/web/guides/quick-start connected-rea ...
- 「Celeste-B」Say Goodbye
做法一 提供一个后半部分略微不同的做法. 首先,基环旋转同构肯定是用 Burnside 那套理论求不动点来解,设 \(f(n, m)\) 为每种颜色 \(/m\) 构成 \(n\) 棵(树之间有标号) ...
- fastjson、jackson以及son-lib的使用
fastjson前言 fastJson是阿里巴巴出品的一个json序列化工具. 引入依赖 <dependency> <groupId>com.alibaba</group ...