vue3.0(十五)状态管理vuex和pinia

文章目录

  • 状态管理
  • vuex
    • 1. 什么情况下应该使用 Vuex
    • 2. vuex的安装
    • 3. vuex的五大属性
    • 4. vuex的五大属性在组件中的应用
    • 5. 数据持久化
  • pinia
    • 1.Pinia 对比 Vuex
    • 2.安装及引入
    • 3.三大属性
    • 4.三大属性在组件中的运用
    • 总结


状态管理

状态管理是指对Vue.js应用中的数据进行统一管理的一种机制。在前端开发中,应用程序的数据通常会被分散存储在各个组件中,这样在跨组件之间共享数据时会变得困难。而Vue状态管理就是为了解决这一问题而设计的。
解决问题:

  1. 多个视图可能都依赖于同一份状态。
  2. 来自不同视图的交互也可能需要更改同一份状态。
    Vue状态管理通过集中存储应用的状态,并提供一组API来更新和获取状态,从而实现了在多个组件中共享数据的能力。这个集中式的状态存储被称为「状态管理器」或「全局状态」。
    一个组件是一个独立的单元
    <script setup>
    import { ref } from 'vue'
    
    // 状态
    const count = ref(0)
    
    // 动作
    function increment() {
      count.value++
    }
    </script>
    
    <!-- 视图 -->
    <template>{{ count }}</template>
    
  • 状态:驱动整个应用的数据源;
  • 视图:对状态的一种声明式映射;
  • 交互:状态根据用户在视图中的输入而作出相应变更的可能方式。
    单向数据流示图

使用Vue状态管理,可以将应用的状态从组件中抽离出来,通过中央数据存储管理器来管理。这样,在不同的组件中就可以通过访问共享的状态来实现数据的一致性和同步更新。同时,由于状态的集中管理,我们可以更好地对状态进行统一的管理和控制,提高了应用的可维护性和可扩展性。

总结一下,Vue状态管理是一种集中式存储和管理Vue.js应用的数据的机制,可以通过使用Vuex库来实现。它提供了统一管理状态的能力,并且方便开发者在多个组件间共享和更新数据。通过Vue状态管理,我们可以更好地组织和维护应用的状态,提高开发效率和代码质量。

vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

1. 什么情况下应该使用 Vuex

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。
如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。
如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

2. vuex的安装

// npm 安装指令
npm install vuex@next --save
// yarn 安装指令
yarn add vuex@next --save

3. vuex的五大属性

  • state

    定义了应用程序的状态,就是要管理的数据
    存放应用程序的状态(数据),所有组件共享。它是vue实例的data属性的替代品,但是通过它存储和管理的状态,可以在整个应用程序中实现全局共享,即不同的组件可以通过定义的getter和setter访问同一状态数据

    // 初始化vuex对象
    const store = new vuex.Store({
      state: {
        // 管理数据
        count: 0
      }
    })
    
  • getters

    用于获取state中的状态,主要用于对state进行逻辑上的组合和应用,类似于vuex组件中的计算属性

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      getters: {
        doubleCount(state) {
          return state.count * 2
        }
      }
    })
    
  • mutations

    用于修改state中的数据,是唯一可以修改state的地方。mutations接收state作为第一参数,接收payload作为第二个参数,用于修改state中的状态,只能同步执行。mutation必须是同步函数。因为它们不能出来异步行为,异步行为应该放在action中处理。

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment(state) {
          state.count++
        },
        add(state, payload) {
          state.count += payload
        }
      }
    })
    
  • actions

    用于异步操作和提高mutations,在actions中可以进行任何异步操作,最后在提交到mutations中同步修改state。actions接收context作为第二个参数,其中包含了state,getters和commit等属性
    可以包含任意异步操作(例如从服务器获取数据),可以用mutations通过提交commit来修改state

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment(state) {
          state.count++
        }
      },
      actions: {
        incrementAsync(context) {
          setTimeout(() => {
            context.commit('increment')
          }, 1000)
        }
      }
    })
    
  • modules

    用于将store分割成模块,每个模块都拥有自己的state,mutations,actions,getters和子模块,以便提高应用程序的可维护性。将state,getters,mutations, sctons模块化,便于组件化和模块化开发

    const store = new Vuex.Store({
      modules: {
        cart: {
          state: {
            items: []
          },
          mutations: {
            addItem(state, item) {
              state.items.push(item)
            }
          },
          actions: {
            addAsyncItem(context, item) {
              setTimeout(() => {
                context.commit('addItem', item)
              }, 1000)
            }
          }
        }
      }
    })
    

4. vuex的五大属性在组件中的应用

  1. state
    不再是vue2.0里什么mapGetter,mapState那些复杂的获取方式,
    vue3.0里直接使用computed就可以调用vuex里的数据了。喜大普奔。
    同时注意,一点,不可以直接使用useStore()方法里的state对象,因为在输出useStore方法的数据中,state是浅灰色的。
    浅灰色只可看到,但是不可以直接使用。
    在这里插入图片描述
    store文件中的设置
    import { createStore } from 'vuex'
    export default createStore({
      state: {
        count: 1
      },
    })
    
    在组件中的应用
    <template>
     <div>{{ constA }}</div>
    </template>
    <script lang="ts">
    import { defineComponent, computed } from 'vue'
    import { useStore } from 'vuex'
    export default defineComponent({
      setup () {
        const store = useStore()
        const constA = computed(() => {
          return store.state.count
        })
        return {
          constA
        }
      }
    })
    </script>
    

注意:

  • state中的数据是自定义的,但是state属性名是固定的
  • 获取数据可以通过 store.state
  • 可以使用计算属性优化模板中获取数据的方式
  1. getters
    getter用于对store中的数据进行加工处理形成的新的数据
    不会修改store中的原数据 它只起到一个包装器的作用 将store中的数据变一种形式返回出来
    -.getter可以对store中已有的数据加工处理之后形成新的数据,类似vue的计算属性
    -.store中数据发生改变 getter中的数据也会跟着变化
    store文件中的设置
    import { createStore } from 'vuex'
    
    export default createStore({
      state: {
        count: 1
      },
      getters: {
        showCount: (state) => state.count
      },
      mutations: {
        addCount (state, step) {
          console.log(step)
          state.count += step
        }
      },
      actions: {
        updateCount (context, payload) {
          console.log(context, payload)
          // 模拟异步操作
          setTimeout(() => {
            context.commit('addCount', payload)
          }, 1000)
        }
      },
      modules: {
      }
    })
    
    在组件中的应用
    	<template>
      <div>{{ constA }}</div>
      <div>getters获取的state定义的count {{ getterCount }}</div>
      <div @click="handleAddCount">增加count</div>
    </template>
    <script lang="ts">
    import { defineComponent, ref, reactive, computed } from 'vue'
    import { useStore } from 'vuex'
    export default defineComponent({
      setup () {
        const store = useStore()
        console.log(store)
        const constA = computed(() => {
          return store.state.count
        })
        // 用计算属性可以获取vuex中的getters中的数据
        const getterCount = computed(() => {
          return store.getters.showCount
        })
        function handleAddCount () {
          store.dispatch('updateCount', 3)
          // store.commit('addCount', 2)
        }
        return {
          constA,
          handleAddCount,
          getterCount
        }
      }
    })
    </script>
    
  2. mutations
    mutations用于更变store中的数据(同步)
    store文件中的设置
    import { createStore } from 'vuex'
    export default createStore({
      state: {
        count: 1
      },
      getters: {
      },
      mutations: {
        addCount (state, step) {
          console.log(step)// 调方法的时候,传的参数
          state.count += step
        }
      },
    })
    
    在组件中的应用
    <template>
      <div>{{ constA }}</div>
      <div @click="handleAddCount">增加count</div>
    </template>
    <script lang="ts">
    import { defineComponent, ref, reactive, computed } from 'vue'
    import { useStore } from 'vuex'
    export default defineComponent({
      setup () {
        const store = useStore()
        console.log(store)
        const constA = computed(() => {
          return store.state.count
        })
        function handleAddCount () {
          // 调用mutations中的方法
          store.commit('addCount', 2)
        }
        return {
          constA,
          handleAddCount
        }
      }
    })
    </script>
    
    上述代码执行效果
    总结:
    vue3中取vuex里的数据 需要用 computed获取
    使用store.commit(“addCount”) 来触发vuex里的mutations方法
    触发mutations时传递参数:store.commit(“addCount”,2) 通过第二个参数
  3. actions
    主要用于处理异步的任务
    import { createStore } from 'vuex'
    export default createStore({
      state: {
        count: 1
      },
      getters: {
      },
      mutations: {
        addCount (state, step) {
          console.log(step)
          state.count += step
        }
      },
      actions: {
        updateCount (context, payload) {
          console.log(context, payload)
          // 模拟异步操作 payload是接收的参数
          setTimeout(() => {
           // 通过commit调用mutctions中的方法修改state中的数据
            context.commit('addCount', payload)
          }, 1000)
        }
      },
      modules: {
      }
    })
    
    在组件中应用
    <template>
      <div>{{ constA }}</div>
      <div @click="handleAddCount">增加count</div>
    </template>
    <script lang="ts">
    import { defineComponent, ref, reactive, computed } from 'vue'
    import { useStore } from 'vuex'
    export default defineComponent({
      setup () {
        const store = useStore()
        console.log(store)
        const constA = computed(() => {
          return store.state.count
        })
        function handleAddCount () {
          //使用diapatch调中store文件中的action属性中定义的异步函数
          store.dispatch('updateCount', 3)
        }
        return {
          constA,
          handleAddCount
        }
      }
    })
    </script>
    
  4. modules
  • 默认的模块( 不带命名空间 ) : 在组件或者js文件中取值或者调用对应方法时,state 区分模块,其他 getters mutations actions 都在全局(通俗讲就是不带命名空间子模块定义的state数据,即时变量名和全局state中定义的变量名相同,也可以通过模块名取到对应的值,例如:store.state.模块名.变量名),但是 getters ,mutations, actions中定义的方法或属性如果跟全局中定义的相同,那么取到的是全局的。
  • 带命名空间 namespaced: true 的模块:所有功能区分模块,更高封装度和复用(同名变量或者方法,可以在多个模块中使用)。
    modules中的user文件
    import { createStore } from 'vuex'
    export default createStore({
      state: {
        name: '迪西'
      },
    })
    
    store中index文件
    import { createStore } from 'vuex'
    // 引入模块文件
    import user from './modules/user'
    
    export default createStore({
      state: {
        count: 1
      },
      getters: {
        showCount: (state) => state.count
      },
      mutations: {
        addCount (state, step) {
          console.log(step)
          state.count += step
        }
      },
      actions: {
        updateCount (context, payload) {
          console.log(context, payload)
          // 模拟异步操作
          setTimeout(() => {
            context.commit('addCount', payload)
          }, 1000)
        }
      },
      modules: {
        user
      }
    })
    
    在组件中的应用
    <template>
      <div>{{ constA }}</div>
      <div>getters获取的state定义的count {{ getterCount }}</div>
      <div>姓名{{ name }}</div>
      <div @click="handleAddCount">增加count</div>
    </template>
    <script lang="ts">
    import { defineComponent, ref, reactive, computed } from 'vue'
    import { useStore } from 'vuex'
    export default defineComponent({
      setup () {
        const store = useStore()
        console.log(store)
        const constA = computed(() => {
          return store.state.count
        }) 
        // 引入user模块的数据
        const name = computed(() => {
          return store.state.user.name
        })
        const getterCount = computed(() => {
          return store.getters.showCount
        })
        function handleAddCount () {
          store.dispatch('updateCount', 3)
          // store.commit('addCount', 2)
        }
        return {
          constA,
          handleAddCount,
          getterCount,
          name
        }
      }
    })
    </script>
    

5. 数据持久化

问题:存储在vuex中的状态,刷新页面,会丢失。为了解决刷新页面数据丢失,才有了数据持久化。最简单的做法就是利用插件 vuex-persistedState。

  1. 安装
    cnpm install vuex-persistedState -S
    
  2. 使用
    import createPersistedState from 'vuex-persistedstate'
    const store = new Vuex.Store({
      state,
      mutations,
      actions,
      getters,
      plugins: [createPersistedState({
        storage: sessionStorage,
        key: "token"
      })]//会自动保存创建的状态。刷新还在
    })
    

pinia

1.Pinia 对比 Vuex

  • Pinia 同时支持 Vue2 以及 Vue3 ,这让同时使用两个版本的小伙伴更容易上手;
  • Pinia 中只存在 State,getter,action,剔除掉了 Vuex 中的 Mutation 及 Module;
  • Pinia 中的 action 可同时支持同步任务、异步任务;
  • 更友好的支持了 TypeScript ,无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断;
  • Pinia 在修改状态的时候不需要通过其他 api,如:vuex 需通过 commit,dispatch 来修改,所以在语法上比 vuex 更容易理解和使用灵活;
  • 由于去除掉了 Module ,无需再创建各个模块嵌套了。Vuex 中,如果数据过多,通常会通过划分模块来进行管理,而 Pinia 中,每个 Store 都是独立的,互不影响;
  • 支持服务端渲染;

2.安装及引入

yarn add pinia
// 或者使用 npm
npm install pinia

安装完 Pinia 包之后,需要在 main.js 文件中导入 createPinia 函数并将 Pinia 插件与 Vue 应用程序绑定:
代码如下(示例):

import { createApp } from 'vue';
import App from './App.vue';
// 引入 createPinia 函数
import { createPinia } from 'pinia';
 
const app = createApp(App)
// 使用 createPinia() 来创建 Pinia(根存储),并应用到整个应用中
app.use(createPinia());
app.mount('#app');

使用 createPinia() 函数创建并初始化 Pinia 插件实例,将其与 Vue 应用程序绑定使用 app.use(pinia)。

3.三大属性

Pinia 的核心概念包括状态(State)、动作(Actions)和获取器(Getters)。这些概念为你提供了一种组织和管理应用状态的方式。

  1. State

    状态是你在 store 中存储的数据。每个 Pinia store 都有自己的状态,这个状态是一个 JavaScript 对象。你可以在定义 store 时初始化状态:

    import { defineStore } from 'pinia';
    const useStore = defineStore({
      id: 'myStore',
      state: () => ({
        count: 0,
        user: null,
      }),
    });
    
  2. Actions

    动作是一种修改 store 状态的方法。在 Pinia 中,你可以在 actions 属性中定义动作:

    import { defineStore } from 'pinia';
    const useStore = defineStore({
      id: 'myStore',
      state: () => ({
        count: 0,
      }),
      actions: {
        increment() {
          this.count++;
        },
      },
    });
    
  3. Getters

    获取器是一种依赖于 store 状态并产生计算值的函数。这些值将被缓存,直到依赖的状态改变。在 Pinia 中,你可以在 getters 属性中定义获取器:

    import { defineStore } from 'pinia';
    const useStore = defineStore({
      id: 'myStore',
      state: () => ({
        count: 0,
      }),
      getters: {
        doubleCount() {
          return this.count * 2;
        },
      },
    });
    

4.三大属性在组件中的运用

store文件中的使用

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    users: [
      { 
        id: 1, 
        name: 'Alice', 
        age: 28, 
        profession: 'Engineer'
      },
      { 
        id: 2, 
        name: 'Bob', 
        age: 24, 
        profession: 'Designer'
      }
    ],
    selectedUser: null
  }),
  actions: {
    selectUser (user: any) {
      this.selectedUser = user
    }
  }
})

组件中的使用

<template>
   <ul>
    <li v-for="user in users" :key="user.id" @click="selectUser(user)">
      {{ user.name }}
    </li>
  </ul>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, computed } from 'vue'
import { useUserStore } from '../store/userStore'
export default defineComponent({
  setup () {
    const store = useUserStore()
    console.log(store)
    function selectUser (item: any) {
      store.selectUser(item);
    }
    return {
      selectUser,
      users: store.users,
    }
  }
})
</script>

上述代码执行结果

总结

Pinia 是一个轻量级且强大的状态管理库,它使得在 Vue.js 应用中管理状态变得更简单、更直观。如果你正在使用 Vue.js 构建应用,并需要一个简单易用的状态管理解决方案,那么 Pinia 是一个很好的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/751971.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【.Net】Web项目部署腾讯云

文章目录 总述前置准备docker-compose部署普通部署 参考 总述 前置准备 云服务添加端口 另有linux本身防火墙请参考&#xff1a; 【Linux】防火墙命令 需安装.Net SDK和Asp .Net Runtime 注意&#xff1a; 1、sdk也要不只是runtime 2、是Asp .Net Runtime不是.Net Runtime …

擎耀解码汽车大灯照明系统电动调节步进电机位置反馈的解决方案

在现代汽车设计中&#xff0c;智能照明系统扮演着至关重要的角色。其中&#xff0c;汽车大灯的电动调节功能不仅提高了夜间行车的安全性&#xff0c;还增强了车辆的科技感和便利性。然而&#xff0c;要实现精准的大灯角度调节&#xff0c;步进电机的位置反馈机制尤为关键。擎耀…

SpringBoot脚手架MySpringBootAPI(PgSQL+Druid+MyBatisPlus+Lombok)

MySpringBootAPI SpringBoot脚手架&#xff0c;基于SpringBootDruidPgSQLMyBatisPlusFastJSONLombok&#xff0c;其他的请自行添加和配置。 Author powered by Moshow郑锴(大狼狗) , https://zhengkai.blog.csdn.net 如何运行 1.首先确保你是JDK17&#xff0c;推荐微软的MSJDK…

《Windows API每日一练》6.4 程序测试

前面我们讨论了鼠标的一些基础知识&#xff0c;本节我们将通过一些实例来讲解鼠标消息的不同处理方式。 本节必须掌握的知识点&#xff1a; 第36练&#xff1a;鼠标击中测试1 第37练&#xff1a;鼠标击中测试2—增加键盘接口 第38练&#xff1a;鼠标击中测试3—子窗口 第39练&…

ECharts 源码代码规范

代码规范 - Apache EChartsApache ECharts&#xff0c;一款基于JavaScript的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。https://echarts.apache.org/zh/coding-standard.html 源文件 [强制] JavaScr…

基于ARM的通用的Qt移植思路

文章目录 实验环境介绍一、确认Qt版本二、确认交叉编译工具链三、配置Qt3.1、修改qmake.conf3.2、创建autoConfig.sh配置文件 四、编译安装Qt五、移植Qt安装目录六、配置Qt creator6.1、配置qmake6.2、配置GCC编译器6.3、配置G编译器6.4、配置编译器套件6.5、创建应用 七、总结…

论文速览 | IEEE Signal Processing Letters, 2024 | 基于时空上下文学习的事件相机立体深度估计

论文速览 | IEEE Signal Processing Letters, 2024 | 基于时空上下文学习的事件相机立体深度估计 1 引言 在计算机视觉领域,立体深度估计一直是一个备受关注的研究热点。传统的基于帧的方法虽然取得了长足的进步,但在处理运动模糊、低照度和平坦区域等挑战性场景时仍面临诸多…

二进制方式部署k8s集群

前置知识点 1、生产环境部署K8s集群的两种方式 • kubeadm Kubeadm是一个K8s部署工具&#xff0c;提供kubeadm init和kubeadm join&#xff0c;用于快速部署Kubernetes集群。 • 二进制包 从github下载发行版的二进制包&#xff0c;手动部署每个组件&#xff0c;组成Kub…

Linux的fread函数

fread函数 从文件中读入数据到指定的地址中 函数原型 : size_t fread(void*buff , size_t size, size_t count , FILE* stream) /* * description : 对已打开的流进行数据读取 * param ‐ ptr &#xff1a;指向 数据块的指针 * param ‐ size &#xff1a;指定读取的每…

LabVIEW编程控制ABB机械臂

使用LabVIEW编程控制ABB机械臂是一项复杂但十分有价值的任务。通过LabVIEW&#xff0c;可以实现对机械臂的精确控制和监控&#xff0c;提升自动化水平和操作效率。 1. 项目规划和硬件选型 1.1 确定系统需求 运动控制&#xff1a;确定机械臂需要执行的任务&#xff0c;如抓取、…

【总线】AXI4第四课时:握手机制详解

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣&#xff0c;那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者&#xff0c;AXI4以其高性能和高度可扩展性&#xff0c;成为了现代电子系统中不可或缺的通信桥梁…

乐观锁和悲观锁(MySQL和Java)

乐观锁和悲观锁(MySQL和Java) 在并发编程中&#xff0c;为了确保数据的一致性和完整性&#xff0c;我们通常需要使用锁机制来控制对共享资源的访问。锁主要分为两种&#xff1a;乐观锁和悲观锁。本文将详细介绍这两种锁的概念、工作原理以及它们的优缺点。 悲观锁 悲观锁(Pe…

LabVIEW电涡流检测系统

开发了一种基于LabVIEW的软件与硬件结合的电涡流检测系统&#xff0c;通过同步采样技术和编码器的协同工作&#xff0c;显著提高了大型结构物的损伤检测精度和效率&#xff0c;具有良好的应用前景和实用价值。 项目背景 传统的手持式电涡流检测方法因其速度慢、灵敏度低、准确…

根文件系统

根文件系统 1 介绍1.1 根文件系统介绍1.2 根文件系统目录1.3 常见的根文件系统 2 Buildroot 根文件系统的构建2.1 介绍2.2 依赖文件2.3 交叉编译工具2.4 构建2.4.1 配置 Target options2.4.2 配置 Toolchain2.4.3 配置 System configuration2.4.4 配置 Filesystem images2.4.5 …

微服务知识

传统架构 传统架构会出现的问题 配置烦琐&#xff0c;上线容易出错 加机器要重启 负载均衡单点 管理困难 CAP原则。 CAP原则是指在一个分布式系统中&#xff0c;Consistency&#xff08;一致性&#xff09;、Availability&#xff08;可用性&#xff09;、Partition Toleranc…

产品中心|高效能双处理器Xilinx FPGA 4通道射频收发板卡

1、产品概述 基于Xilinx XC7K325T芯片的4通道射频收发板卡&#xff0c;搭载高能效Cortex-A8内核处理器、1组16bit/2GB DDR3及1组4GB DDR3、 1组2GB Nand Flash、1路USB接口、4路高速ADC、4路高速DAC&#xff0c;支持外触发&#xff0c;外时钟。用于FPGA程序加载板卡工作温度范…

Zynq7000系列FPGA中的DMA控制器简介(一)

DMA控制器&#xff08;DMAC&#xff09;使用64位AXI主接口来执行与系统存储器和PL外围设备之间的DMA数据传输&#xff0c;操作频率同CPU_2x的时钟速率。传输由DMA指令执行引擎控制。DMA引擎运行在一个小指令集上&#xff0c;该指令集提供了一种灵活的指定DMA传输的方法。这种方…

激光雷达数据处理

激光雷达技术以其高精度、高效率的特点&#xff0c;已经成为地表特征获取、地形建模、环境监测等领域的重要工具。掌握激光雷达数据处理技能&#xff0c;不仅可以提升工作效率&#xff0c;还能够有效提高数据的质量和准确性&#xff0c;为决策提供可靠的数据支持。 第一章、激…

STM32_hal库学习(3)-OLED显示

硬件&#xff1a;stm32f103c8t6&#xff0c;四脚oled 四脚OLED用的是iic通讯协议&#xff0c;什么是IIC通讯协议&#xff1f;具体可看这篇文章。 stm32中IIC通讯协议-CSDN博客 既然了解了iic协议&#xff0c;接下来我们就利用stm32cubemx来配置oled。 1.新建一个工程 2.然…

愁煞了,UI设计师是闷葫芦,会干不会说,该咋办呢?

Hi&#xff0c;我是大千UI工场&#xff0c;经常有粉丝反映做好设计&#xff0c;不知道咋给客户和团队小伙伴阐述&#xff0c;传达设计里面&#xff0c;换言之就是设计师有必要提升表达能力&#xff0c;该如何提升。 UI设计师需要提升语言表达能力的原因有以下几点&#xff1a;…