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_day
、this.tem_night
、this.wea
和this.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()
的写法的原因可能是出于以下考虑:
-
更灵活:使用
render()
函数可以更灵活地控制组件的渲染逻辑和结构。render()
函数可以通过编写 JavaScript 代码来生成组件的 DOM 结构,可以进行条件渲染、循环渲染等复杂的逻辑操作。 -
更高的性能:使用
render()
函数编写组件可以提升性能。由于在编译阶段会将render()
函数编译为可执行的 JavaScript 代码,而使用模板语法的方式需要首先将模板编译为一个render()
函数,再执行该函数来实现渲染,这会导致额外的性能损耗。 -
统一的语法:使用
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
块中处理的。当item
有children
属性时,表示它是一个拥有子菜单的一级菜单。在这种情况下,会使用<el-submenu>
元素来渲染一个含有子菜单的菜单项。具体的处理过程如下:
- 设置
<el-submenu>
元素的index
属性为item.index
,用于标识该菜单项。 - 使用
<template slot="title">
定义一个模板,该模板将作为菜单项的标题渲染。 - 在模板中,使用
<i>
元素显示菜单项的图标,通过item.icon
属性获取图标的样式类。 - 使用
<span>
元素显示菜单项的标题文本,通过item.title
属性获取标题文本内容。 - 在
<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中补充