在vue官网发布3.x之前,小编前端时间正好学了react基础。当学vue3.x的时候,发现好多新特性都是借鉴react的hooks特性,这也对学习vue3.x的更容易一些。所以小编推荐有时间看看react,对你的学习vue3.x的学习也会更容易一些呦~
言归正传:vue3.x新特性
- 底层使用Typescript
- 响应式底层从 Object.defineProperty 变成 Proxy
- hooks---参照react
重点来啦:vue2.x & vue3.0语法差异分析
template,style----机会没有什么差异
script的vue2.x和vue3.x的对比
## data
vue2.x
data() { return {} }
实现响应式
- 定义在data中
- 使用Vue.set实现响应式
vue3.x
import { reactive } from 'vue'
setup (props) {
const state = reactive({
title: 'Hello Vue3.0'
})
return state
}
实现响应式
- 从vue包中导入 toRefs 函数,导出state的时候,进行包裹。代码如下
setup (props) {
const state = reactive({
title: 'Hello Vue3.0'
})
return { ...toRefs(state), xxx }
}
## methods
vue2.x
methods: { 方法 }
vue3.x
- 写在setup函数中,并且要return返回方法名称
- 记得要把返回的state数据,通过toRefs变成响应式的数据,否则不会起作用。代码如下
return {
...toRefs(state),
play
}
## computed
vue2.x
computed: {计算属性}
vue3.x
- 写在setup函数中。代码如下
const getDoubleNum = computed(() => state.num * 2)
- 写在state中
const state = reactive({
myName: computed(() => 'my name is HuangWei --- vue3.x')
})
注意:需要从vue包中导入 computed 函数,如果是写在setup函数中,最后return的时候,返回计算属性函数
## 生命周期函数
vue2.x
created、mounted、beforeDestory、Destoryed ... 和 data同级
vue3.x
写在setup函数中,onCreated、onMounted、onBeforeUnmount、onUnmounted ...
对比
beforeCreate-> 使用 setup()
created-> 使用setup()
beforeMount -> onBeforeMount
Mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestory ->onBeforeDestory
destoryed -> onDestoryed
## 组件传值
vue2.x
父传子:props
子传父:this.$emit
兄弟组件传值: 公共bus,父组件作为中间件
vue3.x
父传子(爷孙传,多级之间可传值)
父组件:provide---provide('名字',值)
子组件:inject----inject('名字')
代码如下:
父组件:
<template>
<div>
<Son />
</div>
</template>
<script>
// 引入子组件
import Son from '@/components/Son'
// 引入vue函数
import {reactive,provide} from 'vue'
export default{
components:{Son},
setup(){
const state = reactive({
title: '你好'
})
provide('title',title)
return {state}
}
}
</sctipt>
子组件:
<template>
<div>
{
{title}}
</div>
</template>
<script>
// 引入vue函数
import {reactive,inject} from 'vue'
export default{
setup(){
const state = reactive({
title: inject('title')
})
return {state}
}
}
</sctipt>
注意:都要写在 setup 函数中
## 路由
vue2.x
导入vue、vue-router,然后Vue.use(VueRouter),通过 new VueRouter() 创建路由对象,里面用routes设置路由规则,最终导出
vue3.x
- 从vue包中,按需导入 createRouter 函数,通过 createRouter创建路由对象,里面用routes设置路由规则,最终导出
- 编程式导航 & 路由参数获取
- 编程式导航:从 vue-router 包中导入 useRouter 函数,然后在setup函数中用useRouter函数创建出router对象,然后就可以调用对应的push等方法实现编程式导航了
- 路由参数获取 :从 vue-router 包中导入 useRoute 函数,然后在setup函数中用 useRoute 函数创建出route对象,然后通过route.params.xxx、route.query.xxx 就可以获取到路由参数了
代码如下:
编程式导航:
<template>
<div>
<p @Click="goToList('in_theaters')">跳转</p>
<p>{
{title}}</p>
</div>
</template>
<script>
// 引入vue函数
import {reactive} from 'vue'
// 引入路由
import {useRouter} from "vue-router";
export default{
setup(){
const state = reactive({
title: '你好vue3.x'
})
// 创建路由对象
const router = useRouter();
// 跳转到列表页面
const goToList = (type) => {
// console.log(type)
// vue2.x this.$router.push(`/list/${type}`)
router.push(`/list/${type}`);
};
return {state,goToList }
}
}
</sctipt>
接收参数
<template>
<div>
{
{title}}
</div>
</template>
<script>
// 引入vue函数
import {reactive} from 'vue'
// 引入路由
import {useRoute} from "vue-router";
export default{
setup(){
const state = reactive({
title: '你好vue3.x'
})
// 创建路由对象
const route = useRoute();
// 接收参数
console.log(route.params.type)
return {state}
}
}
</sctipt>
## vuex
vue2.x
导入vue、vuex,然后Vue.use(Vuex),通过new Vuex.Store() 创建store对象,里面有5个属性(state、getter、mutation、action、module),并且最终导出store。
vue3.x
- 从vuex包中,按需导入 createStore 函数,通过 createStore() 创建store对象,里面有5个属性(state、getter、mutation、action、module)并且最终导出store。
## 其它
注意:
- setup函数在Vue3.0是一个非常重要的函数,它的执行时机是在 beforeCreate之后 和 created之前 ,很多代码都必须写在这个函数中,如果要在组件的template中使用,那么就必须在setup中return出去
setup中的两个参数说明:
- props:用于接收父组件传递过来的值,注意:必须先在setup外面props中定义好,才能通过props.xxx拿到父组件传递过来的值
- context:上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在 vue 2.x 中需要通过 this 才能访问到,在 vue 3.x 中,它们的访问方式如下:
- 项目中vue2.x的语法和3.x的语法可以共存
- vue3.x之后,之前直接写在export default 里面的内容,现在大部分都要写在setup函数中,并且模型值、事件处理、计算属性函数要返回
- 很多用到的内容比如:reactive、toRefs、computed、onMounted 都需要从vue包中导入
================================================================
11.24
vue3.0比vue2.0快的原因
- diff方法的优化
vue2.0的虚拟dom是进行全量对比的
vue3.0增加了静态标记(PatchFlag)
在与上次虚拟节点进行对比的时候,只对比带有patch flag的节点
并且可以通过flag信息得知当前节点要对比的内容
hoistState静态提升
Vue2.0无论元素是否参与更新,每次都会重新创建,然后渲染
Vue3.0中对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可
cacheHandlers 事件监听器缓存
默认情况下onClick会被视为动态绑定,所以每次都会去追中它的变化
但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可。
ssr渲染
<template>
<div>
<p>{
{count}}<p>
<button @click="myFn"></button>
</div>
</template>
<script>
import {ref} from 'vue'
export default{
name: 'App',
// setup函数是组合API的入口函数
setup(){
// let count = 0
// 定义了一个名称叫做count变量,这个变量初始化值是0
// 这个变量发生改变之后,Vue会自动更新UI
let count = ref(0)
// 在组合API中,如果想要定义方法,不用定义到methods中,直接定义即可
function myFn(){
// alert(123)
count.value += 1;
console.log(count.value)
}
// 注意点
// 在组合api中定义的变量/方法,要想在外界使用,必须通过return{xxx}暴露出去
return {count,myFn}
}
}
</script>
<template>
<div>
<ul>
<li v-for="(stu,index) in state.stu"
:key="stu.id"
@click="remStu(index)"
>{
{stu.name}}-{
{stu.age}}</li>
</ul>
</div>
</template>
<script>
import {ref, reactive} from 'vue'
export default{
name: 'App',
setup(){
// ref函数注意点:
// ref函数只能监听简单类型的变化,不能监听复杂类型的变化(对象/数组)
/** let state = reactive({
stus: [
{id: 1,name:'zs',age:12},
{id: 2,name:'ls',age:12},
{id: 3,name:'wu',age:12},
]
})
remStu(index){
state.stus = state.stus.filter((stu,idx) => idx !== index)
}
return {state,remStu}**/
// 删除
let {state, remStu} = useRemoveStudent();
// 新增
let state2 = ({
})
return {state,remStu}
}
function useRemoveStudent(){
let state = reactive({
stus: [
{id: 1,name:'zs',age:12},
{id: 2,name:'ls',age:12},
{id: 3,name:'wu',age:12},
]
})
remStu(index){
state.stus = state.stus.filter((stu,idx) => idx !== index)
}
return {state,remStu}
}
}
</scritp>