Vue学习八:vue3
一、vue3创建项目与介绍
vue3创建项目与vue2使用vue-cli(基于webpack)脚手架不同,vue3使用create-vue(基于vite,更快)。创建项目的指令如下,首先看一下node的版本(node -v),16以上才支持。第一次创建项目会去下载create-vue比较慢(下载是下载到缓存里面的会被清掉),等一会就好了。
npm init vue@latest
然后关掉命令行,重新打开cd到自己需要创建项目的路径,再使用上面的命令创建项目。
然后按照上面三条指令进入到项目中,下载依赖,启动项目。
pnpm也是包管理工具可以用来创建vue3项目,更快更节省空间,相关指令如下。pnpm如果需要更新的话,继续使用下面的npm安装命令。pnpm用不了nodejs里面设置的全局变量,npm能用,使用pnpm更新的话会比较麻烦。
npm install pnpm -g 安装pnpm
pnpm create vue 创建项目
pnpm install 安装依赖
pnpm dev 运行项目
vue3的优势
更容易维护
1 .组合式API
2.更好的TypeScript支持
更快的速度
1.重写diff算法
2.模版编译优化
3.更高效的组件初始化
更小的体积
1.良好的TreeShaking
2.按需引入
更优的数据响应式
Proxy
组合式API个人理解,对于一个数据vue2中将其拆分到不同的部分处理,如data、methods、computed等,这样数据少还容易维护,一旦数据过多就难以维护了。vue3则不同,将一个数据的所有操作都放在一起,这样数据多了也不用怕了。
Vue3项目的关键文件
1. vite.config.js -项目的配置文件基于vite的配置
2. package.json -项目包文件核心依赖项变成了Vue3.x 和vite
3. main.js-入口文件createApp函数创建应用实例
4. app.vue -根组件SFC单文件组件script - template - style
变化- -:脚本script和模板template顺序调整
变化二:模板template不再要求唯一根元素
变化三:脚本script添加setup标识支持组合式API
5. index.html-单页入口提供id为app的挂载点
二、组合式API(一些函数)
setup
1.执行时机,比beforeCreate还要早
2.setup函数中,获取不到this(this是undefined )
3.数据和函数,需要在setup最后return, 才能模板中应用
//原始复杂写法 <script> export default{ setup() { const message = 'hello world' const logMessage = () => { console.log(message) } return { message, logMessage } } } </script> //语法糖写法 <script setup> const message = 'hello world' const logMessage = () => { console.log(message) } </script>
reactive和ref函数
vue3中默认数据不是响应式的,vue2是响应式的,数据变化,视图自然更新,因此vue3中的数据如果想要是响应式的就可以使用上面两个函数。(响应式的好处,如果前端需要修改后端某个数据,在这个事件触发修改后面重新获取数据,这样就能更新局部dom元素,不用重新加载整个页面;视图更新,数据变化的好处就是,我们获取更新的数据不需要再用函数去获取视图中的值,直接拿就行了;数据双向绑定需要看绑定的视图在哪个地方,有可能在根组件,也可能在子组件,这样因为单向数据流那么绑定的方式就不同了)
reactive()
作用:接受对象类型数据的参数传入并返回-一个响应式的对象
1.从vue包中导入reactive函数
2.在< script setup>中执行reactive函数并传入类型为对象的初始值,并使用变量接收返回值
用法如下,点击按钮给一个对象中一个数加一
<script setup> import { reactive } from 'vue' const state = reactive({ count:100 }) const setCount = () => { state.count++ } </script> <template> <div class="box"> {{state.count}} </div> <button @click="setCount">+1</button> </template> <style scoped> .box{ width:50px; height: 50px; border: 1px solid black; } </style>
ref()
作用:接收简单类型或复杂类型,返回一个响应式的对象
本质:是在原有传入数据的基础上,外层包了一层对象,包成了复杂类型
底层:包成复杂类型之后,再借助reactive 实现的响应式
注意点:
1.脚本中访问数据,需要通过. value
2.在template中, .value不需要加(帮我们扒了一层)
<script setup> import { ref } from 'vue' const state = ref(0) console.log(state.value) </script> <template> <div class="box"> {{state}} </div> </template>
computed计算属性函数
计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法
核心步骤:
1.导入computed函数
2.执行函数在回调参数中return基于响应式数据做计算的值,用变量接收
demo如下:获取列表中大于2的元素
<script setup> import { computed,ref } from 'vue' const list = ref([1,2,3,4,5,6,7,8,9]) const computedList = computed(() => { return list.value.filter(item => item > 2) }) </script> <template> <div class="box"> {{list}} {{computedList}} </div> </template> <style scoped> .box{ width:400px; height: 20px; border: 1px solid black; } </style>
watch函数
作用:侦听一个或者多个数据的变化,数据变化时执行回调函数
俩个额外参数: 1. immediate ( 立即执行) 2. deep ( 深度侦听)
基础使用-侦听单个数据
1.导入watch函数
2.执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
immediate
说明:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调
deep深度监视,默认watch 进行的是浅层监视
const ref1 = ref(简单类型)可以直接监视
constref2=ref(复杂类型)监视不到复杂类型内部数据的变化
watch(ref对象,(newValue,oldValue) => {...},{immediate: ,deep: })
三、生命周期函数
关于vue2和vue3中生命周期函数的对应关系见下图和下demo
<script setup> import { onMounted } from 'vue' //beforeCreate和created钩子里面的代码放在setup里面直接声明再执行即可 const getList = () => { console.log('发送请求,获取数据') } getList() //如果有些代码需要在mounted生命周期中执行 onMounted(() => { console.log('mounted生命周期函数 - 逻辑1') }) //写成函数调用的方式,可以调用多次,并不会冲突,而是按照顺序执行 onMounted(() => { console.log('mounted生命周期函数 - 逻辑1') }) </script> <template> <div class="box"> </div> </template> <style scoped> .box{ width:400px; height: 20px; border: 1px solid black; } </style>
四、父子通信
组合式API下的父传子
基本思想
1.父组件中给子组件绑定属性
2.子组件内部通过props选项接收
组合式API下的子传父
基本思想
1.父组件中给子组件标签通过@绑定事件
2.子组件内部通过emit方法触发事件
demo如下:父传子,子传父
父组件
<script setup> import {ref} from 'vue' //局部组件导入即用,不用注册了 import Son1Com from '@/components/Son1Com.vue' const money = ref(100) const changeFn = () => { money.value -= 20 } </script> <template> <div class="box"> <!--给子组件,以添加属性的方式传值--> <Son1Com @changeMoney='changeFn' message='天生我才必有用' :money='money'></Son1Com> </div> </template> <style scoped> .box{ width:400px; height: 20px; border: 1px solid black; } </style>
子组件
<script setup> const props = defineProps({ message:String, money:Number }) console.log(props.message) const emit = defineEmits(['changeMoney']) const buy = () =>{ //需要emit触发的事件 emit('changeMoney',5) } </script> <template> <!--props传来的数据,模块中可以直接用--> <div> {{message}}-{{money}} <button @click="buy">花钱</button> </div> </template> <style> </style>
provide和inject
可以从上往下跨层传递普通数据、响应式数据和函数,语法如下。
//父组件,key为变量名,value可以是普通数据、响应式数据和函数
import {provide} from 'vue'
provide(key,value)
//子组件
import {inject} from 'vue'
const key = inject(key)
五、模板引用
使用
1.调用ref函数生成一个ref对象
2.通过ref标识绑定ref对象到标签
3.通过ref对象.value即可访问到绑定的元素(必须渲染完成后,才能拿到)
<script setup> import {ref,onMounted} from 'vue' const pRef = ref(null) onMounted(() => { console.log(pRef.value) }) </script> <template> <div class="box"> <p ref="pRef">阿龙学前端</p> </div> </template>
defineExpose()
默认情况下在<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问
六、新特性
Vue3.3新特性-defineOptions
Vue 3.3中新引入了defineOptions 宏。顾名思义,主要是用来定义Options API的选项。可以用defineOptions定义任意的选项,props, emits, expose, slots除外( 因为这些可以使用defineXXX来做到)
Vue3中的v-model和defineModel
在Vue3中,自定义组件上使用v - model,相当于传递一个modelValue属性,同时触发update :modelValue事件
七、pinia
pinia是vue最新的状态管理工具,是vuex的替代品
具体使用看官网:https://pinia.vuejs.org/zh/
持久化到本地的pinia插件地址:https://prazdevs.github.io/pinia-plugin-persistedstate/guide/config.html