单向/双向数据流最详解

聊天记录, 网友们的思考

你如果只是无聊翻翻, 可以直接看最底下的聊天记录, 看看网友们的思考: 聊天记录

单向数据流概念

单向数据流: 数据的流动是单向的,从组件的角度看,只能从上到下(祖到孙,或父到子,一个意思),不能从上到下。

更详细的说就是,上游的数据在上游才有可改权,下游的数据是收上游控制的,下游不能修改上游的数据。

单向数据流案例

下面是单向数据流的vue代码 (我也是react重度用户,反正会react的玩家基本都看得懂vue, 所以vue受众度更广, 就直接用vue了)

child.vue

javascript 复制代码
<template>
  <div>
    <button @click="clickBtn" class='btn-item'>hi~</button>
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  setup() {
    const clickBtn = () => {
      ctx.emit('on-change', 'hi~');
    };
    return {
      clickBtn,
    };
  },
});
</script>

parent.vue

javascript 复制代码
<template>
  <div>
    <emit-child @on-change='onEmitMessage' />
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import EmitChild from './Child.vue';

export default defineComponent({
  components: {
    EmitChild,
  },
  setup() {
    const message = ref('');
    const onEmitMessage = (newMessage) => {
      console.log('newMessage', newMessage);
      message.value = newMessage;
    };
    return {
      onEmitMessage,
    };
  },
});
</script>

子组件通过emit通知父组件,父组件接收到消息后,可以做一些事情,如:修改自己组件内部的状态。而不是子组件直接修改父组件。这就是单向数据流。

注: 网上很多误导性的文章说v-modal是双向数据流,但实际上v-modal也是emit的语法糖, 本质也是单向数据流

双向数据流案例

这里就是为了展示双向数据流而硬写的了...

child.vue

javascript 复制代码
<template>
  <div>
    <button @click="clickBtn" class='btn-item'>hi~</button>
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  props: ['parentState'],
  setup(props) {
    const clickBtn = () => {
      // parentState是ref, 所以修改值相对于功能而言是有效的
      props.parentState.message = 'hi~';
    };
    return {
      clickBtn,
    };
  },
});
</script>

进一步抽象

抽象能力强的同学可以类比为纯函数和副作用函数:

纯函数 (类似遵循单向数据流的组件):

javascript 复制代码
const state = {
  message: '',
};

// 纯函数相当于纯组件, 对外界没有多余的影响, 你自己定制行为, 通过参数传进去
// 这就是单向数据流的好处, 用这个纯组件时, 对外界没有影响, 不需要担心任何问题(降低开发的心智负担)
const pureFn = (onEmitMessage) => {
  setTimeout(() => {
    onEmitMessage('hi~');
  }, 1000);
};

pureFn(newMessage => {
  state.message = newMessage;
});

// 多次调用, 爱干嘛就干嘛, 数据传递一目了然, 没有心智负担
pureFn(message => {
  console.log('newMessage', newMessage);
});

副作用函数 (类似双向数据流的组件):

javascript 复制代码
const state = {
  message: '',
};

// 卧槽, 你这么写, 还得记住这个函数什么时候会对外界做出什么影响, 心智负担太大了
// 一个是每次调用时都有心智负担, 一个是这个函数中, 到底对外界做了哪些影响...
const effectFn = () => {
  setTimeout(() => {
    state.message = 'hi~';
  }, 1000);
};

// 心智负担: 调用一次, 这时对state.message修改值了, 对xxx也影响了? 忘了, 草
effectFn();

// 心智负担: 调用一次, 这时对state.message修改值了, 对xxx也影响了? 忘了, 草
effectFn();

// 心智负担: 调用一次, 这时对state.message修改值了, 对xxx也影响了? 忘了, 草
effectFn();

思想

单向数据流就是一种更好的开发范式, 函数式编程(纯函数编程)也是。开发中持续遵循这个原则, 即使有少数烂代码没有遵循, 心智负担也是很小的。

聊天记录更生动

截图里那个最爱bb的人,就是我...

相关推荐
艾小逗1 小时前
vue3中的effectScope有什么作用,如何使用?如何自动清理
前端·javascript·vue.js
小小小小宇4 小时前
手写 zustand
前端
Hamm4 小时前
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
前端·vue.js·typescript
小小小小宇5 小时前
前端国际化看这一篇就够了
前端
大G哥5 小时前
PHP标签+注释+html混写+变量
android·开发语言·前端·html·php
whoarethenext5 小时前
html初识
前端·html
小小小小宇5 小时前
一个功能相对完善的前端 Emoji
前端
m0_627827525 小时前
vue中 vue.config.js反向代理
前端
Java&Develop5 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器
白泽talk5 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务