在5分钟内学习Vuex

This tutorial will give you a basic understanding of Vuex by building a plan-making application. A user can type in activities and then vote how much they like/dislike them.

本教程将通过构建计划制定应用程序使您对Vuex有基本的了解。 用户可以输入活动,然后投票他们喜欢/不喜欢他们的程度。

Once you've read this tutorial, you can check out our free Vuex course on Scrimba, if you're interested in learning more.

阅读本教程后,如果您想了解更多信息,可以查看我们在Scrimba上免费Vuex课程

What is Vuex? From Vue's official documentation

什么是Vuex? 从Vue的官方文档中

Vuex is a state management pattern + library for Vue.js applications.
It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

This course assumes that you're somewhat familiar with Vue and we will briefly touch on features like props, components and bindings, but will not review them in great detail. If you'd like to have a quick primer on Vue, feel free to check out this course on Scrimba.

本课程假定您对Vue有点熟悉,我们将简要介绍一下props ,组件和绑定之类的功能,但不会详细介绍它们。 如果您想快速了解Vue,请随时在Scrimba上查看本课程

设置 (The setup)

At Scrimba, complicated setups are something we just don't do.For this tutorial, we've created a simple HTML file where everything can be written. Feel free to write your own CSS or just copy it from this playground

在Scrimba,我们只是不需要复杂的设置。在本教程中,我们创建了一个简单HTML文件,可以编写所有内容。 随意编写自己CSS或从此游乐场复制它

Vue and Vuex libraries are imported via CDN using <script> tags:

Vue和Vuex库是使用<script>标签通过CDN导入的:

<!DOCTYPE html>
<html lang="en">
  <head>

    <title>Activity Voter</title>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuex/dist/vuex.js"></script>
    <style>
      /*
        ADD CSS HERE
      */
    </style>
  </head>
  <body>
    <div id="app"></div>
  </body>

  <script>
    /*
      ADD VUE CODE HERE
    */
  </script>
</html>

Alternatively, you can also experiment with the code in this Vue Scrimba playground Just remember to relink the playground to your own account.

另外,您也可以在Vue Scrimba游乐场中试用代码,只需记住将游乐场重新链接到您自己的帐户即可。

应用计划 (App plan)

We're going to build a voting app, that works especially well when you're in a group of friends not knowing what to do and you have to consider all the options.

我们将构建一个投票应用程序,当您在一群不知道该做什么的朋友中并且必须考虑所有选项时,该应用程序会特别好用。

The functionality will consist of a user being able to type in an activity and then each activity will have a vote up and down button to count up the totals.

该功能将包括用户能够输入活动,然后每个活动将具有向上和向下投票按钮以计算总数。

入门 (Getting started)

First, let's quickly mock our app up in HTML. We will use this layout to then extract into a separate component and we will add functionality for the layout to come to life.

首先,让我们快速使用HTML模拟我们的应用程序。 我们将使用此布局将其提取到一个单独的组件中,并将添加使该布局生效的功能。

<div id="app">
  <h1>Activity voter</h1>
  <form>
    <input type="text" placeholder="Add Activity" />
    <button id="button">Add Activity</button>
  </form>
  <ul>
    <li>
      <span>
Go Snowboarding</span>
<span>?</span>
        <button>?</button>
        5
        <button>?</button>
      </span>
    </li>
  </ul>
</div>

使用一些基本数据添加Vuex存储 (Add Vuex store with some basic data)

Vuex starts with the store. The store is where we keep (store) our state.

Vuex从商店开始。 商店是我们保存(存储)状态的地方。

<script>
  Vue.use(Vuex);

  const store = new Vuex.Store({

  });

  new Vue({
    el: "#app",
    store
  });
</script>

Let's also add some hard-coded data to the store, that will include one activity and an array with one emoji to display our feelings towards the activity.

我们还向商店添加一些硬编码数据,其中包括一个活动和一个带有一个表情符号的数组,以显示我们对该活动的感受。

<script>
  Vue.use(Vuex);

  const store = new Vuex.Store({
    state: {
      activities: [{ name: "go snowboarding", rating: 5 }],
      emojis: ["?"]
    }
  });

  new Vue({
    el: "#app",
    store
  });
</script>

To allow our state to change reactively, we can use Vuex mapState to handle computed state properties for us.

为了让我们的状态做出React性的改变,我们可以使用Vuex mapState为我们处理计算后的状态属性。

new Vue({
    el: "#app",
    store,
    computed: Vuex.mapState(["activities", "emojis"])
  });

添加组件 (Add component)

Now we have activities inside our state. Let's render a separate component for each of those activities. Each one will need activity and emojis props.

现在,我们在州内开展活动。 让我们为每个活动呈现一个单独的组件。 每个人都需要activityemojis道具。

Vue.component("activity-item", {
  props: ["activity", "emojis"],
  template: `
    <li>
      <span>{{ activity.name }}
        <span>{{ emojis[0] }}</span>
        <button>?</button>
        {{activity.rating}}
        <button>?</button>
      </span>
    </li>
    `
});

Inside app we can now use our newly created component with all the appropriate bindings for activity and emojis. As a quick reminder, if we want to loop over an array and display a component for each item in an array, in Vue, we can use v-for binding.

app内部,我们现在可以将新创建​​的组件与activity和表情符号的所有适当绑定一起使用。 快速提醒一下,如果我们要遍历数组并显示数组中每个项目的组件,则可以在Vue中使用v-for绑定。

<div id="app">
  <h1>Activity voter</h1>
  <form>
    <input type="text" placeholder="Add Activity" />
    <button id="button">Add Activity</button>
  </form>
  <ul>
    <activity-item
      v-for="item in activities"
      v-bind:activity="item"
      v-bind:emojis="emojis"
      v-bind:key="item.name">
</activity-item>

</ul>
</div>

添加突变以存储 (Add mutations to store)

If we want to update the store in Vuex, we can use mutations. At the moment we will just console.log that a mutation happened and we will implement it afterwards.

如果要更新Vuex中的商店,可以使用突变。 此刻,我们将只是console.log发生了突变,然后将其实现。

const store = new Vuex.Store({
  state: {
    activities: [
      { name: "go snowboarding", rating: 5 },
    ],
    emojis: ["?"]
  },
  mutations: {
    increment(state, activityName) {
      console.log('increment');
    },
    decrement(state, activityName) {
      console.log('decrement');
    },
  }
});

How do we trigger a mutation? We call a commit function on $store with the name of mutations we want to be executed. Any arguments after the name of a mutation are treated as arguments to a committed mutation.

我们如何触发突变? 我们在$store上调用一个commit函数,其名称为我们想要执行的突变。 突变名称之后的任何参数都将视为已落实突变的参数。

new Vue({
  el: "#app",
  store,
  data() {
    return {
      activityName: ""
    };
  },
  computed: Vuex.mapState(["activities", "emojis"]),
  methods: {
    increment(activityName) {
      this.$store.commit("increment", activityName);
    },
    decrement(activityName) {
      this.$store.commit("decrement", activityName);
    }
  }
});

向组件添加功能 (Add functionality to component)

Each activity-item has voting buttons that need to increment and decrement on click of a button. We can pass these functions as props. Let's now bind our methods to props.

每个activity-item都有投票按钮,单击按钮时需要incrementdecrement 。 我们可以将这些功能作为道具传递。 现在让我们将方法绑定到道具。

<activity-item
  v-for="item in activities"
  v-bind:increment="increment"
  v-bind:decrement="decrement"
  v-bind:activity="item"
  v-bind:emojis="emojis"
  v-bind:key="item.name">
</activity-item>

Let's also not forget to provide activity.name as an argument to both.

我们也不要忘记提供activity.name作为两者的参数。

Vue.component("activity-item", {
  props: ["activity", "emojis", "increment", "decrement"],
  template: `
    <li>
      <span>{{ activity.name }}
          <span>{{ emojis[0] }}</span>
          <button @click="decrement(activity.name)">?</button>
          {{activity.rating}}
          <button @click="increment(activity.name)">?</button>
      </span>
    </li>
    `
});

And there we go! The flow is working. We can see the console.log statement in the console.

然后我们去了! 流程正在运行。 我们可以在console.log中看到console.log语句。

机具柜台 (Implement counter)

Let's implement the counter. First, we need to find an activity by its name, and then update its rating.

让我们实现计数器。 首先,我们需要按活动名称查找活动,然后更新其评分。

mutations: {
    increment(state, activityName) {
      state.activities
        .filter(activity => activity.name === `${activityName}`)
        .map(activity => activity.rating++);
    },
    decrement(state, activityName) {
      state.activities
        .filter(activity => activity.name === `${activityName}`)
        .map(activity => activity.rating--);
    }
  }

Perfect, we can now vote on activities.

完美,我们现在可以对活动进行投票。

使用表单输入来添加活动 (Use form input to add activity)

But of course, we need to be able to add activities too.

但是,当然,我们也需要能够添加活动。

Let's create a mutation to the store, that would add an activity to the list of existing activities, with a name that we will later get from the input and a default rating of 0.

让我们为商店创建一个变体,该变体会将一个活动添加到现有活动的列表中,其名称将在稍后从输入中获得,默认等级为0。

mutations: {
    ...
    addActivity(state, name) {
      state.activities.push({ name, rating: 0 });
    }
  }

Inside methods, we can commit a new activity to the store.

在方法内部,我们可以向商店提交新活动。

methods: {
    ...
    addActivity(activityName) {
      this.$store.commit("addActivity", activityName);
    }
  }

实施表格提交 (Implement form submission)

Let's wire up the submit function to our HTML form.

让我们将Submit函数连接到我们HTML表单。

<form @submit="onSubmit">
  <input type="text" placeholder="Add Activity" v-model="activityName" />
  <button id="button">Add Activity</button>
</form>

We can now add our submit function to methods. Inside, we're going to use our existing addActivity method and in the end, reset activityName in the input field to an empty string.

现在,我们可以将Submit函数添加到方法中。 在内部,我们将使用现有的addActivity方法,最后将输入字段中的activityName重置为空字符串。

methods: {
    ...
    onSubmit(e) {
      e.preventDefault();
      this.addActivity(this.activityName);
      this.activityName = "";
    }
  }

We call e.preventDefault() to avoid the form from reloading on each addition of a new activity.

我们调用e.preventDefault()来避免在每次添加新活动时重新加载表单。

All the counters now work and the field gets updated. It does look a bit strange, that we have only one emotion for all the activities, no matter what their rating is.

现在所有计数器都工作,并且该字段已更新。 看起来确实有些奇怪,我们对所有活动都只有一种情感,无论它们的评分是多少。

Let's rewrite emojis into an object with some description of what moods they are meant to reflect and clean up existing state, so we start from no activities.

让我们将表情符号重写为一个对象,其中描述了它们旨在反映和清除现有状态的心情,因此我们从没有任何活动开始。

state: {
    activities: [],
    emojis: { yay: "?", nice: "?", meh: "?", argh: "?", hateIt: "?"}
},
...

And as a finishing touch, we can display different emojis depending on the rating an activity has.

最后,我们可以根据活动的等级显示不同的表情符号。

Vue.component("activity-item", {
  props: ["activity", "emojis", "increment", "decrement"],
  template: `
    <li>
      <span>{{ activity.name }}
        <span v-if="activity.rating <= -5">{{ emojis.hateIt }}</span>
        <span v-else-if="activity.rating <= -3">{{ emojis.argh }}</span>
        <span v-else-if="activity.rating < 3">{{ emojis.meh }}</span>
        <span v-else-if="activity.rating < 5">{{ emojis.nice }}</span>
        <span v-else>{{ emojis.yay }}</span>
        <button @click="decrement(activity.name)">?</button>
          {{activity.rating}}
        <button @click="increment(activity.name)">?</button>
      </span>
    </li>
    `
});

We start with a blank app, which is what we wanted.

我们从一个空白的应用程序开始,这就是我们想要的。

And now if we add back the two activities we used to have in the app, vote on the ratings we have emojis that reflect how we feel about the activities!

现在,如果我们将以前在应用程序中拥有的两个活动加回去,请对具有表情符号的评分进行投票,以反映我们对活动的感觉!

You can check out the full code here.

您可以在此处查看完整的代码

翻译自: https://www.freecodecamp.org/news/learn-vuex-in-5-minutes/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值