找回密码
 立即注册
首页 业界区 业界 【vue3】详解单向数据流,大家千万不用为了某某而某某了 ...

【vue3】详解单向数据流,大家千万不用为了某某而某某了。

吉娅寿 2025-6-6 11:21:34
总览 Vue3 的单向数据流

尽信官网,不如那啥。
vue的版本一直在不断更新,内部实现方式也是不断的优化,官网也在不断更新。
既然一切皆在不停地发展,那么我们呢?等着官网更新还是有自己的思考?
我觉得我们要走在官网的前面,而不是等官网更新后,才知道原来可以这么实现。。。
我习惯先给大家一个整体的概念,然后再介绍各个细节。
脑图版

先整理一下和单向数据流有关的信息,做个脑图:
1.png

大纲版

列个大纲看看:

  • 自动版

    • v-model、emit(defineModel):组成无障碍通道,实现父子组件之间的值类型的响应性。
    • pinia.$state、pinia.$patch:状态管理提供的方法。
    • props + reactive:直接改 reactive,争议比较大
    • 注入 + reactive:直接改 reactive,一般可以忍受

  • 手动版

    • 注入 + reactive + function:官网建议通过 function 改 reactive,而不是直接改 reactive。
    • 状态管理的getter、mutation、action:状态管理,其实也涉及到了单向数据流。

  • props是否可以直接改?(从代码的角度来分析)

    • 值类型:不可改,否则响应性就崩了。
    • 引用类型:地址不可改,但是属性可以改。对于引用类型,其实都是通过 reactive 实现响应性的。

  • 有无意义的角度 (这是一个挨骂的话题

    • 有意义的方式:实现响应性的唯一方式,或者有记录(timeline)、有验证、限制等。
    • 无意义的方式:没有上面说的功能,还自认为是严格遵守规矩。

  • 限制的是谁?

    • 发起者:如果是限制子组件不能发起修改的话,那么任何方式都应该不能被允许,emit 也不行。
    • 方式(手段):如果只是限制一些方式的话,那么为啥 emit 可以,reactive 就不能直接改?有啥区别呢?

      • 二者都没有做记录(timeline),
      • 没有做任何限制、验证。


画个表格对比一下:

再来看看各种方式的对比:
方式实现手段有无记录有无限制、验证官网意见适合场景v-model + emit抛出事件无无可以以前的方式v-model + defineModel抛出事件无无推荐V3.4 推荐的方式props + reactive代理,set无无不推荐适合传递引用类型注入 + reactive代理,set无无不建议直接改reactive适合多层级的组件结构注入 + reactive + function调用指定的函数可以有可以有推荐方式适合特殊需求pinia.$patch、$state代理,set等timeline无pinia 的 getter、 action调用指定的函数timeline可以有这样应该有一个明确的总体感觉了吧。
props 的单向数据流

为啥弄得这么复杂?还不是因为两点:

  • vue 自带响应性,主要是 reactive有点太“逆天”。
  • composition API,可以把响应性分离出来单独使用。
如果没有 reactive,那么也就不会这么乱糟糟的了,让我们细细道来。
props 本身是单向的

https://cn.vuejs.org/guide/components/props.html#one-way-data-flow
官网里关于 props 的单向数据流是这样描述的:
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。
这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。
整理一下重点:

  • props 本身是单向的,只能接收父组件传入的数据,本身不具有改变父组件数据的能力。
  • 父组件的(响应性)数据如果变化,会通知 props 进行更新。
  • props.xxxx ,自带响应性。
  • props 不具有修改父组件数据的能力,这样就避免了父组件的数据被意外修改而受到影响。
  • 否则,数据流向 会混乱,导致难以理解
其实 props 本来就是单向的,用于子组件接收父组件传入的数据,完全没有让子组件修改父组件里的数据的功能。
那么为何还要强调单向数据流呢?原因有二:引用类型reactive
props可以设置两种数据类型:

  • 值类型(数字、字符串等),用于简单情况,比如 input、select 的值等。
  • 引用类型(对象、数组等),用于复杂情况,比如表单、验证信息、查询条件等。
现在,仅从代码的角度看看 props 在什么情况可以改、不可以改。

  • 值类型,那是肯定不能直接改,直接改就破坏了响应性,父子组件的数据也对应不上。
  • 引用类型,又分为两种情况:改地址、改属性。

    • 改地址,那当然也是不行滴!同上,地址换了怎么找到你家?
    • 如果传入的是普通对象,虽然可以改属性,但是没有响应性;
    • 如果传入的是 reactive 的话,那就可以改其属性了,因为 reactive 自带响应性。

那么问题来了:

  • reactive 在父组件可以改,不会难以理解。
  • reactive 通过依赖注入的方式给子组件,虽然官网不建议直接改,但是就问问你,你会不会直接改?
  • reactive 通过 props 的方式给子组件,为啥一改就混乱而难以理解了呢?
  • 【重点】单向数据流,限制的是发起者,还是“渠道”?
所以重点就是这个 reactive !如果没有他,props 即使直接改了,也无法保证响应性,从而被我们所抛弃,也就不用纠结和争论了。
那么 reactive 到底是怎么回事?大家先不要着急,先看看官网允许的情况,然后再对比思考。那谁不是说了吗,没有对比就没有那啥。。。
为什么会混乱?想到了一种可能性:父组件定义了一个 reactive 的数据,然后通过 props 传递个多个子组件,然后某个子组件里面还有很多子子组件,也传入了这个数据。
某个时候发现状态异常变更,那么问题来了:到底是谁改了状态?(后续跟进)
emit 怎么可以改了?

emit 本意是子组件向父组件抛出一个事件,然后 vue 内部提供了一种方式(update:XXXXX),可以实现子组件修改父组件的需求。
  1. <template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template>
复制代码
update:XXX 可以视为内部标识,会特殊处理这个 emit。
好了,这里不讨论具体是如何实现了,而是要讨论一下,不是说好的单向数据流,子组件不能改父组件的吗?不是说改了会导致混乱而难以理解吗?
官方的说法:emit 并不是直接修改,而是通过向父组件抛出一个事件,父组件响应这个事件来实现的。所以,不是直接改,并没有破坏单向数据流。
这个说法嘛,确实很官方。只是从结果来看,还是子组件发起了状态的变更,那么问题来了,如果是上面的那种情况,可以方便获知是谁改了状态吗?(似乎也会导致混乱和难以理解吧)
那么问题来了:单向数据流,是限制发起者,还是手段


  • 如果限制的是发起者的话,那么 emit 也不行,因为也是在子组件发起的,啥时候改,怎么改都是由子组件决定,emit只是一个无障碍通道的起始端,另一端是 v-model。
  • 如果限制手段的话,那么不同的手段到底有啥区别?为啥 emit 可以,reactive 就不可以?
不要钻牛角尖了,其实是有一个很实际的需求:

  • 父子组件之间要保持响应性
  • 子组件有“直接”改的要求
举个例子,各种 UI库 都有 xx-input 组件,外面用 v-model 绑定一个变量,然后 xx-input 里面必须可以修改传入的变量,而且要保持响应性对吧,否则咋办?
v-model + emit 就是解决这个实际需求的。(解决问题,给大家带来方便,然后才会选择vue,其余其他的嘛。。。)
当然,可以使用 ref,但是 ref 的本体是一个class,属于引用类型,如果传入 ref 本体的话,相当于传入一个对象给子组件。这个咋算?
vue 现在的做法是,template 会默认把 ref.value 传给子组件,而不是 ref 本体,这样传入的还是基础类型。
所以,这是实现父子组件之间,值类型的响应性的唯一方法。
defineModel,是直接改?

https://cn.vuejs.org/guide/components/v-model.html
defineModel 是 vue3.4 推出来的语法糖(稳定版),内部依然使用了 emit 的方式,所以可以视为和 emit 等效。
官网示例代码:
  1. <template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template>Parent bound v-model is: {{ model }}
复制代码
官方的示例代码,特意展示了一下可以在子组件“直接改”的特点。
看过内部实现代码的都知道,其内部有一个内部变量,然后返回的是一个customerRef(官方说是ref),所以我们不是直接改 props,而是改 ref.value,然后内部通过 set 拦截,调用 emit 向父组件提交申请。
如果对内部原理感兴趣可以看这里:

  • https://juejin.cn/post/7331021519965356071
  • https://juejin.cn/post/7354960709010260005
依赖注入(provide/inject)也有单向数据流?

https://cn.vuejs.org/guide/components/provide-inject.html#working-with-reactivity
父子组件之间传值,就不得不说说依赖注入,那么是否存在“单向数据流”的问题呢?那也是必然应该存在呀,只是官网没有直接明确说。
注意:依赖注入只负责传递数据,并不负责响应性。
官网的意思,是让我们在父组件实现状态的变更,然后把状态和负责状态变更的函数一起传给(注入到)子组件,子组件不要直接改状态,而是通过调用 【父组件传入的函数】 来变更状态。
官网原文:
当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。
有的时候,我们可能需要在注入方组件中更改数据。在这种情况下,我们推荐在供给方组件内声明并提供一个更改数据的方法函数:
官网推荐的方式是这样的:
  1. 子组件<template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template><template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>{{ location }}
复制代码
看着是不是有点眼熟?这让我想起了 react 的 useState。
其实想一想,为啥非得学 react?react 的特点就是:不能变。所以当需要变更的时候,必须调用专门的 hooks 来处理。
但是 vue 的特点就是响应性呀,和 react 恰恰相反。
当然了,自己写一个函数也是有好处的,比如:
  1. const 张三 = reactive({name:'zs',age:20})const setAge = (age) => {<template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template>if (age < 0) {<template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template><template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template>// 年龄不能是负数<template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template>}<template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template>// 其他验证<template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>// 通过验证,赋值<template>
  32.   <input
  33.     :value="props.modelValue"
  34.     @input="emit('update:modelValue', $event.target.value)"
  35.   />
  36. </template>张三.age = age<template>
  37.   <input
  38.     :value="props.modelValue"
  39.     @input="emit('update:modelValue', $event.target.value)"
  40.   />
  41. </template>// 还可以做记录(timeline)}
复制代码
这样就不能瞎改年龄了。或者根据出生日期自动计算年龄。
不是说不能自己写函数,而是说这个函数要有点意义。
状态管理也涉及单向数据流吗?

props 和注入说完了,那么就来到了状态管理,这里以 pinia 为例。
状态管理也涉及单向数据流吗?那当然是必须滴呀,否则 Vuex 的时候,为啥总强调要通过 mutation 去变更状态,而不要直接去改状态?
$state 是直接改吗?

那么 pinia 为什么提供了 $state 用于“直接”改状态呢?这还得看看源码:

  • pinia.mjs 1541 行
  1. <template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template><template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>Object.defineProperty(store, '$state', {<template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template><template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template><template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template><template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>get: () => ((process.env.NODE_ENV !== 'production') && hot ? hotState.value : pinia.state.value[$id]),<template>
  32.   <input
  33.     :value="props.modelValue"
  34.     @input="emit('update:modelValue', $event.target.value)"
  35.   />
  36. </template><template>
  37.   <input
  38.     :value="props.modelValue"
  39.     @input="emit('update:modelValue', $event.target.value)"
  40.   />
  41. </template><template>
  42.   <input
  43.     :value="props.modelValue"
  44.     @input="emit('update:modelValue', $event.target.value)"
  45.   />
  46. </template><template>
  47.   <input
  48.     :value="props.modelValue"
  49.     @input="emit('update:modelValue', $event.target.value)"
  50.   />
  51. </template>set: (state) => {<template>
  52.   <input
  53.     :value="props.modelValue"
  54.     @input="emit('update:modelValue', $event.target.value)"
  55.   />
  56. </template><template>
  57.   <input
  58.     :value="props.modelValue"
  59.     @input="emit('update:modelValue', $event.target.value)"
  60.   />
  61. </template><template>
  62.   <input
  63.     :value="props.modelValue"
  64.     @input="emit('update:modelValue', $event.target.value)"
  65.   />
  66. </template><template>
  67.   <input
  68.     :value="props.modelValue"
  69.     @input="emit('update:modelValue', $event.target.value)"
  70.   />
  71. </template><template>
  72.   <input
  73.     :value="props.modelValue"
  74.     @input="emit('update:modelValue', $event.target.value)"
  75.   />
  76. </template><template>
  77.   <input
  78.     :value="props.modelValue"
  79.     @input="emit('update:modelValue', $event.target.value)"
  80.   />
  81. </template>/* istanbul ignore if */<template>
  82.   <input
  83.     :value="props.modelValue"
  84.     @input="emit('update:modelValue', $event.target.value)"
  85.   />
  86. </template><template>
  87.   <input
  88.     :value="props.modelValue"
  89.     @input="emit('update:modelValue', $event.target.value)"
  90.   />
  91. </template><template>
  92.   <input
  93.     :value="props.modelValue"
  94.     @input="emit('update:modelValue', $event.target.value)"
  95.   />
  96. </template><template>
  97.   <input
  98.     :value="props.modelValue"
  99.     @input="emit('update:modelValue', $event.target.value)"
  100.   />
  101. </template><template>
  102.   <input
  103.     :value="props.modelValue"
  104.     @input="emit('update:modelValue', $event.target.value)"
  105.   />
  106. </template><template>
  107.   <input
  108.     :value="props.modelValue"
  109.     @input="emit('update:modelValue', $event.target.value)"
  110.   />
  111. </template>if ((process.env.NODE_ENV !== 'production') && hot) {<template>
  112.   <input
  113.     :value="props.modelValue"
  114.     @input="emit('update:modelValue', $event.target.value)"
  115.   />
  116. </template><template>
  117.   <input
  118.     :value="props.modelValue"
  119.     @input="emit('update:modelValue', $event.target.value)"
  120.   />
  121. </template><template>
  122.   <input
  123.     :value="props.modelValue"
  124.     @input="emit('update:modelValue', $event.target.value)"
  125.   />
  126. </template><template>
  127.   <input
  128.     :value="props.modelValue"
  129.     @input="emit('update:modelValue', $event.target.value)"
  130.   />
  131. </template><template>
  132.   <input
  133.     :value="props.modelValue"
  134.     @input="emit('update:modelValue', $event.target.value)"
  135.   />
  136. </template><template>
  137.   <input
  138.     :value="props.modelValue"
  139.     @input="emit('update:modelValue', $event.target.value)"
  140.   />
  141. </template><template>
  142.   <input
  143.     :value="props.modelValue"
  144.     @input="emit('update:modelValue', $event.target.value)"
  145.   />
  146. </template><template>
  147.   <input
  148.     :value="props.modelValue"
  149.     @input="emit('update:modelValue', $event.target.value)"
  150.   />
  151. </template>throw new Error('cannot set hotState');<template>
  152.   <input
  153.     :value="props.modelValue"
  154.     @input="emit('update:modelValue', $event.target.value)"
  155.   />
  156. </template><template>
  157.   <input
  158.     :value="props.modelValue"
  159.     @input="emit('update:modelValue', $event.target.value)"
  160.   />
  161. </template><template>
  162.   <input
  163.     :value="props.modelValue"
  164.     @input="emit('update:modelValue', $event.target.value)"
  165.   />
  166. </template><template>
  167.   <input
  168.     :value="props.modelValue"
  169.     @input="emit('update:modelValue', $event.target.value)"
  170.   />
  171. </template><template>
  172.   <input
  173.     :value="props.modelValue"
  174.     @input="emit('update:modelValue', $event.target.value)"
  175.   />
  176. </template><template>
  177.   <input
  178.     :value="props.modelValue"
  179.     @input="emit('update:modelValue', $event.target.value)"
  180.   />
  181. </template>}<template>
  182.   <input
  183.     :value="props.modelValue"
  184.     @input="emit('update:modelValue', $event.target.value)"
  185.   />
  186. </template><template>
  187.   <input
  188.     :value="props.modelValue"
  189.     @input="emit('update:modelValue', $event.target.value)"
  190.   />
  191. </template><template>
  192.   <input
  193.     :value="props.modelValue"
  194.     @input="emit('update:modelValue', $event.target.value)"
  195.   />
  196. </template><template>
  197.   <input
  198.     :value="props.modelValue"
  199.     @input="emit('update:modelValue', $event.target.value)"
  200.   />
  201. </template><template>
  202.   <input
  203.     :value="props.modelValue"
  204.     @input="emit('update:modelValue', $event.target.value)"
  205.   />
  206. </template><template>
  207.   <input
  208.     :value="props.modelValue"
  209.     @input="emit('update:modelValue', $event.target.value)"
  210.   />
  211. </template>$patch(($state) => {<template>
  212.   <input
  213.     :value="props.modelValue"
  214.     @input="emit('update:modelValue', $event.target.value)"
  215.   />
  216. </template><template>
  217.   <input
  218.     :value="props.modelValue"
  219.     @input="emit('update:modelValue', $event.target.value)"
  220.   />
  221. </template><template>
  222.   <input
  223.     :value="props.modelValue"
  224.     @input="emit('update:modelValue', $event.target.value)"
  225.   />
  226. </template><template>
  227.   <input
  228.     :value="props.modelValue"
  229.     @input="emit('update:modelValue', $event.target.value)"
  230.   />
  231. </template><template>
  232.   <input
  233.     :value="props.modelValue"
  234.     @input="emit('update:modelValue', $event.target.value)"
  235.   />
  236. </template><template>
  237.   <input
  238.     :value="props.modelValue"
  239.     @input="emit('update:modelValue', $event.target.value)"
  240.   />
  241. </template><template>
  242.   <input
  243.     :value="props.modelValue"
  244.     @input="emit('update:modelValue', $event.target.value)"
  245.   />
  246. </template><template>
  247.   <input
  248.     :value="props.modelValue"
  249.     @input="emit('update:modelValue', $event.target.value)"
  250.   />
  251. </template>assign($state, state);<template>
  252.   <input
  253.     :value="props.modelValue"
  254.     @input="emit('update:modelValue', $event.target.value)"
  255.   />
  256. </template><template>
  257.   <input
  258.     :value="props.modelValue"
  259.     @input="emit('update:modelValue', $event.target.value)"
  260.   />
  261. </template><template>
  262.   <input
  263.     :value="props.modelValue"
  264.     @input="emit('update:modelValue', $event.target.value)"
  265.   />
  266. </template><template>
  267.   <input
  268.     :value="props.modelValue"
  269.     @input="emit('update:modelValue', $event.target.value)"
  270.   />
  271. </template><template>
  272.   <input
  273.     :value="props.modelValue"
  274.     @input="emit('update:modelValue', $event.target.value)"
  275.   />
  276. </template><template>
  277.   <input
  278.     :value="props.modelValue"
  279.     @input="emit('update:modelValue', $event.target.value)"
  280.   />
  281. </template>});<template>
  282.   <input
  283.     :value="props.modelValue"
  284.     @input="emit('update:modelValue', $event.target.value)"
  285.   />
  286. </template><template>
  287.   <input
  288.     :value="props.modelValue"
  289.     @input="emit('update:modelValue', $event.target.value)"
  290.   />
  291. </template><template>
  292.   <input
  293.     :value="props.modelValue"
  294.     @input="emit('update:modelValue', $event.target.value)"
  295.   />
  296. </template><template>
  297.   <input
  298.     :value="props.modelValue"
  299.     @input="emit('update:modelValue', $event.target.value)"
  300.   />
  301. </template>},<template>
  302.   <input
  303.     :value="props.modelValue"
  304.     @input="emit('update:modelValue', $event.target.value)"
  305.   />
  306. </template><template>
  307.   <input
  308.     :value="props.modelValue"
  309.     @input="emit('update:modelValue', $event.target.value)"
  310.   />
  311. </template>});
复制代码
不太会TypeScript,所以我们来看看编译后的代码,是不是有点眼熟。
虽然表面上看是直接修改,但是却被 set 给拦截了,实际上是通过 $patch 和 Object.assign 实现的赋值操作。
这个和 defineModel 有点类似,表面上看直接改,其实都是间接修改。
而 $patch 里面还有一些操作,比如做记录(timeline)。
store.xxx 是直接修改吗?

可能你会说,$state 并不是状态自己的属性,当然不算直接修改了,那么我们来试试直接修改状态。
通过测试我们可以发现:

  • 可以直接改状态
  • 可以产生记录(timeline)
那么是怎么实现的呢?

  • 其实 pinia 的状态(store)也是 reactive。
    pinia.mis:1436行
  1. <template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template><template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>const store = reactive((process.env.NODE_ENV !== 'production') || USE_DEVTOOLS<template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template><template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template><template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template><template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>? assign({<template>
  32.   <input
  33.     :value="props.modelValue"
  34.     @input="emit('update:modelValue', $event.target.value)"
  35.   />
  36. </template><template>
  37.   <input
  38.     :value="props.modelValue"
  39.     @input="emit('update:modelValue', $event.target.value)"
  40.   />
  41. </template><template>
  42.   <input
  43.     :value="props.modelValue"
  44.     @input="emit('update:modelValue', $event.target.value)"
  45.   />
  46. </template><template>
  47.   <input
  48.     :value="props.modelValue"
  49.     @input="emit('update:modelValue', $event.target.value)"
  50.   />
  51. </template><template>
  52.   <input
  53.     :value="props.modelValue"
  54.     @input="emit('update:modelValue', $event.target.value)"
  55.   />
  56. </template><template>
  57.   <input
  58.     :value="props.modelValue"
  59.     @input="emit('update:modelValue', $event.target.value)"
  60.   />
  61. </template>_hmrPayload,<template>
  62.   <input
  63.     :value="props.modelValue"
  64.     @input="emit('update:modelValue', $event.target.value)"
  65.   />
  66. </template><template>
  67.   <input
  68.     :value="props.modelValue"
  69.     @input="emit('update:modelValue', $event.target.value)"
  70.   />
  71. </template><template>
  72.   <input
  73.     :value="props.modelValue"
  74.     @input="emit('update:modelValue', $event.target.value)"
  75.   />
  76. </template><template>
  77.   <input
  78.     :value="props.modelValue"
  79.     @input="emit('update:modelValue', $event.target.value)"
  80.   />
  81. </template><template>
  82.   <input
  83.     :value="props.modelValue"
  84.     @input="emit('update:modelValue', $event.target.value)"
  85.   />
  86. </template><template>
  87.   <input
  88.     :value="props.modelValue"
  89.     @input="emit('update:modelValue', $event.target.value)"
  90.   />
  91. </template>_customProperties: markRaw(new Set()), // devtools custom properties<template>
  92.   <input
  93.     :value="props.modelValue"
  94.     @input="emit('update:modelValue', $event.target.value)"
  95.   />
  96. </template><template>
  97.   <input
  98.     :value="props.modelValue"
  99.     @input="emit('update:modelValue', $event.target.value)"
  100.   />
  101. </template><template>
  102.   <input
  103.     :value="props.modelValue"
  104.     @input="emit('update:modelValue', $event.target.value)"
  105.   />
  106. </template><template>
  107.   <input
  108.     :value="props.modelValue"
  109.     @input="emit('update:modelValue', $event.target.value)"
  110.   />
  111. </template>}, partialStore<template>
  112.   <input
  113.     :value="props.modelValue"
  114.     @input="emit('update:modelValue', $event.target.value)"
  115.   />
  116. </template><template>
  117.   <input
  118.     :value="props.modelValue"
  119.     @input="emit('update:modelValue', $event.target.value)"
  120.   />
  121. </template><template>
  122.   <input
  123.     :value="props.modelValue"
  124.     @input="emit('update:modelValue', $event.target.value)"
  125.   />
  126. </template><template>
  127.   <input
  128.     :value="props.modelValue"
  129.     @input="emit('update:modelValue', $event.target.value)"
  130.   />
  131. </template>// must be added later<template>
  132.   <input
  133.     :value="props.modelValue"
  134.     @input="emit('update:modelValue', $event.target.value)"
  135.   />
  136. </template><template>
  137.   <input
  138.     :value="props.modelValue"
  139.     @input="emit('update:modelValue', $event.target.value)"
  140.   />
  141. </template><template>
  142.   <input
  143.     :value="props.modelValue"
  144.     @input="emit('update:modelValue', $event.target.value)"
  145.   />
  146. </template><template>
  147.   <input
  148.     :value="props.modelValue"
  149.     @input="emit('update:modelValue', $event.target.value)"
  150.   />
  151. </template>// setupStore<template>
  152.   <input
  153.     :value="props.modelValue"
  154.     @input="emit('update:modelValue', $event.target.value)"
  155.   />
  156. </template><template>
  157.   <input
  158.     :value="props.modelValue"
  159.     @input="emit('update:modelValue', $event.target.value)"
  160.   />
  161. </template><template>
  162.   <input
  163.     :value="props.modelValue"
  164.     @input="emit('update:modelValue', $event.target.value)"
  165.   />
  166. </template><template>
  167.   <input
  168.     :value="props.modelValue"
  169.     @input="emit('update:modelValue', $event.target.value)"
  170.   />
  171. </template>)<template>
  172.   <input
  173.     :value="props.modelValue"
  174.     @input="emit('update:modelValue', $event.target.value)"
  175.   />
  176. </template><template>
  177.   <input
  178.     :value="props.modelValue"
  179.     @input="emit('update:modelValue', $event.target.value)"
  180.   />
  181. </template><template>
  182.   <input
  183.     :value="props.modelValue"
  184.     @input="emit('update:modelValue', $event.target.value)"
  185.   />
  186. </template><template>
  187.   <input
  188.     :value="props.modelValue"
  189.     @input="emit('update:modelValue', $event.target.value)"
  190.   />
  191. </template>: partialStore);
复制代码

  • 然后对 reactive 进行了监听
    pinia.mis:1409行
  1. <template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template><template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>const partialStore = {<template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template><template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template><template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template><template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>_p: pinia,<template>
  32.   <input
  33.     :value="props.modelValue"
  34.     @input="emit('update:modelValue', $event.target.value)"
  35.   />
  36. </template><template>
  37.   <input
  38.     :value="props.modelValue"
  39.     @input="emit('update:modelValue', $event.target.value)"
  40.   />
  41. </template><template>
  42.   <input
  43.     :value="props.modelValue"
  44.     @input="emit('update:modelValue', $event.target.value)"
  45.   />
  46. </template><template>
  47.   <input
  48.     :value="props.modelValue"
  49.     @input="emit('update:modelValue', $event.target.value)"
  50.   />
  51. </template>// _s: scope,<template>
  52.   <input
  53.     :value="props.modelValue"
  54.     @input="emit('update:modelValue', $event.target.value)"
  55.   />
  56. </template><template>
  57.   <input
  58.     :value="props.modelValue"
  59.     @input="emit('update:modelValue', $event.target.value)"
  60.   />
  61. </template><template>
  62.   <input
  63.     :value="props.modelValue"
  64.     @input="emit('update:modelValue', $event.target.value)"
  65.   />
  66. </template><template>
  67.   <input
  68.     :value="props.modelValue"
  69.     @input="emit('update:modelValue', $event.target.value)"
  70.   />
  71. </template>$id,<template>
  72.   <input
  73.     :value="props.modelValue"
  74.     @input="emit('update:modelValue', $event.target.value)"
  75.   />
  76. </template><template>
  77.   <input
  78.     :value="props.modelValue"
  79.     @input="emit('update:modelValue', $event.target.value)"
  80.   />
  81. </template><template>
  82.   <input
  83.     :value="props.modelValue"
  84.     @input="emit('update:modelValue', $event.target.value)"
  85.   />
  86. </template><template>
  87.   <input
  88.     :value="props.modelValue"
  89.     @input="emit('update:modelValue', $event.target.value)"
  90.   />
  91. </template>$onAction: addSubscription.bind(null, actionSubscriptions),<template>
  92.   <input
  93.     :value="props.modelValue"
  94.     @input="emit('update:modelValue', $event.target.value)"
  95.   />
  96. </template><template>
  97.   <input
  98.     :value="props.modelValue"
  99.     @input="emit('update:modelValue', $event.target.value)"
  100.   />
  101. </template><template>
  102.   <input
  103.     :value="props.modelValue"
  104.     @input="emit('update:modelValue', $event.target.value)"
  105.   />
  106. </template><template>
  107.   <input
  108.     :value="props.modelValue"
  109.     @input="emit('update:modelValue', $event.target.value)"
  110.   />
  111. </template>$patch,<template>
  112.   <input
  113.     :value="props.modelValue"
  114.     @input="emit('update:modelValue', $event.target.value)"
  115.   />
  116. </template><template>
  117.   <input
  118.     :value="props.modelValue"
  119.     @input="emit('update:modelValue', $event.target.value)"
  120.   />
  121. </template><template>
  122.   <input
  123.     :value="props.modelValue"
  124.     @input="emit('update:modelValue', $event.target.value)"
  125.   />
  126. </template><template>
  127.   <input
  128.     :value="props.modelValue"
  129.     @input="emit('update:modelValue', $event.target.value)"
  130.   />
  131. </template>$reset,<template>
  132.   <input
  133.     :value="props.modelValue"
  134.     @input="emit('update:modelValue', $event.target.value)"
  135.   />
  136. </template><template>
  137.   <input
  138.     :value="props.modelValue"
  139.     @input="emit('update:modelValue', $event.target.value)"
  140.   />
  141. </template><template>
  142.   <input
  143.     :value="props.modelValue"
  144.     @input="emit('update:modelValue', $event.target.value)"
  145.   />
  146. </template><template>
  147.   <input
  148.     :value="props.modelValue"
  149.     @input="emit('update:modelValue', $event.target.value)"
  150.   />
  151. </template>$subscribe(callback, options = {}) {<template>
  152.   <input
  153.     :value="props.modelValue"
  154.     @input="emit('update:modelValue', $event.target.value)"
  155.   />
  156. </template><template>
  157.   <input
  158.     :value="props.modelValue"
  159.     @input="emit('update:modelValue', $event.target.value)"
  160.   />
  161. </template><template>
  162.   <input
  163.     :value="props.modelValue"
  164.     @input="emit('update:modelValue', $event.target.value)"
  165.   />
  166. </template><template>
  167.   <input
  168.     :value="props.modelValue"
  169.     @input="emit('update:modelValue', $event.target.value)"
  170.   />
  171. </template><template>
  172.   <input
  173.     :value="props.modelValue"
  174.     @input="emit('update:modelValue', $event.target.value)"
  175.   />
  176. </template><template>
  177.   <input
  178.     :value="props.modelValue"
  179.     @input="emit('update:modelValue', $event.target.value)"
  180.   />
  181. </template>const removeSubscription = addSubscription(subscriptions, callback, options.detached, () => stopWatcher());<template>
  182.   <input
  183.     :value="props.modelValue"
  184.     @input="emit('update:modelValue', $event.target.value)"
  185.   />
  186. </template><template>
  187.   <input
  188.     :value="props.modelValue"
  189.     @input="emit('update:modelValue', $event.target.value)"
  190.   />
  191. </template><template>
  192.   <input
  193.     :value="props.modelValue"
  194.     @input="emit('update:modelValue', $event.target.value)"
  195.   />
  196. </template><template>
  197.   <input
  198.     :value="props.modelValue"
  199.     @input="emit('update:modelValue', $event.target.value)"
  200.   />
  201. </template><template>
  202.   <input
  203.     :value="props.modelValue"
  204.     @input="emit('update:modelValue', $event.target.value)"
  205.   />
  206. </template><template>
  207.   <input
  208.     :value="props.modelValue"
  209.     @input="emit('update:modelValue', $event.target.value)"
  210.   />
  211. </template>const stopWatcher = scope.run(() => watch(() => pinia.state.value[$id], (state) => {<template>
  212.   <input
  213.     :value="props.modelValue"
  214.     @input="emit('update:modelValue', $event.target.value)"
  215.   />
  216. </template><template>
  217.   <input
  218.     :value="props.modelValue"
  219.     @input="emit('update:modelValue', $event.target.value)"
  220.   />
  221. </template><template>
  222.   <input
  223.     :value="props.modelValue"
  224.     @input="emit('update:modelValue', $event.target.value)"
  225.   />
  226. </template><template>
  227.   <input
  228.     :value="props.modelValue"
  229.     @input="emit('update:modelValue', $event.target.value)"
  230.   />
  231. </template><template>
  232.   <input
  233.     :value="props.modelValue"
  234.     @input="emit('update:modelValue', $event.target.value)"
  235.   />
  236. </template><template>
  237.   <input
  238.     :value="props.modelValue"
  239.     @input="emit('update:modelValue', $event.target.value)"
  240.   />
  241. </template><template>
  242.   <input
  243.     :value="props.modelValue"
  244.     @input="emit('update:modelValue', $event.target.value)"
  245.   />
  246. </template><template>
  247.   <input
  248.     :value="props.modelValue"
  249.     @input="emit('update:modelValue', $event.target.value)"
  250.   />
  251. </template>if (options.flush === 'sync' ? isSyncListening : isListening) {<template>
  252.   <input
  253.     :value="props.modelValue"
  254.     @input="emit('update:modelValue', $event.target.value)"
  255.   />
  256. </template><template>
  257.   <input
  258.     :value="props.modelValue"
  259.     @input="emit('update:modelValue', $event.target.value)"
  260.   />
  261. </template><template>
  262.   <input
  263.     :value="props.modelValue"
  264.     @input="emit('update:modelValue', $event.target.value)"
  265.   />
  266. </template><template>
  267.   <input
  268.     :value="props.modelValue"
  269.     @input="emit('update:modelValue', $event.target.value)"
  270.   />
  271. </template><template>
  272.   <input
  273.     :value="props.modelValue"
  274.     @input="emit('update:modelValue', $event.target.value)"
  275.   />
  276. </template><template>
  277.   <input
  278.     :value="props.modelValue"
  279.     @input="emit('update:modelValue', $event.target.value)"
  280.   />
  281. </template><template>
  282.   <input
  283.     :value="props.modelValue"
  284.     @input="emit('update:modelValue', $event.target.value)"
  285.   />
  286. </template><template>
  287.   <input
  288.     :value="props.modelValue"
  289.     @input="emit('update:modelValue', $event.target.value)"
  290.   />
  291. </template><template>
  292.   <input
  293.     :value="props.modelValue"
  294.     @input="emit('update:modelValue', $event.target.value)"
  295.   />
  296. </template><template>
  297.   <input
  298.     :value="props.modelValue"
  299.     @input="emit('update:modelValue', $event.target.value)"
  300.   />
  301. </template>callback({<template>
  302.   <input
  303.     :value="props.modelValue"
  304.     @input="emit('update:modelValue', $event.target.value)"
  305.   />
  306. </template><template>
  307.   <input
  308.     :value="props.modelValue"
  309.     @input="emit('update:modelValue', $event.target.value)"
  310.   />
  311. </template><template>
  312.   <input
  313.     :value="props.modelValue"
  314.     @input="emit('update:modelValue', $event.target.value)"
  315.   />
  316. </template><template>
  317.   <input
  318.     :value="props.modelValue"
  319.     @input="emit('update:modelValue', $event.target.value)"
  320.   />
  321. </template><template>
  322.   <input
  323.     :value="props.modelValue"
  324.     @input="emit('update:modelValue', $event.target.value)"
  325.   />
  326. </template><template>
  327.   <input
  328.     :value="props.modelValue"
  329.     @input="emit('update:modelValue', $event.target.value)"
  330.   />
  331. </template><template>
  332.   <input
  333.     :value="props.modelValue"
  334.     @input="emit('update:modelValue', $event.target.value)"
  335.   />
  336. </template><template>
  337.   <input
  338.     :value="props.modelValue"
  339.     @input="emit('update:modelValue', $event.target.value)"
  340.   />
  341. </template><template>
  342.   <input
  343.     :value="props.modelValue"
  344.     @input="emit('update:modelValue', $event.target.value)"
  345.   />
  346. </template><template>
  347.   <input
  348.     :value="props.modelValue"
  349.     @input="emit('update:modelValue', $event.target.value)"
  350.   />
  351. </template><template>
  352.   <input
  353.     :value="props.modelValue"
  354.     @input="emit('update:modelValue', $event.target.value)"
  355.   />
  356. </template><template>
  357.   <input
  358.     :value="props.modelValue"
  359.     @input="emit('update:modelValue', $event.target.value)"
  360.   />
  361. </template>storeId: $id,<template>
  362.   <input
  363.     :value="props.modelValue"
  364.     @input="emit('update:modelValue', $event.target.value)"
  365.   />
  366. </template><template>
  367.   <input
  368.     :value="props.modelValue"
  369.     @input="emit('update:modelValue', $event.target.value)"
  370.   />
  371. </template><template>
  372.   <input
  373.     :value="props.modelValue"
  374.     @input="emit('update:modelValue', $event.target.value)"
  375.   />
  376. </template><template>
  377.   <input
  378.     :value="props.modelValue"
  379.     @input="emit('update:modelValue', $event.target.value)"
  380.   />
  381. </template><template>
  382.   <input
  383.     :value="props.modelValue"
  384.     @input="emit('update:modelValue', $event.target.value)"
  385.   />
  386. </template><template>
  387.   <input
  388.     :value="props.modelValue"
  389.     @input="emit('update:modelValue', $event.target.value)"
  390.   />
  391. </template><template>
  392.   <input
  393.     :value="props.modelValue"
  394.     @input="emit('update:modelValue', $event.target.value)"
  395.   />
  396. </template><template>
  397.   <input
  398.     :value="props.modelValue"
  399.     @input="emit('update:modelValue', $event.target.value)"
  400.   />
  401. </template><template>
  402.   <input
  403.     :value="props.modelValue"
  404.     @input="emit('update:modelValue', $event.target.value)"
  405.   />
  406. </template><template>
  407.   <input
  408.     :value="props.modelValue"
  409.     @input="emit('update:modelValue', $event.target.value)"
  410.   />
  411. </template><template>
  412.   <input
  413.     :value="props.modelValue"
  414.     @input="emit('update:modelValue', $event.target.value)"
  415.   />
  416. </template><template>
  417.   <input
  418.     :value="props.modelValue"
  419.     @input="emit('update:modelValue', $event.target.value)"
  420.   />
  421. </template>type: MutationType.direct,<template>
  422.   <input
  423.     :value="props.modelValue"
  424.     @input="emit('update:modelValue', $event.target.value)"
  425.   />
  426. </template><template>
  427.   <input
  428.     :value="props.modelValue"
  429.     @input="emit('update:modelValue', $event.target.value)"
  430.   />
  431. </template><template>
  432.   <input
  433.     :value="props.modelValue"
  434.     @input="emit('update:modelValue', $event.target.value)"
  435.   />
  436. </template><template>
  437.   <input
  438.     :value="props.modelValue"
  439.     @input="emit('update:modelValue', $event.target.value)"
  440.   />
  441. </template><template>
  442.   <input
  443.     :value="props.modelValue"
  444.     @input="emit('update:modelValue', $event.target.value)"
  445.   />
  446. </template><template>
  447.   <input
  448.     :value="props.modelValue"
  449.     @input="emit('update:modelValue', $event.target.value)"
  450.   />
  451. </template><template>
  452.   <input
  453.     :value="props.modelValue"
  454.     @input="emit('update:modelValue', $event.target.value)"
  455.   />
  456. </template><template>
  457.   <input
  458.     :value="props.modelValue"
  459.     @input="emit('update:modelValue', $event.target.value)"
  460.   />
  461. </template><template>
  462.   <input
  463.     :value="props.modelValue"
  464.     @input="emit('update:modelValue', $event.target.value)"
  465.   />
  466. </template><template>
  467.   <input
  468.     :value="props.modelValue"
  469.     @input="emit('update:modelValue', $event.target.value)"
  470.   />
  471. </template><template>
  472.   <input
  473.     :value="props.modelValue"
  474.     @input="emit('update:modelValue', $event.target.value)"
  475.   />
  476. </template><template>
  477.   <input
  478.     :value="props.modelValue"
  479.     @input="emit('update:modelValue', $event.target.value)"
  480.   />
  481. </template>events: debuggerEvents,<template>
  482.   <input
  483.     :value="props.modelValue"
  484.     @input="emit('update:modelValue', $event.target.value)"
  485.   />
  486. </template><template>
  487.   <input
  488.     :value="props.modelValue"
  489.     @input="emit('update:modelValue', $event.target.value)"
  490.   />
  491. </template><template>
  492.   <input
  493.     :value="props.modelValue"
  494.     @input="emit('update:modelValue', $event.target.value)"
  495.   />
  496. </template><template>
  497.   <input
  498.     :value="props.modelValue"
  499.     @input="emit('update:modelValue', $event.target.value)"
  500.   />
  501. </template><template>
  502.   <input
  503.     :value="props.modelValue"
  504.     @input="emit('update:modelValue', $event.target.value)"
  505.   />
  506. </template><template>
  507.   <input
  508.     :value="props.modelValue"
  509.     @input="emit('update:modelValue', $event.target.value)"
  510.   />
  511. </template><template>
  512.   <input
  513.     :value="props.modelValue"
  514.     @input="emit('update:modelValue', $event.target.value)"
  515.   />
  516. </template><template>
  517.   <input
  518.     :value="props.modelValue"
  519.     @input="emit('update:modelValue', $event.target.value)"
  520.   />
  521. </template><template>
  522.   <input
  523.     :value="props.modelValue"
  524.     @input="emit('update:modelValue', $event.target.value)"
  525.   />
  526. </template><template>
  527.   <input
  528.     :value="props.modelValue"
  529.     @input="emit('update:modelValue', $event.target.value)"
  530.   />
  531. </template>}, state);<template>
  532.   <input
  533.     :value="props.modelValue"
  534.     @input="emit('update:modelValue', $event.target.value)"
  535.   />
  536. </template><template>
  537.   <input
  538.     :value="props.modelValue"
  539.     @input="emit('update:modelValue', $event.target.value)"
  540.   />
  541. </template><template>
  542.   <input
  543.     :value="props.modelValue"
  544.     @input="emit('update:modelValue', $event.target.value)"
  545.   />
  546. </template><template>
  547.   <input
  548.     :value="props.modelValue"
  549.     @input="emit('update:modelValue', $event.target.value)"
  550.   />
  551. </template><template>
  552.   <input
  553.     :value="props.modelValue"
  554.     @input="emit('update:modelValue', $event.target.value)"
  555.   />
  556. </template><template>
  557.   <input
  558.     :value="props.modelValue"
  559.     @input="emit('update:modelValue', $event.target.value)"
  560.   />
  561. </template><template>
  562.   <input
  563.     :value="props.modelValue"
  564.     @input="emit('update:modelValue', $event.target.value)"
  565.   />
  566. </template><template>
  567.   <input
  568.     :value="props.modelValue"
  569.     @input="emit('update:modelValue', $event.target.value)"
  570.   />
  571. </template>}<template>
  572.   <input
  573.     :value="props.modelValue"
  574.     @input="emit('update:modelValue', $event.target.value)"
  575.   />
  576. </template><template>
  577.   <input
  578.     :value="props.modelValue"
  579.     @input="emit('update:modelValue', $event.target.value)"
  580.   />
  581. </template><template>
  582.   <input
  583.     :value="props.modelValue"
  584.     @input="emit('update:modelValue', $event.target.value)"
  585.   />
  586. </template><template>
  587.   <input
  588.     :value="props.modelValue"
  589.     @input="emit('update:modelValue', $event.target.value)"
  590.   />
  591. </template><template>
  592.   <input
  593.     :value="props.modelValue"
  594.     @input="emit('update:modelValue', $event.target.value)"
  595.   />
  596. </template><template>
  597.   <input
  598.     :value="props.modelValue"
  599.     @input="emit('update:modelValue', $event.target.value)"
  600.   />
  601. </template>}, assign({}, $subscribeOptions, options)));<template>
  602.   <input
  603.     :value="props.modelValue"
  604.     @input="emit('update:modelValue', $event.target.value)"
  605.   />
  606. </template><template>
  607.   <input
  608.     :value="props.modelValue"
  609.     @input="emit('update:modelValue', $event.target.value)"
  610.   />
  611. </template><template>
  612.   <input
  613.     :value="props.modelValue"
  614.     @input="emit('update:modelValue', $event.target.value)"
  615.   />
  616. </template><template>
  617.   <input
  618.     :value="props.modelValue"
  619.     @input="emit('update:modelValue', $event.target.value)"
  620.   />
  621. </template><template>
  622.   <input
  623.     :value="props.modelValue"
  624.     @input="emit('update:modelValue', $event.target.value)"
  625.   />
  626. </template><template>
  627.   <input
  628.     :value="props.modelValue"
  629.     @input="emit('update:modelValue', $event.target.value)"
  630.   />
  631. </template>return removeSubscription;<template>
  632.   <input
  633.     :value="props.modelValue"
  634.     @input="emit('update:modelValue', $event.target.value)"
  635.   />
  636. </template><template>
  637.   <input
  638.     :value="props.modelValue"
  639.     @input="emit('update:modelValue', $event.target.value)"
  640.   />
  641. </template><template>
  642.   <input
  643.     :value="props.modelValue"
  644.     @input="emit('update:modelValue', $event.target.value)"
  645.   />
  646. </template><template>
  647.   <input
  648.     :value="props.modelValue"
  649.     @input="emit('update:modelValue', $event.target.value)"
  650.   />
  651. </template>},<template>
  652.   <input
  653.     :value="props.modelValue"
  654.     @input="emit('update:modelValue', $event.target.value)"
  655.   />
  656. </template><template>
  657.   <input
  658.     :value="props.modelValue"
  659.     @input="emit('update:modelValue', $event.target.value)"
  660.   />
  661. </template><template>
  662.   <input
  663.     :value="props.modelValue"
  664.     @input="emit('update:modelValue', $event.target.value)"
  665.   />
  666. </template><template>
  667.   <input
  668.     :value="props.modelValue"
  669.     @input="emit('update:modelValue', $event.target.value)"
  670.   />
  671. </template>$dispose,<template>
  672.   <input
  673.     :value="props.modelValue"
  674.     @input="emit('update:modelValue', $event.target.value)"
  675.   />
  676. </template><template>
  677.   <input
  678.     :value="props.modelValue"
  679.     @input="emit('update:modelValue', $event.target.value)"
  680.   />
  681. </template>};
复制代码
这里的第10行,用 watch 对状态的属性进行了监听,然后写记录(timeline)。
pinia 不仅没有阻止我们直接改属性,还很贴心的做了记录。
pinia 的 timeline

以前就一直对这个 timeline 非常好奇,想知道记录的是什么,但是奈何各种原因总是看不到,现在vue 推出了,终于看到了。
2.png

这里的记录非常详细,有状态名称、动作、属性名称、新旧值、触发时间等等信息,只是有个小问题,到底是谁改了状态? 没发现有定位代码位置的功能。
reactive 怎么算?

好了,终于到了比较有争议的 reactive 了,大家有没有等着急?
首先 reactive 的本质是 Proxy,而 Proxy 是代理,这个想必大家都知道,所以我们可以设置这样的代码:
  1. const 张三 = {<template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template>name:'zhangsan',<template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>age:20}const 张三的代理 = reactive(张三)const setAge = (age) => {<template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template>if (age < 0) {<template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template><template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template>// 年龄不能是负数<template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>}<template>
  32.   <input
  33.     :value="props.modelValue"
  34.     @input="emit('update:modelValue', $event.target.value)"
  35.   />
  36. </template>// 其他验证<template>
  37.   <input
  38.     :value="props.modelValue"
  39.     @input="emit('update:modelValue', $event.target.value)"
  40.   />
  41. </template><template>
  42.   <input
  43.     :value="props.modelValue"
  44.     @input="emit('update:modelValue', $event.target.value)"
  45.   />
  46. </template>// 通过验证后才能赋值<template>
  47.   <input
  48.     :value="props.modelValue"
  49.     @input="emit('update:modelValue', $event.target.value)"
  50.   />
  51. </template>张三的代理.age = age}
复制代码
平时大家都是一步成,现在分成了两步,是不是就很明确了呢。
张三是一个普通的对象,没有响应性,张三的代理是 reactive 有响应性,是张三的代理。
所以,我们传递给子组件的是张三的代理,并不是张三本尊。
既然子组件根本就得不到张三的本尊,那么又何来直接修改呢?
如果说通过 emit 是间接修改(抛出事件),那么通过 reactive 也是通过代理间接修改的。
虽然一个是事件,一个是代理,但是有啥本质区别呢?事件是函数,Proxy 里的 set 也是函数呀。
同样都是没有记录(timeline)、判断、验证、限制,想怎么改就怎么改。
如果你还不理解,可以看看这个演化过程。
阶段一:参考官网里面依赖注入的推荐方式
  1. // 阶段一:按照官网里面注入的推荐方式const person = reactive({<template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template>name:'zhangsan',<template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>age:20})const setAge = (age) => {<template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template>person.age = age }// 通过 props 或者 依赖注入,把 proxyPerson 传给子组件,const proxyPerson = reactive({<template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template>// 使用 readonly 变成只读形式,只能通过 setAge 修改。<template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template>person: readonly(person),<template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>setAge})
复制代码
这样子组件只能使用 setAge 修改,代理套上 readonly 之后,通过代理的修改方式都给堵死了,是严格遵守单向数据流了吧。
阶段二:充血实体类,把数据和方法合在一起
  1. // 阶段二:充血实体类,把数据和方法合在一起const person2 = {<template>
  2.   <input
  3.     :value="props.modelValue"
  4.     @input="emit('update:modelValue', $event.target.value)"
  5.   />
  6. </template>name:'zhangsan',<template>
  7.   <input
  8.     :value="props.modelValue"
  9.     @input="emit('update:modelValue', $event.target.value)"
  10.   />
  11. </template>_age:20, // 内部成员,相当于“本尊”<template>
  12.   <input
  13.     :value="props.modelValue"
  14.     @input="emit('update:modelValue', $event.target.value)"
  15.   />
  16. </template>// set 拦截,其实也是一个函数,类似于代理。<template>
  17.   <input
  18.     :value="props.modelValue"
  19.     @input="emit('update:modelValue', $event.target.value)"
  20.   />
  21. </template>set age(age) { // 拦截设置属性<template>
  22.   <input
  23.     :value="props.modelValue"
  24.     @input="emit('update:modelValue', $event.target.value)"
  25.   />
  26. </template><template>
  27.   <input
  28.     :value="props.modelValue"
  29.     @input="emit('update:modelValue', $event.target.value)"
  30.   />
  31. </template>// 可以做验证<template>
  32.   <input
  33.     :value="props.modelValue"
  34.     @input="emit('update:modelValue', $event.target.value)"
  35.   />
  36. </template><template>
  37.   <input
  38.     :value="props.modelValue"
  39.     @input="emit('update:modelValue', $event.target.value)"
  40.   />
  41. </template>this._age = age<template>
  42.   <input
  43.     :value="props.modelValue"
  44.     @input="emit('update:modelValue', $event.target.value)"
  45.   />
  46. </template> },<template>
  47.   <input
  48.     :value="props.modelValue"
  49.     @input="emit('update:modelValue', $event.target.value)"
  50.   />
  51. </template>get age(){ // 拦截读取属性<template>
  52.   <input
  53.     :value="props.modelValue"
  54.     @input="emit('update:modelValue', $event.target.value)"
  55.   />
  56. </template><template>
  57.   <input
  58.     :value="props.modelValue"
  59.     @input="emit('update:modelValue', $event.target.value)"
  60.   />
  61. </template>return this._age<template>
  62.   <input
  63.     :value="props.modelValue"
  64.     @input="emit('update:modelValue', $event.target.value)"
  65.   />
  66. </template>}}//<template>
  67.   <input
  68.     :value="props.modelValue"
  69.     @input="emit('update:modelValue', $event.target.value)"
  70.   />
  71. </template>给子组件用const proxyPerson2 = reactive(person2)// 子组件// 表名上看是通过属性修改,但是实际上被 set 拦截了,调用的是一个函数proxyPerson2.age = 30
复制代码
在父组件里面把数据和变更方法合并,也是符合官网的建议对吧。
那么看看阶段二是不是有点眼熟?如果你熟悉 Proxy 和 reactive 内部原理的话,这不就是 reactive 内部代码的一小部分吗?
既然 reactive 都自带了这种功能,那么我们又何必自己手撸?
当然 reactive 也有点小问题,没有内置记录,不过我们可以用 watch 的 onTrigger 做记录,详细看下面:
给 Pinia 加一个定位代码的功能(支持 reactive)
小结


  • v-model + emit
    目的是实现父子组件之间,值类型数据的响应性,如果不用 emit 的话,如何实现?
  • defineModel
    语法糖(宏),封装复杂的代码,让我们使用起来更方便。
  • 状态管理
    pinia 提供了 timeline,弥补了 reactive 的不足,方便我们调试代码,提供 $state 方便我们直接赋值。
    给 Pinia 加一个定位代码的功能(支持 reactive)
  • reactive
    我觉得可以直接改,因为本身就是一个代理(Proxy),直接用就好了。
    如果外面再套一个 Proxy 有何意义呢?当然了,如果可以加上 timeline,或者是判断、验证等,那么就有意义了。
  • 数据 + 方法
    可以在方法里面做一些操作,比如验证、判断等,那么就有意义,如果是个“空”函数,除了赋值啥都没做,那么有何意义呢?

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册