给selectedProjectId赋值报getter-only属性TypeError错误如何解决?
错误原因
- 你用
const声明了selectedProjectId变量,const声明的基础类型值(字符串、数字等)不允许被重新赋值,一旦声明后修改就会抛出类型错误。 - 你将
selectedProjectId作为ES模块的成员直接导出,ES模块的导出绑定默认是只读的,就算你把const改成let,在导入模块中直接给导入的变量赋值也会触发相同的只读错误。 - 教程没有报错是因为大概率没有使用ES模块化导出变量,直接在全局作用域声明变量,不会触发模块导出的只读限制,你使用webpack打包启用了模块化机制才会出现差异。
修复方案
推荐两种可行方案,按需选择:
方案1:封装状态存取方法(更安全,推荐)
在定义变量的模块中,不直接导出状态变量,而是导出对应的读写方法,所有状态修改都通过模块内部暴露的方法完成:
首先修改原模块代码:
const LOCAL_STORAGE_LIST_KEY = 'project.lists'; const LOCAL_STORAGE_SELECTED_LIST_ID_KEY = 'project.selectedProjectId'; const projects = JSON.parse(localStorage.getItem(LOCAL_STORAGE_LIST_KEY)) || []; // 把const改为let,允许内部修改 let selectedProjectId = localStorage.getItem(LOCAL_STORAGE_SELECTED_LIST_ID_KEY); function save() { localStorage.setItem(LOCAL_STORAGE_LIST_KEY, JSON.stringify(projects)); localStorage.setItem(LOCAL_STORAGE_SELECTED_LIST_ID_KEY, selectedProjectId); } // 新增状态读写方法 function getSelectedProjectId() { return selectedProjectId; } function setSelectedProjectId(newId) { selectedProjectId = newId; } export { projects, save, getSelectedProjectId, setSelectedProjectId }
然后在点击事件所在的模块,导入setSelectedProjectId方法,修改赋值逻辑:
projectList.addEventListener('click', e => { if (e.target.tagName.toLowerCase() === 'li') { console.log(e.target.dataset.projectId); console.log('works'); // 替换直接赋值为调用set方法 setSelectedProjectId(e.target.dataset.projectId); saveAndRender(); } });
方案2:把状态存入引用类型对象中
利用const声明的引用类型(对象、数组)可以修改内部属性的特性,把所有状态挂载到同一个对象上导出:
修改原模块代码:
const LOCAL_STORAGE_LIST_KEY = 'project.lists'; const LOCAL_STORAGE_SELECTED_LIST_ID_KEY = 'project.selectedProjectId'; // 所有状态存入state对象 export const state = { projects: JSON.parse(localStorage.getItem(LOCAL_STORAGE_LIST_KEY)) || [], selectedProjectId: localStorage.getItem(LOCAL_STORAGE_SELECTED_LIST_ID_KEY) } function save() { localStorage.setItem(LOCAL_STORAGE_LIST_KEY, JSON.stringify(state.projects)); localStorage.setItem(LOCAL_STORAGE_SELECTED_LIST_ID_KEY, state.selectedProjectId); } export { save }
点击事件逻辑修改为修改对象属性:
projectList.addEventListener('click', e => { if (e.target.tagName.toLowerCase() === 'li') { console.log(e.target.dataset.projectId); console.log('works'); state.selectedProjectId = e.target.dataset.projectId; saveAndRender(); } });
内容的提问来源于stack exchange,提问作者Giaxle
相关产品推荐
相关产品推荐

