返回博客首页
← 所有文章

Vue.js NativeScript 应用中使用 Vuex 的键值本地存储

2018 年 6 月 12 日 — 作者:Nic Raboy

如果你曾经构建过 Vue.js 应用程序,无论是 Web 还是移动应用程序,在搜索数据存储相关信息时,你可能遇到过 Vuex。在 Web 开发中,围绕 Vuex 的常见教程包括浏览器本地存储或类似方法,其中 Vuex 处理组件之间所有状态规则。

现在 NativeScript 支持 Vue.js,这为移动开发打开了新的大门,但如何在这些情况下处理数据呢?NativeScript 不使用浏览器,因此本地存储不是一种选择。

我们将了解如何使用 NativeScript 和 Vue.js 管理使用 NativeScript 和 Vue.js 构建的 Android 和 iOS 移动应用程序中的数据。此应用程序将利用 Vuex 的强大功能和 NativeScript 内置的 应用程序设置 模块。

在深入代码之前,让我们退一步,了解我们提出的每个模块在使用 NativeScript 构建移动应用程序时能为我们提供什么。

根据 Vue.js 网站,Vuex 可以描述为以下内容

Vuex 是一个状态管理模式 + 库,适用于 Vue.js 应用程序。它充当应用程序中所有组件的集中存储库,并通过规则确保状态只能以可预测的方式进行变异。

在 NativeScript 应用程序中存储数据有许多不同的方法。在本例中,我们将使用 应用程序设置 模块提供的键值存储,该模块在 Android 上使用 SharePreferences,在 iOS 上使用 NSUserDefaults。在未来的教程中,我们将探讨如何使用 SQLite 或类似方法。

本教程的灵感来自我阅读的一篇名为 Vue: 使用 localStorage 与 Vuex Store 的 Web 教程。

创建支持 Vuex 的 NativeScript 与 Vue.js 项目

要使本教程成功,你需要在你的计算机上安装和配置 NativeScript,以及 Vue CLI,如 NativeScript 文档 中所述。创建项目的命令如下

vue init nativescript-vue/vue-cli-template vuex-project
cd vuex-project
npm install
npm run watch:ios

上述命令将创建一个名为 vuex-project 的项目,并包含必要的依赖项。在创建项目时,确保在提示时启用 Vuex,因为这将使我们的生活更轻松。在配置过程中的所有其他提示中,默认值就足够了。

定义 Vuex 状态逻辑

现在我们已经创建了一个 NativeScript 与 Vue.js 项目并准备就绪,我们可以专注于开发用于管理应用程序状态的 Vuex 逻辑。在我看来,创建新项目时使用的生成器有点古怪。出于这个原因,我们将略微违背模板,以努力匹配我们在 Web 上看到的 Vue.js 情况。

在项目的 src/store/index.js 文件中,包含以下 JavaScript 代码

import Vue from 'nativescript-vue';
import Vuex from 'vuex';
import * as ApplicationSettings from "application-settings";

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        firstname: "",
        lastname: ""
    },
    mutations: {
        load(state) {
            if(ApplicationSettings.getString("store")) {
                this.replaceState(
                    Object.assign(state, JSON.parse(ApplicationSettings.getString("store")))
                );
            }
        },
        save(state, data) {
            state.firstname = data.firstname;
            state.lastname = data.lastname;
        }
    }
});

Vue.prototype.$store = store;

module.exports = store;

在我们讨论上述代码的含义之前,先提一下我做了哪些更改。我没有在 src/store/index.js 文件中引用模块,而是直接在该文件中包含了模块的内容。

那么上述代码中发生了什么?

首先,我们定义了可以在我们的存储中管理的数据。在本例中,我们将管理姓和名信息,这是一个相当简单的示例。默认情况下,数据将为空。

我们定义了两个可用于改变应用程序状态的变异。

load(state) {
    if(ApplicationSettings.getString("store")) {
        this.replaceState(
            Object.assign(state, JSON.parse(ApplicationSettings.getString("store")))
        );
    }
},

load 变异将首先检查我们称为 store 键中是否有任何先前保存的内容。为了使我们的数据更灵活,我们不想限制自己只使用 state 变量中存在的内容。相反,如果之前保存了数据,我们将用存储中存在的内容和状态中存在的内容的合并副本替换当前状态。replaceState 函数是 Vuex API 的一部分。

save(state, data) {
    state.firstname = data.firstname;
    state.lastname = data.lastname;
}

save 变异将获取提交到该变异的数据并将其保存在我们的状态中。你会注意到,我们实际上并没有在 Vuex 控制器中将任何数据保存到存储中,但我们可以这样做。相反,实际的保存将在我们的组件中的订阅中进行。

在 NativeScript 中构建具有数据需求的 Vue.js 组件

我们想看到 Vuex 的神奇效果,我们也想要真正持久化数据,而不仅仅是在应用程序打开并使用时管理数据。出于这个原因,我们需要处理我们的组件。

当你创建项目时,你可能会有一个 src/components/Counter.vue 文件。你可以重命名它、保留它或创建一个新文件。这是一个示例,因此我们的命名约定并不重要,但我们不会计算任何内容。

打开组件并包含以下代码

<template></template>

<script>
    import * as ApplicationSettings from "application-settings";
    export default {
        data() {
            return {
                input: {
                    firstname: "",
                    lastname: ""
                }
            }
        },
        mounted() {
            this.$store.subscribe((mutations, state) => {
                ApplicationSettings.setString("store", JSON.stringify(state));
                this.input.firstname = state.firstname;
                this.input.lastname = state.lastname;
            });
        },
        methods: {
            save() {
                this.$store.commit("save", this.input);
            },
            load() {
                this.$store.commit("load");
            },
            clear() {
                this.input.firstname = "";
                this.input.lastname = "";
            }
        }
    };
</script>

你可以看到,我暂时删除了 <template> 内容,因为我们想关注 <script> 内容。简而言之,此组件将包含一个表单和三个按钮。我们可以保存表单的内容、加载表单的内容或清除表单的内容。该表单将允许输入姓名和姓氏。

首先,我们要在 data 方法中初始化我们的变量。接下来,当应用程序挂载时,我们要订阅我们的 Vuex 存储。这是实际保存发生的地方。只要我们的存储发生变化,此订阅就会触发,然后持久化我们的状态并设置表单内容。请记住,这不是保存数据的唯一策略。

methods: {
    save() {
        this.$store.commit("save", this.input);
    },
    load() {
        this.$store.commit("load");
    },
    clear() {
        this.input.firstname = "";
        this.input.lastname = "";
    }
}

save 方法将调用我们在 Vuex 文件中找到的 save 变异。我们将表单输入传递给此变异。load 方法将调用我们在 Vuex 文件中找到的 load 变异。最后,clear 方法将只清除我们的表单的 UI,而不是保存的数据。

现在让我们看看之前删除的 <template>

<template>
    <Page class="page">
        <ActionBar class="action-bar" title="Person"></ActionBar>
        <StackLayout class="form">
            <StackLayout class="input-field">
                <Label text="First Name" class="label font-weight-bold m-b-5" />
                <TextField class="input" v-model="input.firstname" />
                <StackLayout class="hr-light"></StackLayout>
            </StackLayout>
            <StackLayout class="input-field">
                <Label text="Last Name" class="label font-weight-bold m-b-5" />
                <TextField class="input" v-model="input.lastname" />
                <StackLayout class="hr-light"></StackLayout>
            </StackLayout>
            <GridLayout rows="auto, auto" columns="*, *">
                <Button text="Save" @tap="save" class="btn btn-primary" row="0" col="0" />
                <Button text="Load" @tap="load" class="btn btn-primary" row="0" col="1"  />
                <Button text="Clear" @tap="clear" class="btn btn-primary" row="1" col="0" colSpan="2"  />
            </GridLayout>
        </StackLayout>
    </Page>
</template>

<template> 中,我们有两个表单字段,它们使用 NativeScript 核心主题进行样式设置。它们使用 v-model 属性绑定到我们在 <script> 块中定义的数据。我们按钮上的每个 @tap 事件都将调用一个相应的函数。

如果你之前更改了文件名或创建了一个新文件,不要忘记更新项目的 src/main.js 文件。

结论

你刚刚看到了如何在使用 NativeScript 和 Vue.js 创建的 Android 和 iOS 应用程序中使用 Vuex 和一种持久化本地存储形式。正如我之前提到的,在 NativeScript 中持久化数据的方法有很多,但共同点是,在管理方面,你很可能会使用 Vuex。

要查看另一个 Vuex 示例,我有一个名为 使用 Axios 与 Vuex 的 Vue.js 应用程序 的 Web 示例,可以轻松地移植到 NativeScript。