Skip to main content

Command Palette

Search for a command to run...

Vue: readonly的代理坑

Updated
1 min read

最近寫composable要 return 響應式變數,因為希望外部在使用這個composable的時候不要去改動到這個響應式變數,故使用 readonly 去包覆這個響應式變數:

// useComposable.js

import { readonly } from "vue";

export default useComposable(){
 
    const nested = ref({
        states: [
            {
                id: 1,
                isChecked: false,
                /* ... */
            },
            {
                id: 2,
                isChecked: false,
                /* ... */
            },
        ]
    });

    // ...

    const toggleState = (val, state) => {
        state.isChecked = val;
    }

    return {
        nested: readonly(nested),
        toggleState
    }

}

我在外部檔案使用這個composable,取得到nested這個巢狀物件,但希望改變其中的 nested.states[0].isChecked 屬性值:

// outer.vue
<template>
    <checkbox
        v-for="state in states"
        :key="state.id"
        :model-value="state.isChecked"
        @update:modelValue="\(evt => toggleState(\)evt, state)"
    />
</template>
<script>
import useComposable from "./useComposable";

const { states, toggleState } = useComposable();

</script>

結果發現無法改變nested.states[0].isChecked 屬性值,後來看文件

A readonly proxy is deep: any nested property accessed will be readonly as well.

readonly 包裹的響應式變數會連同其內部屬性都一起設定為唯讀(readonly),所以即使我在 toggleState 會是傳入唯讀的 state、無法修改其值,所以正確 toggleState 的正確作法應該是傳入 id 去改變原始的響應式變數:

 const toggleState = (val, stateId) => {
    const state = nested.states.find(s => s.id === stateId);
    state.isChecked = val;
 }

References

4 views

More from this blog

Vite: vite-plugin-html的bugs和坑

因為工作要用Vite去生成一個mpa專案且根據頁面不同,動態生成不同 <title> 的HTML,所以就找了一個套件──vite-plugin-html,結果因為套件好像很久沒維護,隨著Vite升級又多了一些有的沒的bug,順手來記錄一下。 template delete 像我第一個就是遇到生成的時候template HTML也會被刪掉,後來看到issue上也有人反映,還好有好心人士解決這個問題,

Feb 26, 20261 min read4

Lun's Blog

82 posts

Notes for web development