第三节:整体架构剖析、登录业务编写

一. 整体架构剖析

1. 目标

 该项目架构的搭建,侧重组件的抽取、封装、调用各个组件的相互通信侧重于一些核心方案的实现侧重于vue3+ts+elementPlus+vuex的使用

 忽略项目的UI、忽略一些基本的验证逻辑、忽略一些无关紧要的位置。

2. 核心组件封装

(1). breadcrumb:面包屑组件  →  nav-header:主页顶部栏目组件

(2). nav-menu:左侧菜单组件

(3). ypf-form:表单组件 → page-search:搜索框组件 → user.vue:用户管理页面

(4). ypf-form: 表单组件 → page-modal:弹框组件 → user.vue:用户管理页面

(5). ypf-table: 表格组件 → page-content:内容区域组件 → user.vue:用户管理页面

解析:

 →的指向,代表左边的组件 被 右边组件 调用,最终在user.vue页面,只需要引入page-search、page-content、page-modal 三大组件,传入各个组件的相关配置,这三个组件之间可以实现互相调用,即可完成常规用户管理业务。

 

3. 数据调用流程

(1). 定义HYRequest类,封装axios实例

(2). new一个HYRequest实例,hyRequest

(3). 在Service文件夹下使用hyRequest调用,封装各个请求的方法(仅仅传入 url 和 参数,不处理结果)

(4). 在Vuex中的state里声明存储各类数据

(5). 在Vuex中的mutation里声明方法,用来给state里的属性赋值

(6). 在Vuex中的action里 调用Service里封装的方法,拿到返回值结果,然后调用mutition里方法,给state里的属性赋值

(7). 在各个具体的页面里(user.vue, role.vue),可以dispatch调用action里的方法,然后,同时也可以直接 store.state.xxx 拿 state 里的数据进行使用

 

4.核心方案 

(1). 动态路由权限配置

   详见:xxxxx

(2). 按钮权限 

   详见:xxxx

(3). 刷新页面仍然记住当前页面

  详见:xxxx

 

二. 登录业务剖析

1. 业务流程

 流程1:

  前端校验form表单中的值,校验通过 → dispatch调用vuex中的方法 → 调用Service封装登录方法 → 返回token存入缓存;同时Commit调用mutations中的方法→将token存入vuex中state属性中

 流程2:

  为了防止vuex中的数据刷新后丢失,这里封装1个方法,然后在main.ts中调用;这里的套路就是vuex中的数据第一次获取的时候也存入缓存一份,然后刷新页面的时候,从缓存中获取,然后给vuex中的数据赋值。【重点!!!vuex中的数据是在内存中,只要页面刷新了,vuex中的数据就消失了】

loadLocalLogin({ commit }) {
    const token = cacheUtils.getCache('token');
    if (token) {
    commit('changeToken', token);
    }
},

2. 组件关系和用法

(1). 组件关系 

  login-panel父组件中 调用 : login-account(帐户密码登录组件) 和 login-phone(手机号验证码登录组件)

(2). tab组件用法

  核心是给el-tabs通过v-model绑定一个值,这个值则需要和子tab-panel中的name属性相关联,等于那个name属性,则哪个被选中。

(3). form表单用法

    <div>
        <el-form label-width="80px" :model="myLoginInfo" :rules="myRules" ref="formRef">
            <el-form-item label="账号" prop="userAccount">
                <el-input v-model="myLoginInfo.userAccount" @keyup.enter="checkLogin"></el-input>
            </el-form-item>
            <el-form-item label="密码" prop="userPwd">
                <el-input v-model="myLoginInfo.userPwd" @keyup.enter="checkLogin"></el-input>
            </el-form-item>
        </el-form>
    </div>

A. 绑定表单数据对象

 ef-form通过model属性绑定一个对象myLoginInfo,然后子元素input通过v-model绑定  myLoginInfo.xxx 属性。

    setup(props) {
            // 表单信息
            const myLoginInfo = reactive({
                userAccount: '',
                userPwd: '',
            });
            // form表单对象
            const formRef = ref<InstanceType<typeof ElForm>>();return {
                myLoginInfo,
                formRef,
            };
        },

B. 校验规则绑定

 el-formrules属性绑定校验规则对象,然后每个el-form-item通过prop定义一个名称,注意prop定义的这个名称要和rules定义的属性名相关联,从而实现规则的校验(通常为了方便,就把prop里的名称和model里绑定的对象名称设置成相同即可了)

// 编写好规则,名称必须和form表单中prop属性定义的名称相同
export const myRules = {
    userAccount: [
        {
            required: true,
            message: '用户名是必传内容~',
            trigger: 'blur',
        },
        {
            pattern: /^[a-z0-9]{5,10}$/,
            message: '用户名必须是5~10个字母或者数字~',
            trigger: 'blur',
        },
    ],
    userPwd: [
        {
            required: true,
            message: '密码是必传内容~',
            trigger: 'blur',
        },
        {
            pattern: /^[a-z0-9]{3,}$/,
            message: '用户名必须是3位以上的字母或者数字~',
            trigger: 'blur',
        },
    ],
};
View Code

C. 规则校验

 首先要给el-form表单通过 ref 属性绑定一个对象 formRef ,代码详见上面,然后通过这个对象调用validate方法进行校验,true表示校验通过。

    formRef.value?.validate((valid) => {
        if (valid) {
                       
        }
     });

D. input回车触发

 使用 @keyup.enter 触发即可

    <el-input v-model="myLoginInfo.userAccount" @keyup.enter="checkLogin"></el-input>

(4). 父组件调用子组件中返回

  在父组件中,首先通过ref属性给子组件绑定一个ref对象,然后通过这个对象 obj.value.xxx,来调用子组件的方法。

<template>
    <div class="login-panel">
        <el-tabs type="border-card" v-model="currentTabName" stretch>
            <el-tab-pane name="account">            
                <login-account ref="accountRef" :isKeepPwd="isKeepPassWord" />
            </el-tab-pane>
            <el-tab-pane name="phone">
                <login-phone ref="phoneRef" />
            </el-tab-pane>
        </el-tabs>
    </div>
</template>

<script lang="ts">
    import { defineComponent, ref, onMounted } from 'vue';
    export default defineComponent({
        setup() {
            // 1.定义属性
            const accountRef = ref<InstanceType<typeof loginAccount>>(); //子组件对象
            const phoneRef = ref<InstanceType<typeof loginPhone>>(); //子组件对象

            // 2.定义方法
            const handleLoginClick = () => {
                console.log(isKeepPassWord.value, currentTabName.value);
                // 调用子组件方法
                if (currentTabName.value === 'account') {
                    accountRef.value?.checkLogin(isKeepPassWord.value);
                } else {
                    phoneRef.value?.checkLogin();
                }
            };
            return {
                accountRef,
                phoneRef,
            };
        },
    });
</script>
View Code

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2021-11-24 13:06  Yaopengfei  阅读(288)  评论(4编辑  收藏  举报