Day01【Vue3 选项式】
Day01【Vue3 选项式】
📅 2025/02/20
- 拉取和运行 chemical plant(化工厂)项目。
- 安装 WebStorm、Typora、pycnblog、百度网盘、uTools、图吧工具箱。
破解 WebStorm 和 Typora:https://blog.idejihuo.com/
- 单位使用的前端技术是 Vue3 选项式。
Vue3 选项式
一、生命周期钩子的变化
- 重命名钩子:
Vue3 将部分生命周期钩子改名,容易与 Vue2 混淆:
- beforeDestroy→- beforeUnmount
- destroyed→- unmounted
- 新增 renderTracked(调试渲染依赖)和renderTriggered(调试重新渲染)。
- 执行顺序:
如果同时使用选项式 API 和组合式 API 的 setup(),组合式的钩子(如 onMounted)会先于选项式的钩子(如 mounted)执行。

 .
.
二、响应式系统的差异
- Proxy 替代 defineProperty:
Vue3 使用 Proxy 实现响应式,因此可以直接通过赋值修改对象或数组,无需 Vue.set/ Vue.delete。
常见误区:
// Vue2 中需要 Vue.set,Vue3 中直接赋值即可
this.user.age = 25; // 直接生效

 .
.
- data 必须是函数:
export default {
    data() {
        return {
            object: {
                name: '软柠柠吖'
                age: 18,
            },
            num: 100
        }
    }
}
组件的 data 必须返回一个对象,否则多个组件实例会共享同一份数据(和 Vue2 一致,但新手容易忘记)。
三、选项合并与混入(Mixins)
- 合并策略:
- 
data、methods、computed等选项会合并,同名属性以组件自身为准。
- 
生命周期钩子会合并为数组,按顺序执行(混入的先执行)。 
- 混入的潜在问题:
多个混入可能导致命名冲突或逻辑耦合,建议谨慎使用,优先用组合式 API 的 setup。
四、emits 选项的显式声明
- 必须声明自定义事件:
通过 emits 选项声明组件发出的自定义事件,否则可能被误认为原生事件。
export default {
  emits: ['submit'], // 必须声明
  methods: {
    handleClick() {
      this.$emit('submit'); // 正确触发
    }
  }
}
- 事件验证:
可以为 emits 配置验证函数,确保事件参数符合预期:
emits: {
  submit: (payload) => {
    return typeof payload === 'string'; // 验证参数类型
  }
}
五、setup() 与选项式 API 的混合使用
- setup()中的响应式数据:
在选项式中使用 setup() 时,需要手动暴露数据和方法到 return,才能在模板或其他选项(如 methods)中通过 this 访问。
export default {
  setup() {
    const count = ref(0);
    return { count }; // 暴露到 this
  },
  methods: {
    increment() {
      this.count++; // 通过 this 访问 setup 返回的值
    }
  }
}
- this的指向问题:
- 避免在 setup()或箭头函数中使用this(此时this未绑定到组件实例)。
- 在 methods中正常使用this访问数据和方法。
六、计算属性与方法的区别
- 缓存特性:
computed 基于依赖缓存,依赖不变时不会重新计算;methods 每次调用都会执行。
错误示例:
computed: {
  now() {
    return Date.now(); // 错误!值不会更新,因为无依赖
  }
}
- 依赖追踪:
计算属性必须依赖响应式数据(如 data 或 ref),否则不会自动更新。
七、watch 与 watchEffect
- 选项式中的 watch:
在选项式中,watch 是一个对象,需配置侦听的数据源和回调:
export default {
  data() {
    return { count: 0 };
  },
  watch: {
    count(newVal, oldVal) {
      console.log(`count变化:${oldVal} → ${newVal}`);
    }
  }
}
- 深度侦听与立即执行:
通过 deep: true 和 immediate: true 配置:
watch: {
  user: {
    handler(newVal) { /* ... */ },
    deep: true,    // 深度侦听对象内部变化
    immediate: true // 立即执行一次
  }
}
八、模板引用(Refs)
- 访问 DOM 或组件:
通过 ref 属性标记元素,在 mounted 后通过 this.$refs 访问:
<template>
  <div ref="myDiv">Hello</div>
</template>
<script>
export default {
  mounted() {
    console.log(this.$refs.myDiv); // 获取 DOM
  }
}
</script>
- 避免在 setup()中混淆:
组合式 API 的 ref(响应式变量)与模板 ref(DOM 引用)名称相同,但用途不同,需注意区分。
九、依赖注入(Provide/Inject)
- 父组件提供数据:
使用 provide 选项:
export default {
  provide: {
    theme: 'dark' // 提供静态值
  }
  // 或提供响应式数据:
  data() {
    return { theme: 'dark' };
  },
  provide() {
    return { theme: this.theme };
  }
}
- 子组件注入数据:
使用 inject 选项,建议设置默认值:
export default {
  inject: {
    theme: {
      default: 'light' // 默认值
    }
  }
}
十、常见错误与解决方法
- 箭头函数导致 this错误:
methods: {
  // 错误!箭头函数中的 this 指向全局
  increment: () => this.count++,
  // 正确写法
  increment() { this.count++; }
}
- 异步更新队列:
修改数据后立即操作 DOM 可能获取旧值,需用 nextTick:
this.count++;
this.$nextTick(() => {
  console.log(this.$refs.myDiv.textContent); // 获取更新后的 DOM
});
总结
- 重点:生命周期改名、emits声明、响应式直接赋值、setup()混合使用。
- 难点:this指向、计算属性缓存、watch配置、混入合并策略。
- 建议:多写小示例验证逻辑,结合 Vue Devtools 观察响应式数据变化。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号