vue实现动态路由菜单!!!
目录
总结
递归处理后端响应的菜单树,后依次通过addRoute方法往静态父路由,添加动态子路由,添加完使用el-menu渲染并添加router属性实现路由菜单模式
addRoute:https://router.vuejs.org/zh/api/interfaces/Router.html#Methods-addRoute
后端数据库树菜单:
一、步骤
1.编写静态路由
- 创建router.js文件默认导出静态路由,后在main.js加载注册
编写router.js
//静态路由配置文件
// eslint-disable-next-line no-unused-vars
import Router from "vue-router"
// eslint-disable-next-line no-unused-vars
import Vue from "vue"
//在Vue中加载路由模块
Vue.use(Router)
//写路由表
// eslint-disable-next-line no-unused-vars
// const Foo = { template: '<div>foo</div>' }
const routes = [
// 进入vue项目默认进入登录页面
{
path: "/",
redirect: "/Login"
},
{
path: "/Login",
component: () => import("../view/Login"),
meta: {
skipAuthCheck: true // 添加一个标记,表示不需要进行身份验证检查
}
},
{
path: "/index",
name: 'index',
component: () => import("../components/index"),
children: [
// 默认显示hello页面
{
path: "/",
redirect: "/hello"
},
{
path: "/hello",
meta: { requiresAuth: true },
component: () => import("../components/hello"),
},
],
},
]
export default new Router({
routes
});
// 防止连续点击多次路由报错
let routerPush = Router.prototype.push;
let routerReplace = Router.prototype.replace;
// push
Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(err => err)
}
// replace
Router.prototype.replace = function push(location) {
return routerReplace.call(this, location).catch(err => err)
}
main.js注册
import Vue from 'vue'
import App from './App.vue'
//引入一个router模块
import router from "@/router/router"
import routers from "@/router/permissions"
import element from 'element-ui';
import axiosInstance from '@/request/request'
import { createPinia } from 'pinia';
import 'element-ui/lib/theme-chalk/index.css';
// 在生产环境中禁用警告信息和启用构建优化
Vue.config.productionTip = false
// 将 Axios 实例添加到 Vue 原型中,以便在组件中使用
// Vue.prototype.axios axios便在组件中使用如:this.$axios
Vue.prototype.axios = axiosInstance
const pinia = createPinia();
Vue.use(pinia)
Vue.use(element)
new Vue({
router,
routers,
render: h => h(App),
}).$mount('#app')
2.编写permisstions.js权限文件
- 结合axios封装API于permisstions中配置的全局前置守卫中获取菜单树存入sessionStorage缓存
编写permisstions.js
// 导入默认导出的路由对象用于跳转路由
// import router from '@/router/router';
//导入路由表
import routers from "@/router/router"
//路由配置文件
import { tokenStore } from "@/store/store"
// 全局前置守卫
// to当前即将要进入的路由对象
routers.beforeEach((to, from, next) => {
//如果当前的访问的请求是Login放行
if (to.path === '/Login') {
next();
}
else {
//其余访问请求判断用户是否登录
if (!isLoggedIn()) {
console.log("抱歉你未登录");
next('/Login'); // 如果用户未登录,则重定向到登录页面
} else {
// console.log(to);
next();
}
}
})
//登录验证函数
function isLoggedIn() {
console.log("进入路由守卫");
// 在这里实现检查用户是否已登录的逻辑,例如检查是否有有效的令牌或会话
// 如果已登录,返回true,否则返回false
const jwtToken = sessionStorage.getItem('jwtToken'); // 从本地缓存中获取会话信息
// console.log(jwtToken);
let userId = sessionStorage.getItem('user_name_id');
//userId存在获取动态路由信息
if (userId && jwtToken) {
// if (tokenStore().flag) {
tokenStore().getRouters(userId).then(
(res) => {
if (res.status == 201) {
// console.log(res.data);
//动态路由源信息
let r = res.data;
// 过滤动态路由菜单
let menu = fnAddDynamicMenuRoutes(r)
console.log(menu);
menu.forEach(element => {
element.children.forEach(s => {
// console.log(s);
//index为父路由的name属性值 s是需添加的路由
routers.addRoute('index', s);
})
});
// console.log(routers);
// 动态路由得到后修改标记为false表示已执行过无需在执行
tokenStore().flag = false;
// 保存路由到会话
sessionStorage.setItem('menu', JSON.stringify(menu));
}
if (res.status == 501) {
//未获取到动态路由重新登录
routers.push("/Login");
}
}
)
// }
}
return jwtToken && routers; // 如果登录令牌存在,则用户已登录
}
// 用于处理动态菜单数据,将其转为 route 形式
function fnAddDynamicMenuRoutes(menuList = [], routes = []) {
// 用于保存普通路由数据
let temp = []
// 用于保存存在子路由的路由数据
let route = []
// 遍历数据
for (let i = 0; i < menuList.length; i++) {
// 存在子路由,则递归遍历,并返回数据作为 children 保存
if (menuList[i].childMenus && menuList[i].childMenus.length > 0) {
// 获取路由的基本格式
route = getRoute(menuList[i])
// 递归处理子路由数据,并返回,将其作为路由的 childMenus 保存
route.children = fnAddDynamicMenuRoutes(menuList[i].childMenus)
// 保存存在子路由的路由
routes.push(route)
} else {
// 保存普通路由
temp.push(getRoute(menuList[i]))
}
}
// 返回路由结果
return routes.concat(temp)
}
// 返回路由的基本格式
function getRoute(item) {
// 路由基本格式
let route = {
// 路由的路径
path: item.path,
// 路由名
name: item.menuName,
// 路由所在组件 必须有一段已定义好的组件名字
// component: (resolve) => require([`@/layout/Index`], resolve),
component: (resolve) => require([`../components${item.menuUrl}.vue`], resolve),
meta: {
id: item.menuType,
// icon: item.icon
},
// 路由的子路由
children: []
}
// 返回 route
return route
}
export default routers
axios封装的API
store.js状态库
// 导入pinia库
import { defineStore } from 'pinia';
// 导入api
import { login, logOut, getRouters } from '@/request/api/system';
// 导入jwt解析器
import jwtDecode from "jwt-decode";
// 导入默认导出的路由对象用于跳转路由
import router from '@/router/router';
export const tokenStore = defineStore({
id: 'myStore',
state: () => ({
jwtToken: null,
user_name: null,
user_name_id: null,
user_type: null,
menu: null,
}),
actions: {
getRouters(userId) {
return new Promise((resolve) => {
getRouters(userId).then(res => {
console.log(res);
resolve(res)
})
})
},
doLogin(params) {
login(params).then((res) => {
if (res.status == 200) {
const jwtToken = res.data; // 从响应中获取JWT
sessionStorage.setItem('jwtToken', jwtToken);
this.jwtToken = jwtToken; // pinia存储JWT
// 解码JWT令牌以获取载荷信息
const decodedToken = jwtDecode(jwtToken);
console.log(decodedToken);
//访问包含在JWT令牌中的用户信息
//保存用户类型的id便于门诊医生问诊
var user_name_id = decodedToken.user_name_id;
sessionStorage.setItem('user_name_id', user_name_id);
this.user_name_id = user_name_id;
//保存用户类型便于控制导航栏的显示与隐藏
const userType = decodedToken.user_type;
this.user_type =
userType == 1
? "系统管理员"
: userType == 2
? "挂号员"
: "门诊医生";
//跳转到主页
router.push("/index");
}
});
},
LogOut() {
return logOut();
}
},
});
system.js Axios-API
import axiosInstance from "@/request/request"
export function login(data) {
return axiosInstance({
url : "/Login",
method : "POST",
data
})
}
export function logOut() {
return axiosInstance({
url : "/LogOut",
method : "get",
})
}
export function getUserInfo(data) {
return axiosInstance({
url : "/User/select",
method : "post",
data
})
}
export function getRouters(userId) {
return axiosInstance({
url : `/UserTreeInfo${userId}`,
method : "get",
})
}
request.js axios请求实例封装
import axios from 'axios'
import { Message } from 'element-ui'
import {tokenStore} from "@/store/store";
// 创建一个 Axios 实例
const axiosInstance = axios.create({
baseURL: 'http://localhost:8080/qy', // 通用后端 Url 地址
timeout: 5000, // 请求最大等待时间,
headers: { 'Content-Type': 'application/json' },
})
// 添加请求拦截器
axiosInstance.interceptors.request.use(
(config) => {
// 获取请求的URL
const requestUrl = config.url;
console.log(requestUrl);
// console.log(config);
// 提取URL路径部分/qy/Login
// const urlPath = new URL(requestUrl).pathname;
// 如果是post请求将参数data转成json字符串
// 检查请求方法是否为 POST
if (config.method === 'post' || config.method === 'POST') {
// 将请求数据转换为 JSON 字符串
config.data = JSON.stringify(config.data);
}
if (config.method === 'get' || config.method === 'GET') {
config.headers['Content-Type'] = 'x-www-form-urlencoded';
}
// 在请求头中获取令牌信息
const jwtToken = tokenStore().jwtToken // 从pinia中获取令牌
// 检查是否是登录请求,这里假设登录请求的URL是 '/Login'
if (requestUrl !== '/Login' && requestUrl !== '/LogOut') {
console.log(requestUrl);
// 如果不是登录请求,添加令牌到请求头
if (jwtToken) {
config.headers.Authorization = `${jwtToken}`
}
}
return config
},
(error) => {
return Promise.reject(error)
}
)
//添加响应拦截器
axiosInstance.interceptors.response.use((response) => {
var res = response.data
// console.log(res);
// 设置请求状态弹窗提示
if (res.status == 200) {
//请求成功提示
Message.success(res.msg);
}
else if(res.msg === "菜单载入成功") {
return res
}
else {
Message.error(res.msg);
}
// 后端响应Resbody的data数据
return res
},
(error) => {
return Promise.reject(error)
}
)
export default axiosInstance
3.编写菜单树组件
- 接受父组件菜单树,递归遍历渲染树菜单
MenuTree.vue
<template>
<div>
<!--
:default-active 一进页面默认显示的页面
unique-opened 保持一个子菜单的打开
router 采用路由模式 菜单上的index就是点击跳转的页面
text-color 菜单文字的颜色
active-text-color 菜单激活后文字的颜色
-->
<el-menu
default-active
background-color="#2b333e"
router
text-color="#fff"
active-text-color="#ffd04b"
>
<template v-for="item in menuData">
<el-submenu
v-if="item.children && item.children.length > 0"
:key="item.id"
:index="item.path"
>
<template slot="title">
<i class="el-icon-menu"></i>
<span>{{ item.name }}</span>
</template>
<!-- 若有子菜单递归渲染 -->
<menu-tree :menuData="item.children" />
</el-submenu>
<el-menu-item v-else :key="item.id" :index="item.path">{{
item.name
}}</el-menu-item>
</template>
</el-menu>
</div>
</template>
<script>
export default {
props: {
menuData: {},
},
name: "MenuTree",
};
</script>
4.主页中使用菜单树组件
- 导入组件并注册MenuTree.vue,通过JSON.parse()转换菜单树对象menuData,后父传子menuData渲染菜单树
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<!-- 整个页面 -->
<div class="index">
<!-- 左导航 -->
<div
class="leftNav"
:style="{
width: leftNavWidth,
visibility: show,
transition: transitionParam,
}"
>
<!-- 标题 -->
<h2 style="color: #fff; margin: 20px 0">青芽在线医疗</h2>
<!-- 动态导航 -->
<!-- {{ menuData }} -->
<menu-tree :menuData="menuData"></menu-tree>
</div>
<!-- 主界面 -->
<div
class="mainSection"
:style="{ width: mainSectionWidth, transition: transitionParam }"
>
<!-- 标题头部 -->
<div class="QYheader">
<span class="el-icon-s-operation" @click="controlWidth"></span>
<span class="QYheaderFont"
><el-button type="primary" @click="LogOut">退出登录</el-button></span
>
<div class="QYheaderRight">
<span class="el-icon-user-solid"></span>
<span class="QYheaderRightFont">{{ user_name }}</span>
</div>
</div>
<!-- 二级路由部分 -->
<div class="QYcontent">
<router-view></router-view>
</div>
<!-- QYcontent -->
</div>
<!-- mainSection -->
</div>
<!-- index -->
</template>
<script>
import { tokenStore } from "@/store/store";
import MenuTree from "../components/MenuTree.vue";
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: "mainSection",
components: {
MenuTree,
},
data() {
return {
menuData: JSON.parse(sessionStorage.getItem("menu")),
tokenStore: tokenStore(),
//接收从Login页传来的登录用户名
user_name: tokenStore().user_name,
//接收从Login页传来的用户类型
user_type: tokenStore().user_type,
//设置导航和主界面默认宽高
leftNavWidth: "16%",
mainSectionWidth: "84%",
show: "visible",
transitionParam: "width 0.5s ease",
};
},
methods: {
//控制导航和主界面的宽和高
controlWidth() {
console.log("已进入控制宽度方法");
this.leftNavWidth = this.leftNavWidth === "16%" ? "0%" : "16%";
//控制左导航的显示与隐藏 同时设置mainSectionWidth的宽和高
if (this.leftNavWidth === "16%") {
this.show = "visible";
this.mainSectionWidth = "84%";
} else if (this.leftNavWidth === "0%") {
this.show = "hidden";
this.mainSectionWidth = "100%";
}
},
LogOut() {
// 删除所有本地缓存包括令牌信息
// localStorage.clear();
this.tokenStore.LogOut().then((res) => {
if (res.status == 200) {
// 删除所有本地缓存包括令牌信息
sessionStorage.clear();
// 重置获取路由的标记
tokenStore.flag = false;
// 跳转到登录页面
this.$router.push({ path: "/Login" });
}
});
// localStorage.removeItem("user_name");
// localStorage.removeItem("user_type");
},
},
};
</script>
<style>
@import url(../css/index.css);
</style>
相关文章:

使用JavaScript实现复杂功能:一个完整的电商网站搜索功能
随着互联网的发展,电子商务网站已经成为人们购物的重要平台。而在这些网站中,搜索功能无疑是核心功能之一。用户可以通过搜索快速找到他们需要的商品,从而提高购物体验。本文将详细介绍如何使用JavaScript实现一个完整的电商网站搜索功能。

抖音直播原理解析-如何在 Web 中播放 FLV 直播流
Media Source Extensions API(MSE)媒体源扩展 API 提供了实现无插件且基于 Web 的流媒体的功能,不同于简单的使用video元素,video元素对于开发者来说完全是一个黑盒,浏览器自己去加载数据,加载完了自己解析,解码再播放,这个过程中开发者无法进行任何操作。利用 MSE API 开发者可以自定义获取流媒体数据并且还可以对数据做一些操作。MSE 的兼容性如下图所示。可以发现 MSE 的兼容性还算可以,IE 11 都支持。

JavaScript DOM之Cookie详解
随着互联网的不断发展各种基于互联网的服务系统逐渐多了起来,我们常常需要记录访问者的一些信息,比如用户的账号,购物车存储的商品等,就需要用到cookie技术。cookie最早是网景公司发明的,是一种跟踪用户会话的技术。可以理解为本地缓存,它由服务器生成,保存在用户本地浏览器上的小文本文件,它可以包含与用户相关的信息。

说说你对 TypeScript 的理解?与 JavaScript 的区别?
超集,不得不说另外一个概念,子集,怎么理解这两个呢,举个例子,如果一个集合 A 里面的的所有元素集合 B 里面都存在,那么我们可以理解集合 B 是集合 A 的超集,集合 A 为集合 B 的子集。其是一种静态类型检查的语言,提供了类型注解,在代码编译阶段就可以检查出数据类型的错误。通过类型批注提供在编译时启动类型检查的静态类型,这是可选的,而且可以忽略而使用。如果缺乏声明而不能推断出类型,那么它的类型被视作默认的动态。等数据格式,对象的类型就是用接口来描述的。的语法,所以任何现有的。对于基本类型的批注是。

elementPlust 的el-select在提示框关闭时自动弹出
主要问题就是因为filterable属性,根本解决方案是选中的时候让他失去焦点 el-select有一个visible-change事件,下拉框出现/隐藏时触发。当el-select添加filterable属性时,弹提示窗时,点击确定后,下拉框会自动弹出。console.log('弹窗出select', item)增加了visible-change事件。el-select事件最后增加焦点取消。

在 Spring MVC 中,用于接收前端传递的参数的注解常用的有以下几种
form-data参数使用multipart/form-data作为Content-Type,前端使用params格式传参,后端使用@RequestParam注解接收参数。- json请求体参数使用application/json作为Content-Type,前端使用data格式传参,后端使用@RequestBody注解接收参数。- 路径传参不需要设置Content-Type,前端将参数通过URL传递,后端使用@PathVariable注解接收参数。

在react中说说对受控组件和非受控组件的理解?以及应用场景
这时候当我们在输入框输入内容时,会发现输入的内容无法显示出来,此时input标签是一个可读的状态,因为value被this.state.username所控制,当用户输入时,this.state.username不会自动更新,这样的话input的内容就不会发生变化了,想要解除被控制,可以为input标签设置onChange事件,触发的时候更新state,从而导致input框内容更新。简单来讲,就是受我们控制的组件,组件的状态全程响应外部数据。

Python中如何简化if...else...语句
我们通常在Python中采用if...else..语句对结果进行判断,根据条件来返回不同的结果,如下面的例子。这段代码是一个简单的Python代码片段,让用户输入姓名并将其赋值给变量user_input。我们能不能把这几行代码进行简化,优化代码的执行效率呢?以下是对各行代码的解读。这里使用了or这个逻辑运算符,当user_input不为空时,user_input为真,name就被赋于user_input的值。采用这种方法可以轻松实现if...else语句的简化。我们可以使用一行简短的代码来实现上面的任务。

vue3 项目中 arguments 对象获取失败问题
在 vue3 项目中获取到的 arguments 对象与传入实参不符,打印出函数中的 arguments 对象如下...

前端JS代码中Object类型数据的相关知识
遍历JavaScript中的对象有几种方法,包括使用for…in循环、Object.keys()方法、Object.values()方法和Object.entries()方法。因此前端传入了日期类型数据之后,如果和后台数据库中的数据类型不一致,比如数据库中的日期数据类型格式是。前端传入的Object对象中其中某个字段值是日期类型的数据,则在前端的类型就是一个。,则数据传往后端之前需要做格式类型转换。,它的值是一个中国标准时间,比如。

深入解析JavaScript的原生原型
在JavaScript中,除了自定义对象,还存在很多由JavaScript语言本身提供的原生对象。这些原生对象同样基于原型继承机制,拥有自己的原型。理解原生对象的原型非常重要,可以让我们正确使用这些内置对象,也有助于进一步理解JavaScript的原型继承系统。本文将详细解析原生对象的原型结构,揭开一些常见原生对象原型的神秘面纱。学习原生对象的原型关系,有助于我们在日常开发中正确理解和使用这些JavaScript内置对象,避免一些常见陷阱。

深入三目运算符:JavaScript、C++ 和 Python 比较
三目运算符是编程中常用的条件表达式,它允许我们根据条件选择不同的值。我们将通过具体的例子分别介绍 JavaScript、C++ 和 Python 中的三目运算符,以便更好地理解它们的用法和特性。JavaScript 示例// 例子: 根据条件选择不同的值var x = 10;var y = 20;"x 大于 y" : "x 不大于 y";在这个例子中,如果x大于y,则result的值为 “x 大于 y”,否则为 “x 不大于 y”。C++ 示例// 例子: 根据条件选择不同的值。

深入解析JavaScript中new Function语法
Function是JavaScript中非常重要的内置构造函数,可以用来动态创建函数。new Function语法就是其中一种函数创建方式。但是new Function也有一定的缺点需要注意。本文将带您深入解析new Function语法,了解其应用场景以及需要注意的问题。new Function是动态创建函数的一种方式,但也有缺点。为了更好的代码质量和性能,应该慎用或避免使用。对JavaScript函数和作用域有深入理解,可以编写出更简洁、高效、稳定的代码。。

javascript的变量存储机制和原理
js的变量存储机制

uniap vue3 组件使用uni.createSelectorQuery() 获取dom报错
批量查询时,结果是按照查询的顺序返回的。由于vue3中没有this,所以使用。

将 RGB 转换为十六进制、生成随机十六进制
RGB是一种加法混色模式,它通过调节红、绿、蓝三个颜色通道的亮度来混合出各种颜色。对于每个颜色通道,取值范围是0到255,0表示该通道对应的颜色分量没有亮度,255表示达到最大亮度。

nodemon(自动重启 node 应用程序)的安装与使用
(2).键入命令 set-ExecutionPolicy remoteSigned。windows 默认不允许 npm 全局命令执行脚本文件,所以需要修改执行策略。全局安装完成之后就可以在命令行的任何位置运行 nodemon 命令。(4)、再运行 nodemon app.js ok。我们可以执行安装选项 -g 进行全局安装。1、安装,在随意一个命令窗口都可以。自动重启 node 应用程序。(3)、输入Y 或者 A。

如何优化Uniapp应用程序的性能?
避免频繁的重绘和重排:频繁的DOM操作会导致浏览器频繁的重绘和重排,影响性能。使用v-for中的key属性:在使用v-for渲染列表时,为每个列表项添加唯一的key属性,这样可以减少渲染的次数,提高渲染的效率。减少页面加载时间:避免页面过多和过大的组件,减少不必要的资源加载。使用图片懒加载:对于图片较多的场景,可以使用图片懒加载的方式,当图片进入用户可视范围时再进行加载,减少初始页面加载的时间。节流和防抖:对于频繁触发事件的场景,可以使用节流和防抖的方法来减少事件处理的频率,从而提高性能。

鸿蒙开发-ArkTS基础,它与TS区别在那?
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。说明: 也就是前端开发过程中所有的js/ts语法大部分支持的,比如es6中的箭头函数-模板字符串-promise-async/await-数组对象方法- 注意: 根据对下一代的Next版本的内部沟通,下一版本的ArkTs对类型最了更一步的限制。

vue+element ui实现图片上传并拖拽进行图片排序
vue+element ui实现图片上传并拖住进行图片排序

TypeScript基础知识:类型断言
语法,我们可以将一个值断言为特定类型或将联合类型的变量断言为其中一个类型。在实际开发中,合理使用类型断言可以提高代码的可读性和维护性。中,类型断言是一种强制将一个值视为特定类型的方式。它允许开发人员在编译时指定变量的类型,从而获得更好的类型检查和代码提示。类型断言是一种告诉编译器某个值的具体类型的方法。中的一项强大特性,它允许开发人员在编译时明确指定变量的类型,以获得更好的类型检查和代码提示。中的类型断言,并提供丰富的示例代码帮助读者更好地理解和应用这一特性。将一个联合类型的变量断言为其中一个类型。

2024年,前端必会的console骚操作
调试。程序员们努力地避免的东西,只为在代码中制造更多的错误。编写无错误的代码是即使是最好的程序员也会觉得难以实现的。这就是为什么你应该总是调试代码。而调试JavaScript代码的最好方法之一就是了不起的。除此之外,还有更好的方法。这也正是本文的重点。告诉你与控制台交互的更好方法。在复杂的IDE中输入控制台会出现各种自动补全。在Visual Studio Code中输入console时的自动补全选项。与使用普通的不同,这里有一些更好的选择。使用这些使调试过程变得更加容易和快速。

JavaScript中内置对象--数学对象
1、数学对象Math 2、日期对象new Date() 3、数组对象new Array 4、字符串对象new String()1、自定义对象(computer/car) 2、DOM对象(div/p) 3、BOM对象(window/console) 4、内置对象。

html 原生网页使用ElementPlus 日期控件el-date-picker换成中文
原生的html,加jQuery使用不习惯,新html页面导入vue3,element plus做界面,现在需要把日历上英文切成中文。elementplus, vue3对应的js都可以通过创建一个vue3项目找到对应的脚本导入)然后在node_modules对应目录的文件,把它拷贝到html项目即可。

学习调整echarts中toolbox位置toolBox工具栏属性
学习调整echarts中toolbox位置toolBox工具栏属性

OpenHarmony之消息机制实现
以上只是消息机制核外用户态的实现,最后会执行到系统调用以上的内容只是简单介绍了OpenHarmony之消息机制实现,没有具体到代码分析,移植等细节。要想成为一名鸿蒙高级开发,以上知识点是必须要掌握的,除此之外,还需要掌握一些鸿蒙应用开发相关的一些技术,需要我们共同去探索。

HarmonyOS UI框架简介
HarmonyOSUI框架是一个用于构建跨设备应用的开发框架,它属于HarmonyOS系统架构的上层框架。该框架通过提供一系列的开发模型、声明式UI范式、系统API等,帮助开发者更高效地构建用户界面。在HarmonyOSUI框架中,开发语言目前主要支持arkts/TS语言。该框架通过自研的声明式UI范式,使开发者能够描述用户界面的状态和变化,而无需关注具体的实现细节。这种范式降低了学习成本,提高了开发效率。

了解JavaScript中的基本类型值和引用类型值
/创建空对象并将其引用赋给变量avar b={};//创建空对象并将其引用赋给变量bvar c=[];//创建空数组并将其引用赋给变量c以上示例中,变量a和变量b都是指向了一个空对象,如果new Object()不传参数的话,那么用new Object()和{}来创建对象的效果是相同的。但是如果传入不同的参数,会有不同的效果。传入String 返回String,类似new String()传入Number 返回Number,类似new Number()

vue3解决切换tab页每次切换加载数据导致数据缓慢问题
使用标识符来进行辨认 有两个tab页 搞个动态加载 在开头的vedioload还没开始加载的时候判断是否加载过 入股已经加载过 则返回 不要重新加载。由标签页的离线和在线数据 都分开管理 使用两个列表:即一个数组两个对象进行存储 数组的下标有tab0 tab1 动态决定 代替原来的直接覆盖数据。loadvideos会根据loadedTabs的状态决定是否需要加载数据。