vue源码学习总结 prop data method computed 的命名冲突处理策略

本文详细解析了Vue中prop、data、method、computed属性命名冲突时的处理策略及优先级,介绍了源码中相关初始化逻辑,帮助开发者理解并解决实际开发中可能遇到的属性覆盖问题。

vue 组件属性命名冲突处理策略

  1. 当 prop data method computed 的key值冲突, 获取值优先级策略如下:
    computed>data>method computed>method>prop prop>data

  2. 在源码src/instance/state.js 的 initState中,方法的执行顺序为 initProps>initMethods>initData>initComputed , 后面初始化的属性声明会覆盖前面的,所以理论上取值优先级为 computed>data>method>prop 。但是initData中有逻辑:如果prop中没有该属性名data才会声明。所以结论如1中所述。 源码如下:

export function initState (vm: Component) {
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
  if (!isPlainObject(data)) {
    data = {}
    process.env.NODE_ENV !== 'production' && warn(
      'data functions should return an object:\n' +
      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
      vm
    )
  }
  // proxy data on instance
  const keys = Object.keys(data)
  const props = vm.$options.props
  const methods = vm.$options.methods
  let i = keys.length
  while (i--) {
    const key = keys[i]
    if (process.env.NODE_ENV !== 'production') {
      if (methods && hasOwn(methods, key)) {
        warn(
          `Method "${key}" has already been defined as a data property.`,
          vm
        )
      }
    }
    if (props && hasOwn(props, key)) {
      process.env.NODE_ENV !== 'production' && warn(
        `The data property "${key}" is already declared as a prop. ` +
        `Use prop default value instead.`,
        vm
      )
    } else if (!isReserved(key)) {
      proxy(vm, `_data`, key)
    }
  }
  // observe data
  observe(data, true /* asRootData */)
}

关注下再走呗 +_+

Vue 中,`computed`(计算属性)是一种非常强大的功能,用于**声明式地描述依赖于其他数据的值**。它会基于其响应式依赖进行缓存,只有当依赖发生变化才会重新计算。 --- ## ✅ 基本用法 ### 示例 1:基础计算属性 —— 拼接字符串 ```vue <template> <div>Full Name: {{ fullName }}</div> </template> <script> export default { data() { return { firstName: &#39;John&#39;, lastName: &#39;Doe&#39; }; }, computed: { fullName() { return this.firstName + &#39; &#39; + this.lastName; } } }; </script> ``` > 当 `firstName` 或 `lastName` 发生变化,`fullName` 会自动更新。 --- ### 示例 2:带逻辑处理的计算属性 —— 过滤列表 ```vue <template> <ul> <li v-for="item in filteredItems" :key="item.id"> {{ item.name }} </li> </ul> </template> <script> export default { data() { return { items: [ { id: 1, name: &#39;Apple&#39; }, { id: 2, name: &#39;Banana&#39; }, { id: 3, name: &#39;Cherry&#39; } ], filterText: &#39;a&#39; }; }, computed: { filteredItems() { return this.items.filter(item => item.name.toLowerCase().includes(this.filterText.toLowerCase()) ); } } }; </script> ``` > 计算属性返回一个过滤后的数组,模板中可以像普通属性一样使用它。 --- ## ✅ 计算属性 vs 方法(methods) | 特性 | computed | methods | |------|----------|---------| | 是否缓存 | ✅ 是(依赖未变不会重复执行) | ❌ 否(每次调用都会执行) | | 使用方式 | 属性形式 `{{ computedProp }}` | 函数调用 `{{ method() }}` | | 推荐场景 | 基于已有数据派生出新数据 | 需要传参或不依赖响应式数据 | --- ## ✅ 带 setter 的计算属性(高级用法) 你可以为计算属性提供 `get` `set`,实现双向绑定。 ### 示例: ```vue <template> <div> First Name: <input v-model="firstName"><br> Last Name: <input v-model="lastName"><br> Full Name: <input v-model="fullName"> </div> </template> <script> export default { data() { return { firstName: &#39;John&#39;, lastName: &#39;Doe&#39; }; }, computed: { fullName: { get() { return this.firstName + &#39; &#39; + this.lastName; }, set(newValue) { const names = newValue.split(&#39; &#39;); this.firstName = names[0]; this.lastName = names[1]; } } } }; </script> ``` > 当你在输入框修改 `fullName` ,会自动拆分并更新 `firstName` `lastName`。 --- ## ✅ 在组件中使用计算属性 你可以在组件内部定义自己的计算属性,它们只能访问当前组件的数据 props。 ### 示例:组件内使用 computed ```vue <!-- ChildComponent.vue --> <template> <div> <p>Prop Value: {{ propValue }}</p> <p>Formatted Prop: {{ formattedProp }}</p> </div> </template> <script> export default { props: [&#39;value&#39;], computed: { formattedProp() { return this.value.toUpperCase(); } } }; </script> ``` --- ## ✅ 总结对比 | 功能 | computed | methods | watch | |------|----------|---------|-------| | 缓存机制 | ✅ 有缓存 | ❌ 无缓存 | ❌ 无缓存 | | 支持异步 | ❌ 不推荐 | ✅ 可以 | ✅ 可以 | | 适合场景 | 数据派生、组合多个响应式数据 | 事件处理、复杂逻辑、非响应式操作 | 监听数据变化并执行副作用 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值