• 前端项目--尚医通学习分享


    这段时间跟着线上课程完成了一个项目:商医通(基于Vue3+TypeScript的医院挂号平台)。具体我就不过多地介绍其具体功能以及详细的实现步骤了,感兴趣的小伙伴直接:传送门 。该文章我就分享一下在该项目中学习到的一些知识点,以及一些前端小伙伴比较常接触到的功能。

    项目介绍

    项目实现效果如下:

    在这里插入图片描述
    在这里插入图片描述

    项目的技术选型如下:

    在这里插入图片描述

    项目总结:

    一、Vue3中的一些基础语法?

    官方文档
    由于该项目是使用Vue3实现的,因此需要具备Vue3的一些基础知识,但是Vue3中的知识点不会介绍太多,主要介绍在这个项目中接触到的比较多的部分知识。

    1.Vue3与Vue2创建实例方法的不同:

    //Vue3中的写法:
    import {createAPP} from 'vue'
    import App from './App.vue'
    createApp(App).mount("#app")
    
    //Vue2中的写法:
    import Vue from 'vue'
    import App from './App.vue'
    new Vue({
        el:"#app",
        render:h=>h(APP)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.Vue3中setup的作用:

    理解:Vue3.0中一个新的配置项,值为一个函数,setup是所有Composition API(组合API)“ 表演的舞台 ”。组件中所用到的:数据、方法等等,均要配置在setup中。

    setup函数的两种返回值:若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)若返回一个渲染函数:则可以自定义渲染内容。(了解)

    注意点:尽量不要与Vue2.x配置混用。Vue2.x配置(data、methos、computed…)中可以访问到setup中的属性、方法。但在setup中不能访问到Vue2.x配置(data、methos、computed…)。如果有重名, setup优先。setup不能是一个async函数,因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)

    3.Vu3中ref函数的作用:

    作用: 定义一个响应式的数据。语法: const xxx = ref(initValue)。创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。JS中操作数据: xxx.value。模板中读取数据: 不需要.value,直接:

    {{xxx}}

    备注:接收的数据可以是:基本类型、也可以是对象类型。基本类型的数据:响应式依然是靠Object.defineProperty()getset完成的。对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数—— reactive函数。

    4.Vue3中的reactive函数:

    作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)

    reactive定义的响应式数据是“深层次的”。内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

    5.reactive与ref的比较:

    从定义数据角度对比:ref用来定义:基本类型数据。reactive用来定义:对象(或数组)类型数据

    备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象

    从原理角度对比:ref通过Object.defineProperty()getset来实现响应式(数据劫持)。reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。

    从使用角度对比:ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。reactive定义的数据:操作数据与读取数据:均不需要.value

    6.setup的两个注意点:

    setup执行的时机,在beforeCreate之前执行一次,this是undefined。

    setup的参数:props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。context:上下文对象。attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs。slots: 收到的插槽内容, 相当于 this.$slots。emit: 分发自定义事件的函数, 相当于 this.$emit

    二、Vite构建工具如何使用?

    1.Vite官网

    2.为什么使用Vite:

    一句话总结:使用vite构建项目,启动的速度要比使用webpack构建更快。

    之前浏览器是不支持ES Modules的,为了在让浏览器能够运行我们写的代码(es6语法、.jsx/.vue文件),我们需要使用打包工具,例如webpack,来实现代码的转换和优化的过程;

    在浏览器支持ES Modules后,import、export、

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    state和getters属性都主要是数据层面的,并没有具体的业务逻辑代码,它们两个就和我们组件代码中的data数据和computed计算属性一样。那么,如果我们有业务代码的话,最好就是写在actions属性里面,该属性就和我们组件代码中的methods相似,用来放置一些处理业务逻辑的方法。actions属性值同样是一个对象,该对象里面也是存储的各种各样的方法,包括同步方法和异步方法。

    六、element-plus组件库该如何使用?

    相应官网:一个 Vue 3 UI 框架 | Element Plus (element-plus.org)

    首先需要先导入其对应的包在main.js中导入如下内容:(Element Plus 组件 默认 使用英语,如果你希望使用中文,可以导入国际化文件。)

    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
    // 国际化文件
    import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
    app.use(ElementPlus,{
        locale: zhCn,
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后只需要搜素你所需要的内容,然后根据文档的提示将其引入到你自己的组件中即可。例如想要实现如下的搜素效果:

    在这里插入图片描述

    首先在官网中搜索search输入框,之后会出现各种各样的输入框,选择具有远程搜索功能的输入框,点击相应的代码查看,将相应的代码如下到自己的组件中,通过查看官方提供的代码以及API功能介绍进行补充以及修改:

     <el-autocomplete
        v-model="state"
        :fetch-suggestions="querySearchAsync"
        placeholder="Please input"
        @select="handleSelect"
      />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    v-model属性为选中项绑定值,fetch-suggestions获取输入建议的方法, 仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它。也就是在这个方法中当输入框输入完数据之后就回调用它,此时就需要在这个方法中获取到输入框中需要的数据,在通过传给回调函数,让其展现在相应的搜索框下方。该方法具有两个参数:(queryString: string, cb: (arg: any) => void),第一个为数据的内容,第二个为回调函数。

    const loadAll = () => {
      return [
        { value: 'vue', link: 'https://github.com/vuejs/vue' },
        { value: 'element', link: 'https://github.com/ElemeFE/element' },
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过官网例子提供的代码我们知道在若需要在搜索框出现,则需要参数名为value,而我们通过发送请求返回来的数据参数名并不是value,因此后续我们还需要对数据进行处理之后才能够给回调函数。 @select="handleSelect"为选择其中的某一项时会触发的事件。

    因此我们结合自己的项目编写的代码如下:

    <template>
        <div class="search">
            <el-autocomplete @select="goDetail" :trigger-on-focus="false" clearable placeholder="请输入医院名称" v-model="hosname"
                :fetch-suggestions="fetchData" />
            <el-button type="primary" size="default" :icon="Search">搜索</el-button>
    
        </div>
    </template>
    
    <script setup lang="ts">
    import { Search } from '@element-plus/icons-vue';
    import { useRouter } from 'vue-router';
    import { ref } from 'vue';
    import { reqHospitalInfo } from '@/api/home';
    import type { HospitalInfo } from '@/api/home/type';
    // 创建路由对象
    let $router = useRouter();
    // 收集搜素的关键字
    let hosname = ref<string>('');
    // 顶部组件的回调
    const fetchData = async (keyword: string, cb: any) => {
        let result: HospitalInfo = await reqHospitalInfo(keyword);
        let showData = result.data.map(item => {
            return {
                value: item.hosname,
                hoscode: item.hoscode
            }
        })
        cb(showData);
    }
    // 点击某一个推荐项
    const goDetail = (item: any) => {
        $router.push({ path: '/hospital/register' ,query:{hoscode:item.hoscode}})
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    因此其他的样式以及布局也可以通过在其中寻找相应的组件来完成,这样可以减少很多的开发时间。

    七、如何对axios进行二次封装来实现向服务器请求数据?

    对原生的axios进行二次封装

    //对于axios函数库进行二次封装?
    //你工作的时候是否axios进行二次封装?二次封装的目的是什么那?
    //目的:1,利用axios请求、响应拦截器功能
    //目的2:请求拦截器,一般可以在请求头中携带公共的参数:token
    //目的3:响应拦截器,可以简化服务器返回的数据,处理http网络错误
    import axios from 'axios';
    //引入用户相关的仓库
    import useUserStore from '@/store/modules/user';
    //@ts-ignore
    import { ElMessage } from 'element-plus';
    //利用axios.create方法创建一个axios实例:可以设置基础路径、超时的时间的设置
    const request = axios.create({
          baseURL: '/api',//请求的基础路径的设置
          timeout: 5000//超时的时间的设置,超出五秒请求就是失败的
    });
    
    //请求拦截器
    request.interceptors.request.use((config) => {
          //获取用户仓库
          let userStore = useUserStore();
          //token:公共参数,如果用户登录了需要携带
          if (userStore.userInfo.token) {
                config.headers.token = userStore.userInfo.token;
          }
          //config:请求拦截器回调注入的对象(配置对象),配置对象的身上最终要的一件事情headers属性
          //可以通过请求头携带公共参数-token
          return config;
    });
    //响应拦截器
    request.interceptors.response.use((response) => {
          //响应拦截器成功的回调,一般会进行简化数据
          return response.data;
    }, (error) => {
          //处理http网络错误
          let status = error.response.status;
          switch (status) {
                case 404:
                      //错误提示信息
                      ElMessage({
                            type: 'error',
                            message: '请求失败路径出现问题'
                      })
                      break;
                case 500 | 501 | 502 | 503 | 504 | 505:
                      ElMessage({
                            type: 'error',
                            message: '服务器挂了'
                      })
                      break;
                case 401:
                      ElMessage({
                            type: 'error',
                            message: '参数有误'
                      })
                      break;
          }
          return Promise.reject(new Error(error.message))
    });
    //务必对外暴露axios
    export default request;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    对请求封装成相应的函数

    import request from "@/utils/request";
    import { get } from "http";
    import type{HospitalResponseData,HospitalLevelAndRegionResponseData,HospitalInfo} from './type'
    
    enum API{
        // 获取已有医院数据接口
        HOSPITAL_URL='/hosp/hospital/',
        // 获取医院等级与地区接口
        HOSPITALLEVELANDREGION_URL='/cmn/dict/findByDictCode/',
        // 根据关键词搜素医院
        HOSPITALINFO_URL='/hosp/hospital/findByHosname/'
    
    }
    export const reqHospital =  (page:number,limit:number,hostype='',districtCode='')=>request.get<any,HospitalResponseData>(API.HOSPITAL_URL+`${page}/${limit}?hostype=${hostype}&districtCode=${districtCode}`)
    export const reqHospitalLevelAndRegion=(dictCode:string)=>request.get<any,HospitalLevelAndRegionResponseData>(API.HOSPITALLEVELANDREGION_URL+dictCode);
    export const reqHospitalInfo=(hosname:string)=>request.get<any,HospitalInfo>(API.HOSPITALINFO_URL+hosname)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在对应的地方进行调用(可以在onMounted函数中编写方法,若需要多次的调用建议先封装成一个函数,在onMounted中进行调用)

    为何使用async以及await与axios进行结合,因为axios异步请求会出现请求的数据来不及渲染到页面的情况,因此使用async以及await来处理异步请求。

    onMounted(() => {
        getLevel();
    
    });
    const getLevel = async () => {
        let result: HospitalLevelAndRegionResponseData = await reqHospitalLevelAndRegion('HosType')
        if (result.code == 200) {
            levelArr.value = result.data;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    好啦!本次文章就分享到这里了,希望对你有一定的帮助!

  • 相关阅读:
    Android 开发想学习Flutter?带你从0基础到“封神”
    股票振幅榜查询易语言代码
    NANK新旗舰首发!南卡Pro4骨传导耳机配置新升级!新的音质天花板
    [nacos]nacos2.x+nginx集群搭建以及过程中遇到的坑
    28.云原生之服务网格ServiceMesh和istio
    PostgreSQL修炼之道笔记之基础篇(九)
    TexGen简单模型对应inp文件简单梳理-2
    分布式下多节点WebSocket消息收发
    打开 Java 新的大门,Solon v2.5.10 发布
    C++复习笔记--C++常用注释规范
  • 原文地址:https://blog.csdn.net/weixin_51735748/article/details/133782163