vue3个人最佳实践记录(5)- readonly/shadowReadonly的奇妙用法,从今天起进入不可变的世界

104 阅读1分钟

vue3中提供了深只读/浅只读,实现就是递归的方式,所以按需去使用即可,下面提供一些个人的思考

不可变的优点与缺点

优点:

  1. 不可变是函数式编程中重要思想,因其不可变,所以规避潜在因为引用而出现的问题
  2. vue3提供的readonly/shadowReadonly有硬性的控制台提示,可以实时看到,搭配上github的工作流可以达到无法构建的硬性效果(硬性可以让团队变得更好)
  3. 优异的错误定位

缺点:

  1. 对于规范的团队,画蛇添足
  2. 因为深只读是递归实现,同时伴随着深拷贝,它们需要更多的内存

例子1

// App.vue
<script setup>
import {ref, readonly} from "vue";
import HelloWorld from '@/components/HelloWorld.vue'

const user = ref({})
const updateUser = (value) => {
  user.value = value
}
</script>

<template>
  <HelloWorld msg="Vite + Vue" :user="readonly(user)" @update:user="updateUser"/>
</template>
// HelloWorld.vue
<script setup>
import {ref} from 'vue'

const props = defineProps({
  msg: String,
  user: Object
})
const emit = defineEmits([
  'update:user',
])

const count = ref(0)

const test = () => {
  emit('update:user', {
    ...props.user,
    newProp: 1
  })
}

</script>

<template>
  <h1>{{ msg }}</h1>
  <p>{{user.newProp}}</p>
  <button type="button" @click="test">change</button>
</template>

例子2

<script setup>
import {ref, readonly} from "vue";
import {useRoute, useRouter} from "vue-router";
import { pipe } from 'ramda'
import { useUserStore } from 'store/user'

const route = useRoute()
const router = useRouter()
const userStore = useUserStore

const navigateToDetail = pipe(
    function genQuery(query) {
        query.owner = userStore.userId
        return query
    },
    // 自己试一下即可
    // function genQuery(query) {
    //    const result = {...query}
    //    result.owner = userStore.userId
    //    return result
    // },
    function navigate(query) {
        router.push({
            path: '/detail',
            query
        })
    }
)
</script>

<template>
    <button @click="navigateToDetail(route)">跳转到详情页</button>
</template>

最后,仁者见仁智者见智,我在开发中会更多的抛弃代码给我带来的“副作用”(比如引用问题),更专注于业务。也引用一句话,代码没出现性能问题时,不需要提前优化

后续会陆续分享vue3个人觉得最佳实践