Vue 3 + Pinia - 基本HTTP认证教程和实例

847 阅读5分钟

使用Vue 3.2.37Pinia 2.0.14构建的教程

其他版本可用。

本教程展示了如何使用Vue 3和Pinia构建一个使用Basic HTTP认证的简单登录应用。

Vue 3 + Pinia应用实例

这个例子的应用相当简约,只包含2个页面来演示Vue 3和Pinia的基本认证。

  • /login - 带有用户名和密码字段的公共登录页面,提交时页面会向API发送一个POST请求,以验证用户的证书。
  • / - 安全主页,显示从安全API端点获取的用户列表,使用认证用户的基本认证凭证,基本认证凭证由Base64编码的 和 ,用一个冒号隔开 。username password :

Pinia状态管理

Pinia是由Vuejs核心团队建立的一个新的状态管理库,它简化了全局状态管理,它是Vuex的继承者,需要的代码比Vuex少很多,是Vue 3的推荐状态管理库。

状态和业务逻辑在Pinia中使用商店来定义,每个商店可以包含状态获取器动作状态定义了商店管理的数据,获取器返回一个从状态和/或其他获取器派生(计算)的值,而行动是用来执行业务逻辑或异步操作的方法,如API调用。它们相当于传统(选项API)Vue组件中的data,computedmethods

你可以定义任意多的Pinia商店,它们可以在整个Vue应用程序中全局访问。关于Pinea的更多信息请看pinia.vuejs.org/core-concep…

Vue组合API

例子中的组件是用Vue 3附带的新的VueComposition API构建的,组件的逻辑位于一个

Hi {{authUser?.firstName}}!

You're logged in with Vue 3 + Pinia & Basic HTTP Authentication!!

Users from secure api end point:

  • {{user.firstName}} {{user.lastName}}

Error loading users: {{users.error}}

Vue 3 LoginView组件

路径。/src/views/LoginView.vue

登录视图包含一个用VeeValidate库构建的表单,其中包含用户名和密码字段,用于登录到Vue 3 + Pinia应用程序。

表单验证规则是由VeeValidate支持的Yup模式验证库定义的,关于Yup的更多信息请看github.com/jquense/yup…

onSubmit() 方法通过调用authStore.login() ,将用户凭证发布到API。认证成功后,用户auth ,通过login() 动作方法存储在Pinia全局状态中,并将用户重定向到主页。

Vue组件模板包含带有输入字段和验证信息的表单。表单和字段是用VeeValidate构建的。

和 ,这些组件根据字段的名称自动钩住验证规则(schema)。

当表单被提交且有效时,表单会调用onSubmit() 方法。验证规则通过validation-schema 道具绑定到表单上,验证错误通过范围内的槽v-slot="{ errors }" ,提供给表单模板。关于用Vue 3和VeeValidate进行表单验证的更多信息,请看Vue 3 + VeeValidate - 表单验证实例(Composition API)

<script setup>
import { Form, Field } from 'vee-validate';
import * as Yup from 'yup';

import { useAuthStore } from '@/stores';

const schema = Yup.object().shape({
    username: Yup.string().required('Username is required'),
    password: Yup.string().required('Password is required')
});

function onSubmit(values, { setErrors }) {
    const authStore = useAuthStore();
    const { username, password } = values;

    return authStore.login(username, password)
        .catch(error => setErrors({ apiError: error }));
}
</script>

<template>
    <div>
        <div class="alert alert-info">
            Username: test<br />
            Password: test
        </div>
        <h2>Login</h2>
        <Form @submit="onSubmit" :validation-schema="schema" v-slot="{ errors, isSubmitting }">
            <div class="form-group">
                <label>Username</label>
                <Field name="username" type="text" class="form-control" :class="{ 'is-invalid': errors.username }" />
                <div class="invalid-feedback">{{errors.username}}</div>
            </div>            
            <div class="form-group">
                <label>Password</label>
                <Field name="password" type="password" class="form-control" :class="{ 'is-invalid': errors.password }" />
                <div class="invalid-feedback">{{errors.password}}</div>
            </div>            
            <div class="form-group">
                <button class="btn btn-primary" :disabled="isSubmitting">
                    <span v-show="isSubmitting" class="spinner-border spinner-border-sm mr-1"></span>
                    Login
                </button>
            </div>
            <div v-if="errors.apiError" class="alert alert-danger mt-3 mb-0">{{errors.apiError}}</div>
        </Form>
    </div>
</template>

Vue 3应用程序组件

App 组件是Vue 3 + Pinia应用实例的根组件,它包含只为认证用户显示的主导航栏,以及一个用于根据当前路线/路径显示每个视图内容的RouterView 组件。

Piniaauth storeuser 状态属性被用来在用户登录/退出应用程序时反应性地显示/隐藏主导航栏。

authStore.logout() 方法被主导航栏中的logout链接调用,以注销用户并重定向到登录页面。

<script setup>
import { RouterLink, RouterView } from 'vue-router';

import { useAuthStore } from '@/stores';

const authStore = useAuthStore();
</script>

<template>
    <div class="app-container bg-light">
        <nav v-show="authStore.user" class="navbar navbar-expand navbar-dark bg-dark">
            <div class="navbar-nav">
                <RouterLink to="/" class="nav-item nav-link">Home</RouterLink>
                <a @click="authStore.logout()" class="nav-item nav-link">Logout</a>
            </div>
        </nav>
        <div class="container pt-4 pb-4">
            <RouterView />
        </div>
    </div>
</template>

<style>
@import '@/assets/base.css';
</style>

Vue 3 Main.js

main.js文件通过在主索引html文件中定义的#app div元素中安装App 组件来引导Vue应用程序。

在启动Vue应用程序之前,它导入并启用假后台api。要禁用假后台,只需删除注释// setup fake backend 下面的2行。

Pinia支持被添加到Vue应用程序中,行数为app.use(createPinia())

Vue路由是通过调用app.use(router) 来配置的,路由是在router.js中定义的。

import { createApp } from 'vue';
import { createPinia } from 'pinia';

import App from './App.vue';
import { router } from './helpers';

// setup fake backend
import { fakeBackend } from './helpers';
fakeBackend();

const app = createApp(App);

app.use(createPinia());
app.use(router);

app.mount('#app');

dotenv

dotenv文件包含了Vue应用实例中使用的环境变量,API URL被用于auth storeusers store中,以向API发送HTTP请求。

在dotenv文件中设置的以VITE_ 为前缀的环境变量,在Vue应用程序中可以通过import.meta.env. (例如:import.meta.env.VITE_API_URL )访问。关于在用Vite构建的Vue应用程序中使用环境变量的更多信息,请参见vitejs.dev/guide/env-a…

VITE_API_URL=http://localhost:4000

主索引Html文件

主index.html文件是由浏览器加载的初始页面,它启动了一切。Vite开发服务器通过命令npm run dev ,在开发模式下运行该应用程序。

Vite没有像传统的前端构建工具那样捆绑javascript模块,而是利用了现代浏览器的原生ES模块支持,并增加了热模块替换等额外功能来支持开发。关于Vite开发服务器功能的更多信息,见vitejs.dev/guide/featu…

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

<head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue 3 + Pinia - Basic HTTP Authentication Example</title>

    <!-- bootstrap css -->
    <link href="//netdna.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
</head>

<body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
</body>

</html>

Package.json

package.json文件包含项目配置信息,包括运行npm install 时安装的软件包依赖项,以及运行npm run devnpm run build 时执行的脚本等。完整的文档可在docs.npmjs.com/files/packa…

{
    "name": "vue-3-pinia-basic-authentication-example",
    "version": "0.0.0",
    "scripts": {
        "dev": "vite",
        "build": "vite build",
        "preview": "vite preview --port 5050",
        "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
    },
    "dependencies": {
        "pinia": "^2.0.13",
        "vee-validate": "^4.5.11",
        "vue": "^3.2.37",
        "vue-router": "^4.0.16",
        "yup": "^0.32.11"
    },
    "devDependencies": {
        "@vitejs/plugin-vue": "^2.3.3",
        "eslint": "^8.18.0",
        "eslint-plugin-vue": "^8.2.0",
        "vite": "^2.9.13"
    }
}

Vite.js配置

Vite的配置,Vue项目使用create-vue命令创建的官方前端构建工具和开发服务器。 npm init [[email protected]](https://jasonwatmore.com/cdn-cgi/l/email-protection).

插件@vitejs/plugin-vue 提供对Vue 3单文件组件(SFC)的支持。

别名'@' 使导入语句以at符号为前缀 (@) 相对于项目的/src 文件夹。

关于Vite配置选项的更多信息,见vitejs.dev/config/。

import { fileURLToPath, URL } from 'url';

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [vue()],
    resolve: {
        alias: {
            '@': fileURLToPath(new URL('./src', import.meta.url))
        }
    }
});