核心内容摘要
Linux权限管理:HMCL启动器非root权限配置全攻略
vue2开发中一些
注意事项
1数据响应式问题// ❌ Bug直接通过索引修改数组元素不会触发更新 this.items[0]new value// ❌ 修改数组长度不会触发更新 this.items.length0解决方案// ✅ 使用Vue.set或$setthis.$set(this.items,0,new value)// ✅ 使用数组变异方法 this.items.splice(0,1,new value)// ✅ 清空数组的正确方式 this.items.splice(
0)
2对象属性添加/删除// ❌ 动态添加新属性不会触发更新 this.user.age25// ❌ 删除属性不会触发更新 delete this.user.name解决方案// ✅ 使用Vue.set Vue.set(this.user,age,
// ✅ 使用$setthis.$set(this.user,name,John)// ✅ 删除属性使用$deletethis.$delete(this.user,name)
3disabled和v-if同时使用
注意事项当v-if和disabled同时出现时可能会导致页面不能响应式更新需要刷新一次页面才可以解决方法如下在el-button中添加key属性
4mixins的不规范使用典型事故案例解析Case 1: 异步数据竞争条件// mixinA.jsexportdefault{asynccreated(){const resawait apiCall();this.sharedDatares.data;// 假设此时组件尚未初始化完毕}}// mixinB.jsexportdefault{data(){return{sharedData: null}},mounted(){console.log(this.sharedData)}// undefined!因为执行时机早于赋值} 根本原因: Vue的生命周期钩子执行顺序由内部队列决定跨mixin的异步操作会产生竞态条件。
Case 2: 计算属性污染// mathMixin.jsexportdefault{computed:{totalPrice(){returnthis.items.reduce((sum, i)sum i.price,
}}}// cartComponent.jsexportdefault{mixins:[mathMixin],data(){return{items:[]}}, // 如果另一个mixin也定义了totalPrice会怎样后者覆盖前者} 灾难后果: 最终显示的价格可能是任意一个mixin的版本取决于加载顺序而非业务需求。
最佳实践守则
单一职责原则单个mixin仅解决一个问题如滚动监听、表单验证禁止创建全能型mixin。
前缀约定强制规范// good practice const scrollHandler{/*... */};exportdefault scrollHandler;// bad practice - 无意义命名 const utilityMixin{/*... */};
显式导入代替全局注册// ❌ 危险做法 Vue.mixin({computed:{...}});// ✅ 安全做法importmyMixin from./myMixin;exportdefault{mixins:[myMixin]};
防御性编程技巧// 防止关键属性被覆盖 const safeMixin{beforeCreate(){if(this.$options.methods?.criticalMethod){throw new Error(Critical method conflict detected!);}}, //...其他逻辑}; 建议对于新项目应优先采用 Composition API setup语法糖已存在的重度mixin项目建议分阶段重构至组合式API架构。
若必须使用mixins务必配合ESLint插件实现以下校验规则{rules:{no-mixin-overlap:error,require-explicit-key:error,disallow-global-mixin:error}}
vue3开发中一些
注意事项
1响应式数据解构问题Vue3特有// ❌ 直接解构reactive对象 const statereactive({count:0, name:test})const{count, name}state // 失去响应性 // ✅ 解决方案使用toRefs const statereactive({count:0, name:test})const{count, name}toRefs(state)// 保持响应性 // ✅ 或者使用computed const countcomputed(()state.count)
2生命周期和异步更新相关Bugvue2和vue3通用
21DOM更新异步性问题// ❌ 错误修改数据后立即访问DOM this.messagenew messageconsole.log(this.$el.textContent)// 可能还是旧值 // ✅ 解决方案使用nextTick this.messagenew messagethis.$nextTick((){console.log(this.$el.textContent)// 新值})// Vue3 Composition API写法import{nextTick}fromvueconst changeMessageasync(){message.valuenew messageawait nextTick()console.log(container.value.textContent)}
22生命周期钩子中的异步操作// ❌ 在beforeDestroy/beforeUnmount中忘记清理created(){this.timersetInterval((){console.log(timer running)},
}// ❌ 忘记清理beforeDestroy(){// 缺少clearInterval}// ✅ 正确的清理beforeDestroy(){clearInterval(this.timer)}// Vue3 setup写法import{onUnmounted}fromvuesetup(){const timersetInterval((){},
onUnmounted((){clearInterval(timer)})}
23Props直接修改// ❌ 直接修改props props:[value], methods:{updateValue(){this.valuenew value// 报错}}// ✅ 正确方式触发事件通知父组件 // 子组件 this.$emit(update:value,new value)// Vue3 v-model写法 // 父组件ChildComponent v-model:titlepageTitle/// 子组件 props:[title], emits:[update:title], methods:{updateTitle(){this.$emit(update:title,new title)}}
24事件监听器泄漏// ❌ 忘记移除事件监听器mounted(){window.addEventListener(resize, this.handleResize)}// ✅ 正确方式mounted(){window.addEventListener(resize, this.handleResize)},beforeDestroy(){window.removeEventListener(resize, this.handleResize)}// Vue3 Composition APIimport{onMounted, onUnmounted}fromvuesetup(){const handleResize(){// 处理resize}onMounted((){window.addEventListener(resize, handleResize)})onUnmounted((){window.removeEventListener(resize, handleResize)})}
3.