学员管理系统- 项目跟进day03

1 实时获取城市天气情况

拉取网页链接获取城市实时天气情况:

import jsonp from "jsonp"
export function reqWeather(city){
    const url =`https://www.yiketianqi.com/free/day?appid=88628299&appsecret=8vMuhyrH&unescape=1&city=${city}`
    return new Promise((resolve,reject)=>{
        jsonp(url,{
            param:"callback"
        },(error,response)=>{
            if(!error && response.cityid){
                const {tem_day,tem_night,wea,wea_img} = response
                resolve({tem_day,tem_night,wea,wea_img})
            }else{
                console.log("获取天气信息失败");
            }
        })
    })
}

jsonp的作用是用于跨域请求,解决浏览器同源策略的限制。在上面的代码中,通过导入jsonp库,可以在前端代码中发送跨域请求并获取数据。具体的使用方式是通过传递一个URL和一些可选的选项给jsonp函数来发送请求。在这个例子中,请求的URL是指定的城市的天气信息API地址。通过json函数的回调函数,可以在请求成功后执行相应的操作,比如获取返回的天气信息并解析处理。如此一来,前端代码就能够在异步请求中通过从其他域名获取数据

2 在主页Header部分展示天气情况

在AppHeader的index.vue中进行设置

引入jsonp.js:

import { reqWeather } from "@/api/jsonp";

 将在jsonp中获取到的属性值通过data()的return返回出去(输出):

  data() {
    return {
      user: memoryUtils.user,
      currentTime: formateTime(Date.now()),
      tem_day: "",
      tem_night: "",
      wea: "",
      wea_img: "",
    };
  },

在methods中设置获取天气情况的方法“

 // 获取天气情况
    getWeather() {
      reqWeather("哈尔滨").then((response) => {
        const { tem_day, tem_night, wea, wea_img } = response;
        const weaImgs = {
          xue: "el-icon-light-rain",
          lei: "el-icon-lightning",
          shachen: "el-icon-sunrise",
          wu: "el-icon-cloudy-and-sunny",
          bingbao: "el-icon-light-rain",
          yun: "el-icon-cloudy",
          yu: "el-icon-heavy-rain",
          yin: "el-icon-partly-cloudy",
          qing: "el-icon-sunny",
        };
        this.tem_day = tem_day
        this.tem_night = tem_night
        this.wea = wea
        this.wea_img = weaImgs[wea_img]
      });
    },

注意:要先将要获取的属性( tem_day, tem_night, wea, wea_img)从response中解构出来才能使用

在这里,this指向的是定义getWeather方法的当前对象或组件实例。具体来说,this是指向包含getWeather方法的组件实例,通常是一个Vue组件或类组件的实例。通过使用this.tem_daythis.tem_nightthis.weathis.wea_img,我们可以在getWeather方法中将获取的天气信息赋值给组件的相应实例属性,以便在组件中其他地方使用这些属性。请注意,this的值在不同的上下文环境中可能会有所不同,所以需要根据具体情况来确定this的指向。

3 退出登录

// 修改密码与退出登录
    handleCommand(command) {
      switch (command) {
        case "a":
          // 修改密码
          break;
        case "b":
          // 退出登录
          memoryUtils.user = {}
          storageUtils.removeUser()
          this.$router.replace("/login")
          break;
        default:
          break;
      }
    },

在这段代码中,判断case是"a"还是"b"是通过handleCommand方法的参数command进行判断的。

      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item command="a">修改密码</el-dropdown-item>
        <el-dropdown-item command="b">退出登录</el-dropdown-item>
      </el-dropdown-menu>

command是传递给handleCommand方法的值,在这里是通过点击el-dropdown-item元素触发的。当点击了带有command="a"el-dropdown-item元素时,command的值为"a",进入了case "a"的分支,执行了相应的逻辑,即修改密码。当点击了带有command="b"el-dropdown-item元素时,command的值为"b",进入了case "b"的分支,执行了相应的逻辑,即退出登录,并执行了相关的操作。所以,在这里鼠标点击了哪一个 el-dropdown-item元素就会相应地进入到对应的case分支中执行相应的逻辑。command是一种特殊属性,用于标识el-dropdown-item元素的命令值,在点击时传递给handleCommand方法进行判断和处理。

删除用户信息:

          memoryUtils.user = {}

          storageUtils.removeUser()

重定向跳转:

          this.$router.replace("/login") 

 4 整合所有菜单分类项到一个js文件中命名为:menuConfig.js

 5 在AppNavbar中引入菜单js组件

删除template写法,使用render()的写法的原因可能是出于以下考虑:

  1. 更灵活:使用render()函数可以更灵活地控制组件的渲染逻辑和结构。render()函数可以通过编写 JavaScript 代码来生成组件的 DOM 结构,可以进行条件渲染、循环渲染等复杂的逻辑操作。

  2. 更高的性能:使用render()函数编写组件可以提升性能。由于在编译阶段会将render()函数编译为可执行的 JavaScript 代码,而使用模板语法的方式需要首先将模板编译为一个render()函数,再执行该函数来实现渲染,这会导致额外的性能损耗。

  3. 统一的语法:使用render()函数编写组件可以使代码风格更统一。在 Vue.js 中,render()函数和模板语法(template)都是用于定义组件的方式,但在一些情况下,使用render()函数可以更方便地进行一些高级操作,使代码风格更一致。

尽管在大多数情况下,使用模板语法(template)是更简洁、更易读的方式来定义组件,但当需要更高级的灵活性和性能优化时,使用render()函数是一个很好的选择。

这属于JSX写法。JSX是一种JavaScript的扩展语法,它允许我们在JavaScript代码中直接编写类似于HTML的结构,用来描述用户界面的组件结构。在给定的代码中,我们可以看到在render()函数中,使用了类似HTML标签的语法来描述了组件的结构,并使用了动态的数据(通过this.menuNodes)来渲染相应的内容。这和JSX的写法非常类似,因此可以认为这是JSX写法。

值得注意的是,JSX并不直接与Vue.js绑定,它通常与React一起使用。在这个例子中,可能是使用了Vue.js支持JSX的插件(如vue-jsx)来实现的。这样可以让开发者使用更具表达力、灵活性的JSX语法来编写Vue组件。

(1)引入菜单组件:
import menuList from "@/config/menuConfig.js";
(2)data()中设置所有菜单项显示,默认先定义空字符串
  data() {
    return {
      menuNodes: "", //所有菜单项
    };
  },
(3)在methods写方法来遍历菜单组件内容
  methods: {
    getMenuNodes(menuList) {
      // map根据当前数组生成一个新数组
      return menuList.map((item) => {
        // 先处理一级菜单
        if (!item.children) {
          return (
            <el-menu-item index={item.index}>
              <i class={item.icon}></i>
              <span slot="title">{item.title}</span>
            </el-menu-item>
          );
        } else {
          // 带有二级菜单的
          return (
            <el-submenu index={item.index}>
                <template slot="title">
                    <i class={item.icon}></i>
                    <span>{item.title}</span>
                </template>
                {/* 遍历子菜单 */}
                {this.getMenuNodes(item.children)}
            </el-submenu>
          );
        }
      });
    },
  },

带有二级菜单的一级菜单是在return语句中的else块中处理的。当itemchildren属性时,表示它是一个拥有子菜单的一级菜单。在这种情况下,会使用<el-submenu>元素来渲染一个含有子菜单的菜单项。具体的处理过程如下:

  1. 设置<el-submenu>元素的index属性为item.index,用于标识该菜单项。
  2. 使用<template slot="title">定义一个模板,该模板将作为菜单项的标题渲染。
  3. 在模板中,使用<i>元素显示菜单项的图标,通过item.icon属性获取图标的样式类。
  4. 使用<span>元素显示菜单项的标题文本,通过item.title属性获取标题文本内容。
  5. <el-submenu>元素的内部,调用this.getMenuNodes(item.children)递归生成该一级菜单的子菜单的内容递归的过程会再次调用getMenuNodes()方法来处理每个子菜单项
    因此,带有二级菜单的一级菜单会以<el-submenu>元素的形式进行渲染和处理。如果item没有children属性,即该菜单项没有子菜单,那么会使用<el-menu-item>元素来渲染该一级菜单的菜单项。
(4)在mounted()中调用该方法挂载
  mounted() {
    this.menuNodes = this.getMenuNodes(menuList);
    console.log("this.menuNodes", this.menuNodes);
  },

把获取到的所有列表内容输入给定义的实例空字符串menuNodes

(5)书写render()==>意味着使用jsx可以在js中书写html语法==>将获取内容显示出来
 render() {
    return (
      <div class="navbar">
        <el-menu
          default-active="2"
          class="el-menu-vertical-demo"
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#ffd04b"
          default-openeds={["/students"]}
          default-active={this.$route.path}
          router={true}
        >
        {this.menuNodes}
        </el-menu>
      </div>
    );
  },
  • default-active="2":将default-active属性设置为2,表示默认选中菜单的索引为2
  • class="el-menu-vertical-demo":添加了class属性为el-menu-vertical-demo,用于样式定义。
  • background-color="#545c64":设置背景颜色为#545c64
  • text-color="#fff":设置文本颜色为#fff
  • active-text-color="#ffd04b":设置选中文本的颜色为#ffd04b
  • default-openeds={["/students"]}设置默认展开的菜单项,这里是/students。拥有子菜单的一级菜单被展开
  • default-active={this.$route.path}:将默认选中的菜单项设为当前页面的路由路径所对应的菜单项。
  • router={true}激活路由模式,表示菜单项可以作为路由链接
  • <el-menu>的内部,使用了插槽{this.menuNodes},表示将通过this.menuNodes渲染菜单项的内容放置于该插槽内this.menuNodes是一个值在Vue组件中动态生成的菜单项。

    综上所述,这段代码渲染了一个具有特定样式和行为的菜单组件,并动态生成菜单项内容。具体渲染的菜单项内容由this.menuNodes决定。

  • 注:

  • this.$route是Vue.js中提供的一个路由对象,用于获取当前页面的路由信息。它提供了访问当前URL路径、查询参数、路由参数等等信息的方法,并且支持对路由的动修改和监听。使用this.$route可以实现很多与路由相关的功能,如动态展示不同的页面、路由导航、路由跳转等等。
    在Vue组件中,可以通过访问this.$route属性来获取当前页面的路由信息。在代码中,可以根据当前路由信息来动态地实现菜单选中、路由导航和其他与路由相关的操作。一般在Vue组件、路由导航守卫等地方会使用this.$route
    this.$route可以获取以下信息:

  • $route.path:当前页面的路径。
  • $route.params:当前路由的参数,如/user/:id中的:id参数。
  • $route.query:当前URL查询参数,如/user?id=123中的id参数。
  • $route.fullPath:当前页面的完整URL路径,包含所有参数和哈希值。
  • $route.name:当前路由的名称,可以用来进行命名路由的跳转等操作。
    总之,this.$route可以获取当前页路由信息中的各种属性,用实现不同的路由相关的功能。

6 设置路由跳转(不同菜单项对应不同的main界面)

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from "@/views/login"
import Layout from "@/components/Layout"
import Home from "@/views/home/Home.vue"
import User from "@/views/user/User.vue"
import Role from "@/views/role/Role.vue"
import School from "@/views/students/School.vue"
import Major from "@/views/students/Major.vue"
import Class from "@/views/students/Class.vue"
import Student from "@/views/students/Student.vue"

Vue.use(VueRouter)

const routes = [
  {
    path:"/login",
    name:'login',
    component:Login
  },
  {
    path:'/',
    name:'layout',
    component:Layout,
    redirect:'/home',
    children:[
      {
        path:"/home",
        name:'home',
        component:Home,
        meta:{title:'首页'}
      },
      {
        path:"/user",
        name:'user',
        component:User,
        meta:{title:'用户管理'}
      },
      {
        path:"/role",
        name:'role',
        component:Role,
        meta:{title:'角色管理'}
      },
      {
        path:"/school",
        name:'school',
        component:School,
        meta:{title:'学校管理'}
      },
      {
        path:"/majors",
        name:'major',
        component:Major,
        meta:{title:'专业管理'}
      },
      {
        path:"/class",
        name:'class',
        component:Class,
        meta:{title:'班级管理'}
      },
      {
        path:"/student",
        name:'student',
        component:Student,
        meta:{title:'学生管理'}
      },
    ]
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

main中顶部有link.js链接界面提示

<template>

    <el-breadcrumb >
      <el-breadcrumb-item class="line">{{$route.meta.title}}</el-breadcrumb-item>
    </el-breadcrumb>

</template>

<style scoped>
    .el-breadcrumb{
        height: 10px;
        padding: 20px;
        border-radius: 4px;
        /* 投影 */
        box-shadow: 0 2px 12px 0 rgba(0, 0,0, 0.1);
    }
    .line{
        border-left: 3px solid #31c17b;
        padding-left: 10px;
    }
</style>

(1)在Appmain中的Index.js引入这个js

import AppLink from "./Link.vue"

(2)注册

 components: {
    AppLink
 },

(3)设置路由自定义子组件出口

<app-link v-show="$route.path !== '/home'"></app-link>

(4)路由组件的出口,也就是router的核心的中心路由(有很多组件的集合引入)

    <div class="main">
        <app-link v-show="$route.path !== '/home'"></app-link>
        <router-view></router-view>
    </div>

7 针对不用用户成员进行不同管理

<后端部分>

(1)在后端定义角色管理规则并导出
const mongoose = require('mongoose')

const roleSchema = new mongoose.Schema({
    name:{type:String,required:true},
    auth_name:String,
    auth_time:Number,
    create_time:{type:Number,default:Date.now},
    menus:Array
})

const RoleModel = mongoose.model('roles',roleSchema)

module.exports = RoleModel
(2)在后端路由中导出该规则(并写get请求进行postman后端测试)

(i)引入:

const RoleModel = require("../models/RoleModel")

(ii)get请求获取角色列表

    // 获取角色列表
    router.get("/manage/role/list",(req,res)=>{
        RoleModel.find().then(roles=>{
            res.send({status:0,data:roles})
        }).catch(error=>{
            console.log("获取角色列表异常",error);
            res.send({status:1,msg:'获取角色列表异常,请重试'})
        })
    })

<前端部分>

(1) 在前端的src的api的role.js进行后端接收并定义getRoleList()方法返回ajax的get请求

  

 引入request.js为发送ajax请求的规则

import request from "@/utils/request"

export default{
    getRoleList(){
        return request({
            url:'/manage/role/list',
            method:'get'
        })
    }
}

(2)引入该role.js

import roleApi from "@/api/role";

(3)定义获取角色列表的方法

//  获取角色列表
    fetchRoleList() {
      roleApi.getRoleList().then((response) => {
        const resp = response.data;
        console.log("resp", resp);
        if (resp.status == 0) {
          this.roleList = resp.data;
        }
      });
    },

(4)在mounted()中调用该方法

  mounted() {
    this.fetchRoleList();
  },

附:添加角色部分并不完整,将会在day04中补充

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值