vue3特性笔记

我们把vue3 和 vue2 的项目进行对比来去说明

main.js

通过 按需导入的 createApp 方法来来构建 vue 实例
通过 vue实例.use 方法来挂载插件(router、vuex)
没有了 Vue 构造方法,无法再挂载原型

App.vue

组件内部结构无变化,依然是
tempalte
script
style
<template> 标签中支持多个根标签

store/index.js

通过 按需导入的 createStore 方法来来构建 store 实例
无需再通过 Vue.use(Vuex) 的形式进行挂载

router/index.js

通过 按需导入的 createRouter 方法来构建 router 实例
通过 按需导入的 createWebHashHistory 方法来创建 hash 模式对象,进行路由模式指定
无需再通过 Vue.use(VueRouter) 的形式进行挂载
routes 路由表的定义无差别

综上所述,在 vue3 的初始化项目中,与 vue2 对比的最大差异其实就是两点:

1、vue3 使用 按需导入的形式 进行初始化操作
2、<template> 标签中支持多个根标签


vue3新语法

setup 与 reactive

setup 函数也是 Composition API 的入口函数,我们的变量、方法都是在该函数里定义的,不再使用vue2中的data而是setup。
reactive 方法是用来创建一个响应式的数据对象,该API也很好地解决了Vue2通过 defineProperty 实现数据响应式的缺陷

//app.vue
<template>
 <div id="app"> 
   <p>{{ state.name }}</p>
 </div>
</template>
<script lang="ts">
import {
 defineComponent, 
 reactive, 
} from 'vue' 

export default defineComponent({
 name: 'App', 
 setup(props, { slots, attrs, emit }) {
   //let name = 'abc'  //return的name 是abc,因为setInterval()是异步的

   //reactive的name就会是aaa1111,每2秒变化一次
   const state = reactive({
     name: 'aaa',
   })
   setInterval(() => {
     state.name += '1' 
   }, 2000)   
   
   //不能...state,因为...是提取值,那显示的就不是reactive对象了
   return {
     state 
   }
 },
})
</script>

上面使用name必须state.name,不方便,另一个解决办法如下

export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}

访问组件的 property

执行 setup 时,组件实例尚未被创建。因此,你只能访问以下 property: props attrs slots emit

换句话说,你将无法访问以下组件选项:
data computed methods


生命周期

在Vue3中,这些生命周期部分有所变化,并且调用的方式也有所改变

Vue2 Vue3
beforeCreate setup
created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestory onBeforeUnmount
destoryed onUnmounted

Props的不同处

Ts可指定类型,而不是以往所有对象参数都是object的any类型
另外Props可以提出来

//app.vue
<template>
  <div id="app"> 
    <HelloWorld msg="v3 + TS" :age="age" :config="cfg" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import HelloWorld from './components/HelloWorld.vue' 

export default defineComponent({
  name: 'App',
  components: {
    HelloWorld,
  }, 
  data() {
    return {
      age: 24,
      cfg:{
        name:"abc"
      }
    }
  },
  
})
</script> 
//helloword组件
<template>
  <div class="hello">
   name: {{config.name}}
    age:{{ age }}
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'

interface Config{
  name:string
}

//把props提出来外面
const PropsType = {
  msg: String,
  config:{
      type:Object as PropType<Config>, 
      required:true 
  },
  age: {
    type: Number,
    required: true,
  },
} as const  //多个as const才能让props为readonly只读状态

export default defineComponent({
  name: 'HelloWorld',
  props: PropsType, 
  mounted(){
    this.age
     //有上面的 as PropType<Config>这里就是config接口类型,没有就是Record<string,any>类型
    this.config   //所有定义一个接口类型是有规范意义的
    this.config.name  //如果required不是true,那这里就会报错,因为有可能config不存在,那config.name就是未知数
  }
})
</script>

vue文件转译为js是怎样的,h函数与createVNode

import { createApp, defineComponent, h } from 'vue'
//import App from './App.vue'
import router from './router'
import HelloWorld from './components/HelloWorld.vue'
//由于eslink选择的是TS语法效验,所以出现require是会报错的;手动屏蔽一行效验
const img = require('./assets/logo.png') //eslint-disable-line
/*
创建一个组件
const App = defineComponent({
  render() {
    return 'ABC'    //此时页面就仅显示abc
  },
})
*/

/*
//app.vue默认代码
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Welcome to Vue.js" />
  </div>
</template>
*/

// h函数(标签,属性,子类)
// 以下就是转为vue文件转为JS的样式
const App = defineComponent({
  render() {
    return (
      h('div', { id: 'app' }),
      [
        h('img', {
          alt: 'Vue logo',
          src: img,
        }),
        h(HelloWorld, {
          msg: 'Welcome to Vue.js"',
        }),
      ]
    )
  },
})
createApp(App).use(router).mount('#app')

h函数只是createVNode的简单封装,所以把h函数替换为createVNode也是一样的

import { createApp, defineComponent, h, createVNode } from 'vue'


ref 与 computed 与 watchEffect

ref 就是通过 reactive 包装了一个对象 ,然后是将值传给该对象中的 value 属性,这也就解释了为什么每次访问时我们都需要加上 .value。
我们可以简单地把 ref(obj) 理解为这个样子 reactive({value: obj})

watch 和 watchEffect 都是用来监视某项数据变化从而执行指定的操作的,但用法上还是有所区别
watchEffect:
1、不需要手动传入依赖
2、每次初始化时会执行一次回调函数来自动获取依赖
3、无法获取到原值,只能得到变化后的值

<template>
  <div id="app"> 
    <p>{{ name }}</p> 
    <p>{{ name2 }}</p> 
    <p>{{ ref2 }}</p>
  </div>
</template>

<script lang="ts">
import {
  defineComponent, 
  ref,
  computed,
  watchEffect,
} from 'vue' 

export default defineComponent({
  name: 'App', 
  setup(props, { slots, attrs, emit }) { 
    //不用reactive,而用ref
    const nameRef = ref('ax:')
    const ref2 = ref("bx:")

    setInterval(() => { 
      nameRef.value += 'a'
    }, 2000)

    setInterval(() => { 
      ref2.value += 'b'
    }, 2000)

    //插一脚,演示下计算属性
    const computedNameRef = computed(() => {
      return nameRef.value + '2'
    })

    //只会监听内部用到的ref,如ref2没用到,所以就不会打印ref2
    watchEffect(() => {
      console.log("watch:",nameRef.value)
    })

    //这样就可以直接name了
    return {
      name: nameRef,
      name2: computedNameRef,
      ref2
    }
  }, 
  created(){
    console.log("created:",this.name)  //这里的this.name仍然是ref,而不是值。因为编译时自动name.value了
  }
})
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容