一个Vue项目可以同时用两个UI框架吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个Vue项目可以同时用两个UI框架吗?相关的知识,希望对你有一定的参考价值。
比如说一个Vue的项目同时用iview和layUI,项目中分别用到两个UI框架中的不同模块,会冲突吗?
可以用的,不会冲突~考虑打包大小~建议按需引入 参考技术A 可以啊,但是自己掂量咯,别把项目搞那么大就行了不依赖框架用vue3空白项目从头打造一个过得去的前端
通过全程参与,可以加深对VUE项目的理解。
近期做的一个项目,前端除了UI外,没有使用什么框架。不使用现成的框架是无奈之举,因为找不到合适的。之前用的框架,比较老旧,还是vue2的;新的吧,有学习成本,怕耽误时间,也不知道效果怎么样,存在一定的风险。利用最基本的“空白”项目,按需添加基础功能,代码可控,进度也较有保证,同时还能够消除无框架不会工作恐惧症。现在记录一下心得,以后可以反复使用。
记录重点有:
0、整体结构
1、路由
2、导航条及子菜单
3、ajax请求封装
4、vue.config.js及系统配置
5、登录及退出
一、整体结构
1、创建项目
首先是新创建一个vue3项目。方法是
vue create 项目名称
然后选择合适的选项。具体可参考拙作
vue3多个项目共享开发和单个项目独立打包的解决方案
1)按默认方案创建
项目结构:
2)创建时增加路由及store支持
多了router、store以及一些页面。
3)我们项目的整体结构
实际项目中,当然还会夹带一些私货,额外增加一些东东。
2、项目入口main.js
注意项目的入口不是App.vue,而是main.js。
import createApp from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
main.js是系统约定好的名称,正如一般程序的入口是函数void main()一样。整个项目的入口是main.js,然后每个模块的入口可以是index.js。都是js。本质上,vue是一个大的js语法糖。它有这样那样的结构,让人只把杭州作汴州,但归根到底,它最终是要编译成原始的js,才能被浏览器识别、运行。
从上述代码可以知道,main.js的作用是加载App.vue,引入store、路由,然后绑定到页面id="app"的div。这样该div就是整个项目的活动区域,即展示页面内容的区域了:
vue项目是单页面应用,只有一张html页面。我们看到的所有内容,都展示在id="app"的这个div上!完全由js控制。
3、我们项目里的main.js
main.js这里的引用,都是全局性的。除了路由,store,还可以引入ui框架,css,全局性组件等等。比如我们项目里的main.js是这样写:
import createApp from "vue";
import App from "./App.vue";
import router from "./router";
import PerfectScrollbar from "vue3-perfect-scrollbar";//滚动条美化
import "vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css";
import Antd from "ant-design-vue";//ant design vue,UI框架
import "ant-design-vue/dist/antd.css";
import "@/assets/css/default.css"; //自定义的全局css
createApp(App).use(Antd).use(PerfectScrollbar).use(router).mount("#app");
二、路由
简单来说,路由就是菜单配置,将菜单项的id,路径,都集中写在了一个配置文件里。
1、系统自动生成的路由
import createRouter, createWebHashHistory from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
path: '/',
name: 'home',
component: HomeView
,
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
]
const router = createRouter(
history: createWebHashHistory(),
routes
)
export default router
以上完全是系统自动生成的代码。看上去也不难理解。其中路由表routes对应的是导航条
2、实际项目中的路由
见本文第六章第一条
3、代码中使用路由
如果想多加几个导航条,可以依葫芦画瓢,很容易就能实现。每个路由,name是唯一的ID,在代码里控制跳转的话,引用name就可以,可以不再重复写这个path。比如在某个vue里,可以这样使用路由:
import defineComponent from "vue";
import useRouter from "vue-router"; //引入useRouter
export default defineComponent(
setup()
const router = useRouter();
const browseIt = (fd) =>
const to = router.resolve(
name: "about", //这里是跳转页面的name,要与路由设置保持一致
params: id: fd.id ,
);
window.open(to.href, "_blank");//新开一个页面,打开about
;
return
browseIt,
;
,
);
三、导航条及子菜单
1、导航条
系统生成的代码,已经做了很好的示范:
<template>
<!-- 导航条 -->
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<!-- 导航的目的地。注意该部分必不可少 -->
<router-view/>
</template>
通常,我们的菜单可以从服务器端返回,然后利用循环语句输出。
2、子菜单
导航条是一级菜单,二级或以下是子菜单。子菜单,可以利用UI框架来完成。比如我们利用ant design vue的menu组件来完成
四、ajax请求封装
我们做的项目,总免不了要从服务器端请求数据。前后端分离,理论上前端的数据都来自于服务器端。
目前一般是结合第三方组件axios对ajax请求进行封装。理由主要有2个:
1)ajax一般有超时、返回代码区别对待等共性操作,封装一个ajax处理方法,统一调用,方便维护和修改;除此之外,axios还可以对ajax请求进行拦截,使得请求前、请求后、结果返回做相应处理。
2)解决跨域问题。axios本身似乎并不解决跨域问题,但由于第一点,它对ajax请求进行了封装,我们可以利用一个统一方法,结合api路径前缀做转发,使得浏览器以为api所在路径与前端是同一台服务器,因而不存在跨域。注意所谓跨域问题,是浏览器的一个安全设置,是一种保护措施。只要它不觉得跨域,那跨域就不存在。
1、统一的ajax封装方法
1)ajax封装代码(src/request/index.js)
import axios from "axios";
// 创建一个 axios 实例
const service = axios.create(
baseURL: "/api", // 所有的请求地址前缀部分
timeout: 60000, // 请求超时时间毫秒
withCredentials: true, // 异步请求携带cookie
headers:
// 设置后端需要的传参类型
"Content-Type": "application/json",
//'token': 'your token',
"X-Requested-With": "XMLHttpRequest",
,
);
// 添加请求拦截器
service.interceptors.request.use(
function (config)
// 在发送请求之前做些什么
return config;
,
function (error)
// 对请求错误做些什么
console.log(error);
return Promise.reject(error);
);
// 添加响应拦截器
service.interceptors.response.use(
function (response)
console.log(response);
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
// dataAxios 是 axios 返回数据中的 data
const dataAxios = response.data;
// 这个状态码是和后端约定的
//const code = dataAxios.reset;
return dataAxios;
,
function (error)
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
console.log(error);
return Promise.reject(error);
);
export default service;
2)使用ajax统一封装方法
import request from "@/request";
export const userLogin = (params) =>
return request( //request就是统一封装好的方法
url: "/sys/login",//注意request方法会在前面加上前缀“/api”,变成实质上是请求 “/api/sys/login”
params,
method: 'post'
)
2、开发环境中,利用vue.config.js做api路径转发
如上所属,ajax的封装方法request,会在api请求路径前加上前缀“/api”,可以利用这一点来设置转发。转发是为了避免跨域。其原理,表面上,我们请求的是当前服务器的路径“/api/a/b/c”,但我们设置凡“/api”开头的路径,都转发到另一台服务器(即后端所在服务器)。浏览器蒙在鼓里,并没有察觉,因此不会触发所谓跨域警告。
devServer:
//devServer 只是一个webpack插件 只能用于开发环境
proxy:
"/api":
target: "192.168.0.22",
pathRewrite:
"^/api": "",
,
,
,
,
3、生产环境中,利用nginx做api路径转发
location /api/
proxy_pass http://192.168.0.22:8090/;#必须斜杠/结尾
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
五、vue.config.js及系统配置
有关vue.config.js里面的配置,上面约略提到了一些,这里给出完整代码:
1、系统生成的vue.config.js代码
const defineConfig = require('@vue/cli-service')
module.exports = defineConfig(
transpileDependencies: true
)
2、按项目需要修改后的代码
const defineConfig = require("@vue/cli-service");
const path = require("path");
const appConfig = require("./public/config");
const resolve = (dir) =>
return path.join(__dirname, dir);
;
module.exports = defineConfig(
transpileDependencies: true,
devServer:
//devServer 只是一个webpack插件 只能用于开发环境
proxy:
"/api":
target: appConfig.server,
pathRewrite:
"^/api": "",
,
,
,
,
// 项目部署基础
// 默认情况下,我们假设你的应用将被部署在域的根目录下,
// 例如:https://www.my-app.com/
// 默认:'/'
// 如果您的应用程序部署在子路径中,则需要在这指定子路径
// 例如:https://www.foobar.com/my-app/
// 需要将它改为'/my-app/'
publicPath: "/",
chainWebpack: (config) =>
config.resolve.alias
.set("@", resolve("src")) // key,value自行定义,比如.set('@@', resolve('src/components'))
.set("_c", resolve("src/components"));
config.plugin("html").tap((args) =>
args[0].title = appConfig.app.name;
return args;
);
,
);
值得一提的是,里面的devServer元素设置,针对的是开发环境。详见拙作:vue.config.js中的devServer。
3、真正的项目配置
按我的理解,vue.config.js只在开发阶段和发布时有用,之后就像被消费了的耗材,没啥用处了。同一项目中,真正的项目配置,是/public/config/index.js,即使是发布、部署到生产环境,仍然可以修改,是真正意义上的配置文件。
/public/config/index.js
exports.app =
name: "订餐拿饭抓阄系统",
owner: "蓬蓬养猪场",
developer: "一群饭桶",
;
详见拙作:vue项目读取全局配置
六、登录及退出
主要是路由的应用。原理是:
将页面分为无须登录可浏览和必须登录方可浏览2种。在路由表中做过滤。当转向必须登录页面时,检查登录状态,如果已登录,放行;未登录,转向登录页。注意登录页要设为无须登录可浏览。流程很简单,大家都明白,就不画流程图了。
1、路由表(/src/router/index.js)
完整的路由表。有关登录控制部分,见所谓“路由守卫”。
import createRouter, createWebHashHistory from "vue-router";
import Home from "../views/home/PageIndex.vue";
const routes = [
path: "/login",
name: "login",
component: () => import("../views/login/PageIndex.vue"),
meta:
noLogin: true, //无须登录即可浏览。自定义属性
,
,
path: "/",
name: "Home",
component: Home,
,
path: "/map",
name: "Map",
component: () => import("../views/map/PageIndex.vue"),
,
path: "/resource",
name: "Resource",
component: () => import("../views/resource/PageIndex.vue"),
,
path: "/resource/detail/:id",
name: "ResourceDetail",
component: () => import("../views/resource/PageDetail.vue"),
,
path: "/sys",
name: "Sys",
component: () => import("../views/sys/PageIndex.vue"),
,
];
const router = createRouter(
history: createWebHashHistory(),
routes,
);
// 路由守卫
router.beforeEach((to, from, next) =>
const isLogin = localStorage.isLogin ? true : false;
if (isLogin)
//已经登录的情况下,不能再打开登录页
to.path === "/login" ? next("home") : next();
else
//如果无须登录则直接打开,否则转向登录页面
to.meta.noLogin || to.path === "/login" ? next() : next("/login");
);
export default router;
2、登录及登出
注意要使用router本身的方法,不可用原始的js,如window.location.href = *** 这种方法,否则部署到nginx会报错。
1)登录
const router = useRouter();
localStorage.setItem("isLogin", true);
document.cookie = "token=" + res.token;
router.replace( path: "/" );//转向首页。使用replace,避免登录后回退问题
2)登出
const router = useRouter();
localStorage.removeItem("isLogin");
router.replace( path: "/login" );
七、store
暂无
以上是关于一个Vue项目可以同时用两个UI框架吗?的主要内容,如果未能解决你的问题,请参考以下文章