vue2 -> vue3

451 阅读4分钟

创建实例

// createApp 会产生一个 app 实例,该实例拥有全局的可配置上下文
import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'

const app = createApp(App)
app.use(router)
app.mount("#App")

Template

// 在template中,Vue3支持多个跟标签, Vue2只支持一个根标签
<template>
  <h1>1</h1>
  <h2>2</h2>
</template>

v-model

变更

1、在自定义组件上使用 v-model 时,属性 和 事件的默认名称变了: 属性:value => modelValue 事件:input => update:modelValue

2、v-bind 的 .sync 修饰符和组件的 model 选项被去掉了,取而代之的是 v-model 的参数

新特性:

  • 支持同一组件同时设置多个 v-model
  • 支持开发者自定义 v-model 修饰符

例: 在自定义组件上使用 v-model 相当于传递了一个 modelValue 属性以及触发一个 update:modelValue 事件。 v-model = :modelValue + @update:modelValue

----// vue2.x
<div v-model="name" />
等价于: 
<div :value="name" @input="name = $event" />
  
如果需要改变 v-model 绑定的属性,则需要在自组件中添加一个 model (参考官网:自定义 v-model)
 export default {
      model: {
          prop: 'title',
          event: 'change',
      },
  }
相当于: <div :title="name" @change="name = $event" />
或者用 .sync 修饰符:
 <div :title.sync="name" />
   
----// vue3.x
<div v-model="val">
// 等价于:
<div :modelValue="val" @update:modelValue="val = $event" />

// 改变绑定的属性名
<div v-model:title="name" />
等价于:
<div :title="val" @update:title="val = $event" />

// 支持一个组件有多个 v-model
<div
  :aaa="name"
  @update:aaa="name = $event"
  :bbb="info"
  @update:bbb="info = $event"
/>

组合式api

setup() 函数

// 执行时机 在beforeCreate和created之间 (无法使用组件之内其他的东西)
用法: 
  import { computed, onMounted, ref } from 'vue'
  setup(props, context) {
// 定义变量
    const a = 1
// 定义一个 count 的响应式数据,并赋值为 0
    const count = ref(0)
// 声明函数
    const add = (a) => {
      return count.value = count.value + 1
    }
// 计算属性
    const addTwo = computed(() => {
      return count.value+2;
    });
// 生命周期
    const c = ref(null);
    onMounted(()=>{
        console.log(c);
    })
    return { 
      a, 
      b,
      count,
      add,
      addTwo
    };
  },
    
// setup 参数
参数: props, context
props: 对象,里面包含:父组件传入子组件的值.
props 是响应式的,return 时不能解构,会消除 prop 的响应性。
       如果需要结构:使用torefs()
    例: import { toRefs } from 'vue'
        setup(props) {
          const { title } = toRefs(props)
          console.log(title.value)
        }
context: 一个上下文对象: 包含: attrs(), emit(), slots()
ps: attrs 和 props 的区别:
 	1、props 要先声明才能取值,attrs 不用先声明
  2、props 声明过的属性,attrs 里不会再出现
  3、props 不包含事件,attrs 包含
  4、props 支持 string 及其以外的类型(Number,Boolean...),attrs 只有 string 类型

响应性基础 API

ref 和 reactive

ref:
// 接受一个普通类型的值并返回一个该值的响应式且可变的 ref 对象。
// ref 对象具有指向内部值的单个 property .value
import { ref } from 'vue'
setup() {
  const count = ref(0)
  console.log(count.value) // 0

  count.value++
  console.log(count.value) // 1
  return {
    count
  }
}
注意: 
在 setup 中 return 返回出去后会自动解套,即: 在模板中不需要使用.value
    例:<template>
          <div>{{ count }}</div>
       </template>

reactive:
// 接收一个对象然后返回该对象的响应式代理,// 响应式转换是“深层”的 ———— 它影响所有嵌套属性
setup() {
  data = reactive({
    age: 12,
    name: '张三'
  })
  return {
    data
  }
}
注意: return reactive对象 的时候不能解构,一旦解构,对象失去响应性
可以使用 toRef() // toRef 将对象的某个键变为响应式对象
const res = toRef(data, 'name')
return {
  res,
}
toRefs 是 toRef 的批量版本。会将传入对象的每个属性处理为 ref 的值。
例如: 
return {
  ...toRefs(data) // <div>{{ name }}</div>
}

readonly()

// 有些数据,我们要求对用户是只读的,此时可以使用 readonly() 函数,用法如下:
const obj = readonly({ text: 'hello' })
obj.text += ' world' // Set operation on key "text" failed: target is readonly. 

shallowReadonly()

// 类似于浅响应,shallowReadonly() 定义浅只读数据,深层次的对象值是可以被修改的
用法如下:
// 使用 shallowReadonly() 函数定义浅只读数据
const obj = shallowReadonly({ foo: { bar: 1 } })

obj.foo = { bar: 2 }  // warn
obj.foo.bar = 2 // OK

isReactive()

判断数据对象是否是 reactive 创建的代理

isReadonly()

用于判断数据是否是 readonly

markRaw()

标记一个对象,使其永远不会转换为代理。返回对象本身。
const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false

// 嵌套在其他响应式对象中时也可以使用
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false

watchEffect

// 立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
例: 
import { watchEffect, ref } from 'vue'
setup () {
    const a = ref(0)
    watchEffect(() => console.log(a))
    setTimeout(() => {
      a.value = 1
    }, 1000)
    return {
      a
    }
 }
/**
0
1
...
*/
// 停止
1、当 watchEffect 在组件的 setup() 函数或生命周期钩子被调用时,watchEffect会被链接到该组件的生命周期,并在组件卸载时停止。
2、watchEffect 会返回一个用于停止这个监听的函数
例:
const xx = watchEffect(() => {
  内部用到哪些属性,就自动监听哪些属性。
  /* ... */
})

// later
xx.stop()


与watch 的不同
1、 不需要指定监听的属性,会自动的收集依赖。只要属性发生改变,就执行指定的方法。
2、 watch 可以获取到新值与旧值,而 watchEffect 获取不到

watch

// vue3 中可以侦听多个数据源
watch(
[fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})

生命周期钩子:

!