Vue3总结

一直想总结一个vue3的博客 奈何22年一直再写react  vue3也越来越成熟 所以来总结一下

vue中文文档:Vue.js

相比于vue2 :

   1. 更好的逻辑复用 与 代码组织 (composition组合式api)
        optionsAPI(旧) => compositionAPI(新), 效果: 代码组织更方便了, 逻辑复用更方便了 非常利于维护!!

   2. 更好的类型推导 (typescript支持)
        vue3 源码用 ts 重写了, vue3 对 ts 的支持更友好了 (ts 可以让代码更加稳定, 类型检测! )

vue3新特性:

      1. 数据响应式原理重新实现 (ES6 proxy 替代了 ES5 的 Object.defineProperty)

       解决了: 例如数组的更新检测等bug, 大大优化了响应式监听的性能 ---覆写

       (原来检测对象属性的变化, 需要一个个对属性递归监听) proxy 可以直接对整个对象劫持

       2. 虚拟DOM - 新算法 (更快 更小)

       3. 提供了composition api, 可以更好的逻辑复用

       4. 模板可以有多个根元素 (不再需要一个必须的跟节点)

       5. 源码用 typescript 重写, 有更好的类型推导 (类型检测更为严格, 更稳定)

       废弃了 eventbus 过滤器

总结vue3 性能更高, 体积更小, 更利于复用, 代码维护更方便

组合式API

composition API  VS  options API

1. vue2 采用 optionsAPI

   1. 优点:易于学习和使用, 每个代码有着明确的位置 
   2. 缺点: 相似的逻辑, 不容易复用, 在大项目中尤为明显
   3. 虽然 optionsAPI 可以通过mixins 提取相同的逻辑, 但是也并不是特别好维护

2. vue3 新增 compositionAPI

   1. compositionAPI 是基于 逻辑功能 组织代码的, 一个功能 api 相关放到一起
   2. 即使项目大一些, 功能多了, 也能快速定位功能相关的 api
   3. 大大的提升了 代码可读性 和 维护性

3. vue3 推荐使用 composition API, 也保留了options API。 即 在vue3中用 vue2 的写法也完全兼容

setup 函数

   1. composition api的使用, 需要配置一个setup 函数

   2. setup 函数是一个新的组件选项, 作为组件中 compositionAPI 的起点

   3. 从生命周期角度来看, setup 会在 beforeCreate 钩子函数之前执行

   4. setup 中不能使用 this, this 指向 undefined

   5. 在模版中需要使用的数据和函数,需要在 setup 返回。

<template>
  <div class="container">
    <h1 @click="say()">{{msg}}</h1>
  </div>
</template>

<script>
 export default {
  setup () {
    console.log('setup执行了')
    console.log(this)
    //定义数据和函数
    const msg = 'hi vue3'
    const say = () => {
      console.log(msg)
    }
    return { msg , say}
  },
  beforeCreate(){
    console.log("beforeCreate执行了")
    console.log(this)
 }
</script>

reactive 函数

前置说明:
   1. setup 需要有返回值, 只有返回的值才能在模板中使用
   2. 默认普通的数据, 不是响应式的

作用: 传入一个复杂数据类型,将复杂类型数据, 转换成响应式数据 (返回该对象的响应式代理)

<template>
  <div>{{ obj.name }}</div>
  <div>{{ obj.age }}</div>
  <button @click="obj.name = 'hhh' ">改值</button>
</template>

<script>
import { reactive } from 'vue'
export default {
    setup () {
      // 1.setup 需要返回值,返回的值才能在模板中使用
      // 2.默认的普通的值不是响应式的,需要用 reactive 函数
      const obj = reactive({
      name: 'zgr'
      age: 18
    })
     return{
       obj
     }
  }
}
</script>

ref函数

reactive 处理的数据, 必须是复杂类型, 如果是简单类型无法处理成响应式, 就需要 ref 函数

作用: 对传入的数据(一般简单数据类型),包裹一层对象, 转换成响应式。

   1. ref 函数接收一个的值, 返回一个ref 响应式对象, 有唯一的属性 value
   2. 在 setup 函数中, 通过 ref 对象的 value 属性, 可以访问到值
   3. 在模板中, ref 属性会自动解套, 不需要额外的 .value
   4. ref函数也支持传入复杂类型,传入复杂类型,也会做响应式处理
 

<template>
   <div>{{ money }}</div>
   <button @click="money++”>改值</button>
</template>

<script>
import { reactive, ref } from 'vue'

export default {
    setup() {
      let money = ref(100)
      money.value++
      return {
        money
      }
   }
}
</script>

ref 和 reactive 的最佳使用方式: (reactive能满足的 ref也能满足)

  1. 明确的对象,明确的属性,用reactive,其他用 ref
  2. 从vue3.2之后,更推荐使用ref (ref底层性能做了提升 => 260%)

script setup语法

    script setup是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 script 语法更加简洁

使用:需要将 setup 添加到 <script> 代码块上

<script setup>
</script>

顶层的绑定会自动暴露给模板,所以定义的变量,函数和import导入的内容都可以直接在模板中直接使用  引入封装组件也无需再components注册

<template>
  <div>
    <div>点击次数: {{ count }}</div>
    <button @click="add">点击修改</button>
  </div>
</template>

<script setup>
import { ref } from 'vue
const count = ref(0)
const add = () => {
  count.value++
}
</script>

计算属性computed函数

computed函数调用时, 要接收一个处理函数, 处理函数中, 需要返回计算属性的值

<template>
   <div>
     <input type="text" v-model="year" />
     <input type="text" v-model="nextYear" />
   </div>
</template>

<script setup>
import { computed, ref} from "vue";
export default {
    const year = ref(2023);
    
    //不带set属性
    const nextYear = computed(() => {
      return +year.value + 1;
    })

    //带set属性的  computed中get和set的用法:可直接修改nextYear的值
    const nextYear = computed({
      get() {
        return +year.value + 1;
      },
      set(value) {
        console.log(value);
        return year.value = value - 1
      }
    })
 }
</script>

vue3中计算属性的函数中如果只传入一个回调函数,表示的是get,若传入一个对象,表示的是get和set

watch函数

watch监视,接收三个参数
   1.参数1: 监视的数据源
   2.参数2: 回调函数
   3.参数3:额外的配置

//监听单个ref
const yuan = ref(100000)
watch(yuan,(value, oldValue) => {
  console.log(value)
})

/监听多个ref
const yuan = ref(100000)
const doller = ref(100000)
watch([yuan,doller],(value) => {
  console.log(value)
})

//监听ref复杂数据
const user = ref({
  name: "qhw",
  age: "18",
})
watch(user, (value) =>{
  console.log('user变化了', value)
},
{
  deep: true,        //深度监听
  immediate: true    //立即执行
})

//监听对象某一属性变化
const user = ref({
  name: "qhw",
  age: "18",
})
watch(
  ()=>user.value.name,
  (value) =>{
  console.log(value)
})

钩子函数的使用

生命周期函数  vue3 中的生命周期函数, 需要在 setup 中调用

import { onMounted, onUpdated, onUnmounted } from 'vue'
const MyComponent = {
setup() {
  onMounted(() => {
    console.log( 'mounted!')
  })
  onUpdated(() => {
    console.log('updated!')
  })
  onUnmounted(() => 
    {console.log('unmounted!')
  })
 }
}

组件通讯-父传子

  1. 父组件提供数据
  2. 父组件将数据传递给子组件
  3. 子组件通过defineProps进行接收
  4. 子组件渲染父组件传递的数据

代码示例 :
父组件

<script setup>
import {ref} from 'vue'
//在setup语法中,组件导入之后就能够直接使用,不需要使用components进行局部注册
import Son from './components/Son'

const money = ref(1000000)
const car = ref("宾利欧陆")
</script>

<template>
  <div>
    <h1>我是父组件</h1>
    <div>金钱: {{ money }}</div>
    <div>车辆: {{ car }}</div>
    <Son :money="money” :car="car"></Son>
  </div>
</template>

<style lang="less” scoped></style>

子组件

<script setup>
import { computed } from 'vue'
// defineProps: 接收父组件传递的数据
const props = defineProps({
    money: Number 
    car: string,
})

const myMoney = computed(() => {
  return props.money + 1000000
})
</script>

<template>
<div>
  <h3>我是子组件</h3>
  <div>{{ money }} --- {{ car }}</div></div>
</template>

<style lang="less”scoped></style>

注意:如果使用defineProps接收数据,这个数据只能在模板中渲染,如果想要在script中也操作props属性,应该接收返回值

组件通讯-子传父

   1. 子组件通过defineEmit获取emit对象(因为没有this)
   2. 子组件通过emit触发事件,并且传递数据
   3. 父组件提供方法
   4. 父组件通过自定义事件的方式给子组件注册事件

代码示例:
  子组件

<script setup>
defineProps({
  money: Number, 
  car: string,
})

const emit = defineEmits(['changeMoney'])

const change = () =>{
 emit("changeMoney",10)
}

</script>

父组件 

<script setup>
import { ref } from 'vue'
import Son from './components/son.vue'

const money = ref(1000000)
const car = ref("宾利欧陆")

const changeMoney = (num) => {
  money.value = money.value - num
}
</script>

<Son :money="money” :car="car"@changemoney="changeMoney"x</Son>

provide 和 inject

依赖注入, 可以非常方便的实现 跨层级的 组件通信 

父组件利用 provide 提供数据

<script setup>
import { provide, ref } from 'vue'
import Son from "./components/Son.vue"

const money = ref(1000)
provide( 'money', money)

</script>

<template>
<div>
  <h1>我是父组件</h1>
  <div>金钱: {{ money }}</div>

  <Son></Son>
</div>
</template>

<style lang="less” scoped></style>

子组件 (子孙后代, 都可以拿到这个数据  利用inject)

<script setup>

import { inject } from 'vue'
const money = inject('money')

</script>

<template>
<div>
  <h3>我是子组件--{{ money }}</h3>
  <button>修改数据</button>
</div>
</template>

<style lang="less” scoped></style>

如果希望子传父, 可以 provide 传递一个方法  这里不再写代码示例

模板中 ref 的使用

这个跟hooks中的useRef有点像   嗯~ 我还是说一模一样吧

1.创建ref:    const myRef = ref(null)
2. 模板中建立关联:  <h1 ref="myRef">哈哈哈哈哈</h1>
3. 使用: myRef.value

代码示例: 操作组件

<script setup>
import { ref } from 'vue'
import Form from './components/Form.vue'

// 创建一个ref
const formRef = ref(null)

const fn = () => {
  console.log(formRef.value.count)
  formRef.value.validate()
}
</script>

<template>
  <Form ref="formRef"></Form>
</template>

需要配合defineExpose

<script setup>
import { ref } from 'vue'

const count = ref(0)
const validate = () => {
  console.log("表单校验方法")
}
//暴露属性给外部组件使用
defineExpose({
  count,
  validate
})
</script>

<template>
  <h3>我是Form组件</h3>
</template>

Vue3中过滤器已废弃

vue3.0中不能使用过滤器,直接使用函数进行替代

<template>
  <h3>{{ formatTime(now) }}</h3>
  <h3>{{ formatTime(other) }}</h3>
</template>

<script setup>
import moment from 'moment' 

// 过滤器
const now = new Date()
const other = new Date('2022-01-23 12:00:00')
const formatTime = (value) => {
  return moment(value).format( 'YYYY-MM-DD')
}

</script>

toRefs 函数

使用场景: 如果对一个响应数据, 进行解构 或者 展开, 会丢失他的响应式特性!

原因: vue3 底层是对 对象 进行监听劫持
作用: 对一个响应式对象的所有内部属性, 都做响应式处理
   1.reactive/ref的响应式功能是赋值给对象的, 如果给对象解构或者展开, 会让数据丢失响应式的能力
   2.使用 toRefs 可以保证该对象解构 或者 展开的每个属性都是响应式的

<template>
  <div>{{ money }}</div>
  <div>{{ car }}</div>
  <div>{{ name }}</div>
  <button @click="money++>改值</button>
</template>

<script setup>

import [ reactive, ref, toRefs ] from 'vue'
const user = ref({
  name: 'qhw',
  age: 18,
})
const { name, age } = toRefs(user.value)

</script>

待续 欢迎补充~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值