vue3
-
2020年9月18日发布,但是大多数公司还未使用。
-
2022年2月7日成为默认版本。
-
vue2配合的是vuex3和vue-router3使用。
-
vue3配合的是vuex4和vue-router4使用。
vue3优点:
-
首次渲染更快
-
diff算法更快
-
内存占用更少
-
打包体积更小
-
更好的Typescript支持(Typescript是js的升级版)
-
Composition API 组合 API(方法,工具函数)
回顾vue2、webpack
vue2通过vue/cli 也是webpack创建的,他提供了devServer开发服务器,但是会把所有代码打包再放到devServer,才能看到网页,所以项目越大启动时间越长。
webpack是打包,所有代码不管用不用都打包,让放到devServer开发服务器。
vite
-
vite的原理:利用原生ESM方法提供源码,实际上是让浏览器接管了打包程序的部分工作。
-
vite只需要在浏览器请求源码时进行转换并 按需提供源码。
-
根据情境动态带入代码,即只在当前屏幕上实际使用时才会被处理。
创建vue3
创建vue2 ,要全局安装:npm i @vue/cli -g ,再创建项目:vue create 项目名
创建vue3项目 :
yarn create vite 或 npm create vite@latest
-
填写项目名-----选择vue------选择JavaScript / TypeScript
-
安装时可能会有node版本的问题,直接通过切换版本https://www.jb51.net/article/259681.htm#_lab2_0_1
安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash 常用nvm命令 # 安装指定node版本 nvm install v14.15.0 # 运行指定node版本 nvm use v14.15.0 # 切换到最新的node版本 nvm use node # 远程服务器上所有的可用版本 nvm ls-remote # 给不同的版本号设置别名 nvm alias node_cms 14.15.0 # 使用该别名 nvm use node_cms # 查看已安装node列表 nvm ls
vue2和vue3区别
插件不同
-
vue2的vetur插件需要禁用,vue3用的volar插件需要安装。
组件一个根节点非必需
-
template中可以多个节点
<template>
<div>节点1</div>
<div>节点2</div>
</template>
创建应用挂载到根容器
-
在main.js中写法的区别
-
*vue2写法:导入Vue和App.vue 挂载到唯一的App组件上
import Vue from 'vue'
import App from './App.vue'
new Vue({render:h=>h(App)}).$mount('#app')
-
vue3中依然是创建vue实例,将App根组件渲染至App盒子中
vue3中会大量使用函数调用的方法来创建实例或完成功能
import { createApp } from 'vue'//类似于之前的new Vue()
import './style.css'
import App from './App.vue'
const app = createApp(App)//得到vue的应用实例
app.mount('#app')//渲染到app盒子中
入口页面,ESM 加载资源
-
---- index.html
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
组件中写法差别
只有script中的写法不同,template结构语法完全一致
vue3中基本是函数的调用
API差别
先定义数据,再使用数据
选项式api options API
-
vue2是典型的options API 选项式api
-
优点:对新手友好,属性方法等放到对应的选项里面
-
缺点:相关功能逻辑代码 被割裂了 不好维护
export default{ data(){ return{} }, methods:{}, watch:{}, components:{}, computed:{} }
-
组合式api composition API
-
vue3是典型的composition API 组合式api 需要什么功能,就直接调用某个封装好的函数即可。
-
但是vue3兼容所有vue2的写法
-
所有逻辑在setup函数中,使用 ref、watch 等函数组织代码是
组合式API
写法 -
优点:将某个功能相关的代码 组织在一起 好维护
reactive() ref() computed() watch()
-
setup函数
-
相当于钩子函数----触发时机比vue2中的beforeCreate还早,在组件创建之前的钩子。
-
也是组合式api的入口,所有组合式api代码都写在这个函数中
-
setup函数this不是组件实例,是undefined -----vue3中也不需要this
-
如果数据或函数在模板中使用,需要在setup返回
(react标准的是class,因为this等不好用的问题,衍生了hooks,而vue3就学了创了组合式API )
vue2和vue3都是数据驱动视图!这个数据得是响应式的数据
-
vue2中是写在data函数中的 Object.defineProperty()
-
vue3中数据响应式 Proxy响应式 reactive() ref()
Proxy响应式
reactive()
-
reactive针对复杂数据(不能转换简单) 变响应式
-
把数据放到reactive() 中,会被Proxy变为响应式
复杂数据 <script setup> const obj = reactive({ age:18, name:'zs' }) const ageAdd = () => { obj.age++} </script>
ref()
-
ref将任何数据 变响应式(不限类型)
-
把数据放到ref() 中,会被Proxy变为响应式
-
注意点:
-
ref可以将任何数据都变为响应式,但是在script中需要通过.vlaue来返回结果
-
在模板中不需要.value ===>因为内部底层已经自动解套了一层
简单数据 <div>{{count}}</div> <button @click="addOne">+1</button> setup(){ let count = ref(99) const addOne = () => { count.value++} return{count,addOne} }, 复杂数据类型 <button @click="ageAdd">过了一年{{obj.age}}</button> <script setup> const obj = ref({ age:18, name:'zs'}) const ageAdd = () => { obj.value.age++} </script>
-
总结
1、只要明确是复杂类型也知道准确字段就用reactive(),其他用ref()
2、都用ref()
setup语法糖
setup语法糖:简化方式
将export default{}省略,setup(){}省略,return{}省略
<script setup>// setup语法糖:简化方式
const count = 99
const money = 90
</script>
computed函数
计算属性语法:
computed(()=>{return 值}) return的就是结果
<script setup>
const list=ref([100,98,77,64,43,23,88,95])
//计算属性语法
const goodList = computed(()=>{
return list.value.filter(item=>item>90)})
</script>
watch函数
5种情况:
使用 watch
监听一个响应式数据
使用 watch
监听多个响应式数据
使用 watch
监听响应式对象数据中的一个属性(简单)
使用 watch
监听 响应式对象数据中的一个属性(复杂),配置深度监听
使用 watch
监听 ,配置默认执行
1、监听一个数据
watch(监视数据,回调函数)
watch(count,(newV,oldV)=>{
console.log('你变了',newV,oldV)})
2、监听多个数据
watch([数据1,数据2...],回调函数) 同时监视
watch([count,fn],()=>{
console.log('你变了',count,fn)})
3、监听对象中一个属性(简单)
watch(()=>数据, 改变后回调函数)
watch(()=>user.name,()=>{
console.log('改名字')})
4、监听响应式对象数据中的一个属性(复杂)
watch(()=>数据, 改变后回调函数, {deep: true})
watch(()=>user.info,()=>{
console.log('info变了')
},{deep:true})
5、监听并立即执行
watch(..,..,{deep: true,immediate:true})
watch(()=>user.info,()=>{
console.log('info变了')
},{deep:true,immediate:true})
vue3生命周期函数
选项式API下的生命周期函数使用 | 组合式API下的生命周期函数使用 |
---|---|
beforeCreate | 不需要(直接写到setup函数中) |
created | 不需要(直接写到setup函数中) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroyed | onBeforeUnmount |
destroyed | onUnmounted |
activated | onActivated |
deactivated | onDeactivated |
-
常用的发请求,直接写在setup中
-
常用的
onMounted
组件渲染完毕:发请求,操作dom,初始化图表... onMounted(()=>{}) -
每个钩子都可以多次调用,目的为了拆分逻辑,让不同的代码用单独的钩子,避免相同逻辑的代码拆分。
其他方法
ref操作
ref 获取dom对象
-
创建ref对象
-
将inpRef对象与dom关联 inpRef.value=dom
-
在合适的时机获取dom
<script setup>
const inpRef = ref(null)//inpRef.value
onMounted(()=>{
console.log(inpRef.value)
inpRef.value.value=123
})</script>
<input type="text" ref="inpRef">
ref操作组件
-
导入组件(不用注册),使用组件, 创建ref对象 ,关联ref
-
组件向外暴露数据 defineExpose({xx,xxx})
-
获取组件上的属性/方法
<script setup> import Jack from './components/jack.vue' // 引入组件,组件不需要注册 import { ref } from 'vue'; const jackRef = ref(null) const fn = ()=>{ console.log(jackRef.value.car) jackRef.value.fn()} </script> <Jack ref="jackRef"></Jack> jack.vue中 const money = ref(100)... defineExpose({ money,car,fn })//向外暴露数据 函数的一个方法 // 只有向外暴露了,这个数据才能被外界访问
父子通信
父传子
通过defineProps({...})接收
子组件 --- 通过defineProps({...})接收,正常使用
// 如果接收到的props只在模板中使用,不用通过变量接收返回值
defineProps({
// 接收props
money:{
type:Number,
default:100 },
car:String
})
父组件 --- 导入child,正常写数据,传数据给子组件
<child :money="money" :car="car"></child>
子传父
通过 defineEmits(['xx','xxx']) 传递
子组件
-
如果props数据需要在script中使用,必须通过变量接收
-
想要子传父 必须获取到emit方法
-
注意:触发的自定义事件名 必须显示指定的defineEmits 数组参数中
子组件 --- defineEmits(['xx','xxx']) 传递
const obj = defineProps({money:Number})
const emit =defineEmits(['changeMoney','xx'])
const pay = ()=>{// 触发一个自定义事件
emit('changeMoney',obj.money-10)}
父组件 --- 通过自定义事件名注册事件
<child @changeMoney="fn"></child>
const fn = (num)=>{money.value=num}
依赖注入:解决跨组件通信
1.找父组件 通过provide 提供数据 / 函数
语法:provide('属性名',值)
通过provide提供的数据是属于app.vue组件的所有后代组件的!!!
2.后代组件如何使用数据 语法: inject('属性名') //注入
父组件:
const money = ref(100)
provide('money',money)
provide('car','奥迪')
//以下函数是组件通信,后代组件修改父组件变量的
provide('updateMoney',()=>{money.value+=10})
子组件
const money = inject('money')
const car = inject('car')
const updateMoney = inject('updateMoney')
<div>我是孙组件child2 {{money}} {{car}}</div>
<button @click="updateMoney">加钱+10</button>