前端面试宝典

Vue/uniApp 组件解耦 & 逻辑下沉 极简备忘录

核心口诀

UI 自己管、交互自己做,父只传数据、业务再冒泡


一、标准 6 步流程(固定套路,所有页面通用)

第1步:拆分组件

卡片/模块拆独立子组件,一个卡片一个组件。

第2步:父传子 Props

  1. 子组件 props 声明需要的字段、类型、默认值
  2. 父页面只通过属性传数据,不额外处理子组件内部字段

第3步:下沉「显示隐藏逻辑」

把原来父页面的 showXXX 这类判断,全部移到子组件 computed

  • 是否显示卡片
  • 多状态文案切换
  • 有无数据判断

父页面删掉相关计算属性、冗余判断。

第4步:下沉「所有普通交互逻辑」

以下逻辑一律写在子组件内部,父页面不要出现:

  • uni.showModal 弹窗提示
  • uni.previewImage 图片预览
  • uni.navigateTo 页面跳转
  • 复制文本、拨打电话
  • 开关、折叠、切换 UI 行为

第5步:只对「核心业务动作」emit 抛事件

只有需要调接口、改全局状态、影响父页面数据流的动作,才 $emit 给父组件:

  • 取消订单
  • 确认支付
  • 提交表单
  • 申请退款

纯 UI 跳转/弹窗/预览 不抛事件

第6步:父页面清理收尾

  1. template 删掉多余 @xxx 事件绑定
  2. methods 删除已下沉的方法
  3. computed 删除下沉的显示判断
  4. 抽离:
    • 静态配置 → config/xxx.js
    • 工具方法/数据映射 → utils/xxxUtil.js

二、明确分界线(什么该下沉、什么留父页面)

✅ 必须下沉到子组件

  • 卡片自身显隐判断
  • 自身文案、样式、局部状态
  • 点击弹窗、提示框
  • 图片预览、页面路由跳转
  • 简单格式化展示

✅ 必须留在父页面

  • 页面 onLoad 初始化
  • 接口请求、加载 loading
  • 全局状态管理
  • 子组件抛上来的核心业务回调

❌ 禁止写法

  1. 父页面替子组件写点击事件
  2. 父页面写子组件的显隐 v-if 判断
  3. 子组件大量依赖父页面变量、硬耦合

三、子组件固定模板写法(直接复制套用)

<template>
  <view v-if="isShow">
    <!-- 组件UI -->
  </view>
</template>

<script>
export default {
  name: 'XXXCard',
  props: {
    // 按需声明
    info: {
      type: Object,
      default: () => ({})
    }
  },
  computed: {
    // 1. 显隐判断下沉
    isShow() {
      return !!this.info?.name
    }
  },
  methods: {
    // 2. 自身交互逻辑下沉
    handleClick() {
      // 弹窗/跳转/预览 写这里
    },
    // 3. 业务动作才抛事件
    handleBizAction() {
      this.$emit('confirm', payload)
    }
  }
}
</script>

四、父页面固定模板写法

<XXXCard :info="infoData" @confirm="handleConfirm" />

父页面只做:

  • 传 props 数据
  • 接收业务事件
  • 发请求、处理业务结果

五、你这次订单页面落地总结(对照备忘录)

  1. 每个卡片单独组件 ✅
  2. 只靠 props 传参 ✅
  3. 显隐判断全在子组件 computed ✅
  4. 费用弹窗、图片预览、返程跳转 全下沉 ✅
  5. 只把「取消订单」业务事件往上抛 ✅
  6. 状态配置、数据映射、时间工具 全部抽离 ✅

以后任何 Vue/uniApp 页面,直接按这 6 步走,永远高内聚、低耦合、好维护

需要我给你生成一份 纯文本版,可直接存笔记 的精简无代码版本吗?