最全一篇文带你使用vue完成一个完整后台_后台vue,2024年最新妈妈再也不用担心我找工作了

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

    />
    <span class="show-pwd" @click="showPwd">
      <svg-icon
        :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
      />
    </span>
  </el-form-item>


const validateUsername = (rule, value, callback) => {
if (value.length < 5) {
callback(new Error(‘用户名最少5位’))
} else if (value.length > 12) {
callback(new Error(‘用户名最长12位’))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 5) {
callback(new Error(‘用户名最少5位’))
} else if (value.length > 16) {
callback(new Error(‘用户名最长16位’))
} else {
callback()
}
}

loginRules: {
username: [{ required: true, trigger: ‘blur’, validator: validateUsername }],
password: [
{ required: true, trigger: ‘blur’, validator: validatePassword },
{ min: 5, max: 12, trigger: ‘blur’, message: ‘密码长度应该在5-12位之间’ }
]
}


#### Vue-Cli配置跨域代理


出现跨域的原因是什么呢?  
 因为当下流行的是前后端分离单独开发,前端项目和后端接口不在同域名之下,那前端访问后端接口就出现跨域了  
 那么问题就来了 如何解决呢?  
 我们所遇到的这种跨域是位于开发环境的,真正部署上线时的跨域是生产环境的,解决方式又不同  
 我们先解决开发环境,生产环境在打包上线事可以解决,后面再讲


##### 解决开发环境的跨域问题


开发环境的跨域,也就是在**vue-cli脚手架环境下开发启动服务时,我们访问接口所遇到的跨域问题,vue-cli为我们在本地开启了一个服务,可以通过这个服务帮我们代理请求**,解决跨域问题  
 也就是vue-cli配置webpack的反向代理


在`vue.config.js`中进行反向代理配置



module.exports = {
devServer: {
proxy: {
‘api/private/v1/’: {
target: ‘http://127.0.0.1:8888’, // 我们要代理的地址,当匹配到上面的’api/private/v1/'时,会将http://localhost:9528 替换成 http://127.0.0.1:8888
changeOrigin: true, // 是否跨越 需要设置此值为 true 才可以让本地服务代理我们发送请求
pathRewrite: {
// 重新路由 localhost:8888/api/login => http://127.0.0.1:8888/api/login
‘^/api’: ‘/api’,
‘/hr’: ‘’
}
}
}
}
}


同时,还需要注意的是,我们同时需要注释掉 mock的加载,因为mock-server会导致代理服务的异常



// before: require(‘./mock/mock-server.js’), // 注释mock-server加载


#### 封装单独的登录接口



export function login(data) {
// 返回一个axios对象 => promise // 返回了一个promise对象
return request({
url: ‘login’, // 因为所有的接口都要跨域 表示所有的接口要带 /api
method: ‘post’,
data
})
}


#### 封装Vuex的登录Action并处理token


##### 在Vuex中对token进行管理


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526093131489.png)  
 上图中,组件直接和接口打交道,这并没有什么问题,但是ta用的**钥匙**来进行相互传递,我们需要让vuex来介入,将用户的token状态共享,更方便的读取  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2021052609330162.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)  
 `store/modules/user.js配置`



// 状态
const state = {}
// 修改状态
const mutations = {}
// 执行异步
const actions = {}
export default {
namespaced: true,
state,
mutations,
actions
}


设置token共享状态



const state = {
token: null
}


##### 操作 token


`utils/auth.js` 中,基础模板已经为我们提供了获取 token ,设置 token ,删除 token 的方法,可以直接使用



const TokenKey = ‘haitun_token’

export function getToken() {
// return Cookies.get(TokenKey)
return localStorage.getItem(TokenKey)
}

export function setToken(token) {
// return Cookies.set(TokenKey, token)
return localStorage.setItem(TokenKey, token)
}

export function removeToken() {
// return Cookies.remove(TokenKey)
return localStorage.removeItem(TokenKey)
}


##### 初始化token状态


`store/modules/user.js`



import { getToken, setToken, removeToken } from ‘@/utils/auth’
const state = {
token: getToken() // 设置token初始状态 token持久化 => 放到缓存中
}


##### 提供修改token的mutations



// 修改状态
const mutations = {
// 设置token
setToken(state, token) {
state.token = token // 设置token 只是修改state的数据 123 =》 1234
setToken(token) // vuex和 缓存数据的同步
},
// 删除缓存
removeToken(state) {
state.token = null // 删除vuex的token
removeToken() // 先清除 vuex 再清除缓存 vuex和 缓存数据的同步
}
}


##### 封装登录的Action


登录action要做的事情,调用登录接口,成功后设置token到vuex,失败则返回失败



// 执行异步
const actions = {
// 定义login action 也需要参数 调用action时 传递过来的参数
async login(context, data) {
const result = await login(data) // 实际上是一个promise result是执行的结果
// axios默认给数据加了一层data
if (result.data.success) {
// 表示登录接口调用成功 也就是意味着你的用户名和密码是正确的
// 现在有用户token
// actions 修改state 必须通过mutations
context.commit(‘setToken’, result.data.data)
}
}
}


为了更好的让其他模块和组件更好的获取token数据,我们要在`store/getters.js`中将token值作为公共的访问属性放出



const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token // 在根级的getters上 开发子模块的属性给别人看 给别人用
}
export default getters


通过此内容,我们可以有个脑图画面了  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526094337720.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


##### 区分axios在不同环境中的请求基础地址


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526094459623.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)  
 前端两个主要区分环境,开发环境,生产环境


环境变量 `$ process.env.NODE_ENV # 当为production时为生产环境 为development时为开发环境`  
 我们可以在\*\*.env.development和.env.production\*\*定义变量,变量自动就为当前环境的值  
 基础模板在以上文件定义了变量VUE\_APP\_BASE\_API,该变量可以作为axios请求的baseURL



开发环境的基础地址和代理对应

VUE_APP_BASE_API = ‘/api’


这里配置了/api,意味着需要在Nginx服务器上为该服务配置 nginx的反向代理对应/prod-api的地址

VUE_APP_BASE_API = ‘/prod-api’


也可以都写成一样的 方便管理


在request中设置baseUrl–基准



// 创建一个axios的实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 设置axios请求的基础的基础地址
timeout: 5000 // 定义5秒超时
})


##### 处理axios的响应拦截器


![在这里插入图片描述](https://img-blog.csdnimg.cn/2021052609500735.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)



// 响应拦截器
service.interceptors.response.use(response => {
// axios默认加了一层data
const { success, message, data } = response.data
// 要根据success的成功与否决定下面的操作
if (success) {
return data
} else {
// 业务已经错误了 还能进then ? 不能 ! 应该进catch
Message.error(message) // 提示错误消息
return Promise.reject(new Error(message))
}
}, error => {
Message.error(error.message) // 提示错误信息
return Promise.reject(error) // 返回执行错误 让当前的执行链跳出成功 直接进入 catch
})


#### 登录页面调用登录action,处理异常


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526095342356.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)  
 引入辅助函数



import { mapActions } from ‘vuex’ // 引入vuex的辅助函数

methods: {
…mapActions([‘user/login’])
}


调用登录



this.KaTeX parse error: Expected '}', got 'EOF' at end of input: … this.router.push(‘/’)
} catch (error) {
console.log(error)
} finally {
// 不论执行try 还是catch 都去关闭转圈
this.loading = false
}
}
})


#### 解析


首先使用到了elementUI的from表单进行编写


中间在前台使用表单验证进行对用户输入的账户密码进行对比,是否符合标准,如果不符合我们定义的标准进行一个提示


我们对表单里面的输入框进行双向数据绑定使用`v-model`


用户输入完毕之后点击登录按钮时也要进行后台验证,当我们点击登录发送请求到后台入库查询账户密码是否正确,如不正确会弹出提示


在表单里面使用了`<svg>`标签引入 icon 图标


我们首先在`src\components`下创建了SvgIcon组件


![](https://img-blog.csdnimg.cn/img_convert/ef10f53728e56584dd523fe7e8a38646.png)


我们向外暴露了两个属性


![](https://img-blog.csdnimg.cn/img_convert/4ac990cf54891b57cf5059318c7695dd.png)


通过 computed 监控 icon 的名字和其自定义的样式,当没有指定自定义样式时候,会采用默认样式,否则会再加上自定义 class



iconName() {
return #icon-${this.iconClass}
},
svgClass() {
if (this.className) {
return 'svg-icon ’ + this.className
} else {
return ‘svg-icon’
}
}


然后进行默认样式的编写


![在这里插入图片描述](https://img-blog.csdnimg.cn/2021052608131774.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


在 `src\icons` 中的 `index.js` 中引入 svg 组件 `import IconSvg from '@/components/IconSvg'`


使用全局注册 icon-svg `Vue.component('icon-svg', IconSvg)`


这样就可以在项目中任意地方使用


为了便于集中管理图标,所有图标均放在 `@/icons/svg`


`@`代表找到src目录


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526081328410.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


require.context 有三个参数:


* 参数一:说明需要检索的目录
* 参数二:是否检索子目录
* 参数三: 匹配文件的正则表达式


在`@/main.js`中引入`import '@/icons'`这样在任意页面就可以成功使用组件了


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526081338811.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


在页面中使用就可以进行使用了




#### 完整代码




### 主页模块


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526095734458.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


#### 主页token拦截并进行处理


##### 权限拦截的流程图


我们已经完成了登录的过程,并且存储了token,但是此时主页并没有因为token的有无而被控制访问权限  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526095814710.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


#### 拦截处理代码


`src/permission.js`



import Vue from ‘vue’

import ‘normalize.css/normalize.css’ // A modern alternative to CSS resets

import ElementUI from ‘element-ui’
import ‘element-ui/lib/theme-chalk/index.css’
import locale from ‘element-ui/lib/locale/lang/zh-CN’ // lang i18n

import ‘@/styles/index.scss’ // global css

import App from ‘./App’
import store from ‘./store’
import router from ‘./router’
import i18n from ‘@/lang/index’
import ‘@/icons’ // icon
import ‘@/permission’ // permission control
import directives from ‘./directives’
import Commponent from ‘@/components’
import filters from ‘./filter’
import Print from ‘vue-print-nb’ // 引入打印

// set ElementUI lang to EN
Vue.use(ElementUI, { locale })

// 如果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)
Vue.use(Print)
Vue.config.productionTip = false
// 遍历注册自定义指令
for (const key in directives) {
Vue.directive(key, directives[key])
}
Vue.use(Commponent) // 注册自己的插件
// 注册全局的过滤器
// 遍历注册过滤器
for (const key in filters) {
Vue.filter(key, filters[key])
}
// 设置element为当前的语言
Vue.use(ElementUI, {
i18n: (key, value) => i18n.t(key)
})
new Vue({
el: ‘#app’,
router,
store,
i18n,
render: h => h(App)
})


#### 左侧导航


样式文件`styles/siderbar.scss`  
 设置背景图片



.scrollbar-wrapper {
background: url(‘~@/assets/common/leftnavBg.png’) no-repeat 0 100%;
}


左侧logo图片`src/setttings.js`



module.exports = {

title: ‘海豚电商后台管理平台’,

/**

  • @type {boolean} true | false
  • @description Whether fix the header
    */
    fixedHeader: false,

/**

  • @type {boolean} true | false
  • @description Whether show the logo in sidebar
    */
    sidebarLogo: true // 显示logo
    }

设置头部图片结构 `src/layout/components/Sidebar/Logo.vue`




完整代码




#### 头部内容的布局和样式


头部组件位置`layout/components/Navbar.vue`  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526100908405.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)


添加公司名称时要面包屑



<div class="app-breadcrumb">
  北京梦呓网络有限公司
  <span class="breadBtn">v1.0.0</span>
</div>

右侧头像和下拉菜单等设置



{{ username }}
      <i class="el-icon-caret-bottom" />
    </div>
    <el-dropdown-menu slot="dropdown" class="user-dropdown">
      <router-link to="/">
        <el-dropdown-item> 主页 </el-dropdown-item>
      </router-link>
      <a href="javascript:;">
        <el-dropdown-item>邮箱</el-dropdown-item>
      </a>
      <a href="javascript:;">
        <el-dropdown-item>设置</el-dropdown-item>
      </a>
      <el-dropdown-item @click.native="logout">
        <span style="display: block">退出</span>
      </el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</div>

完整代码:样式+事件




#### 储存用户信息


新增变量:`src/store/modules/user.js`



const getDefaultState = () => {
return {
token: getToken(),
userInfo: {}, // 储存用户信息
}
}


设置和删除用户资料 mutations



// 设置用户信息
set_userInfo (state, user) {
state.userInfo = user
setUSERINFO(user)
}
// 删除用户信息
removeUserInfo (state) {
this.userInfo = {}
}


建立用户名的映射 `src/store/getters.js`



const getters = {
token: state => state.user.token,
username: state => state.user.userInfo.username
}
export default getters


最后我们换成真实名称即可



{{ username }}

这里可能会出现问题,在页面刷新拿不到数据,我们可以将其保存到本地中,然后取出


##### 实现退出功能


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526102329717.png)  
 退出:`src/store/modules/user.js`



// user logout
logout (context) {
// 删除token
context.commit(‘removeToken’) // 不仅仅删除了vuex中的 还删除了缓存中的
// 删除用户资料
context.commit(‘removeUserInfo’) // 删除用户信息
},


mutation



removeToken (state) {
state.token = null
removeToken()
removeUSERINFO()
removeLocalMenus()
},
removeUserInfo (state) {
this.userInfo = {}
},


头部菜单调用 `src/layout/components/Navbar.vue`



async logout () {
await this. s t o r e . d i s p a t c h ( ′ u s e r / l o g o u t ′ ) t h i s . store.dispatch('user/logout') this. store.dispatch(user/logout)this.router.push(/login)
}


完整代码:




#### token失效介入


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526102932693.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)  
 `src/utils/auth.js`



const timeKey = ‘haitun-setTimeStamp’ // 设置一个独一无二的key
// 存储 token 的时间戳(存的是 setToken 方法执行的时间)
// 获取时间戳
export function setTimeStamp () {
return localStorage.setItem(timeKey, Date.now())
}
// 获取 token 的过期时间
export function getTimeStamp () {
return localStorage.getItem(timeKey)
}


`src/utils/request.js`



import axios from ‘axios’
import { Message } from ‘element-ui’
import store from ‘@/store’
import router from ‘…/router’
import { getToken, getTimeStamp, removeToken } from ‘@/utils/auth’

// 定义 token 超时时间
const timeOut = 3600 * 24 * 3
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
timeout: 5000 // request timeout
})

// request interceptor
service.interceptors.request.use(
// 注入token
config => {
// do something before request is sent

if (store.getters.token) {
  // 判断当前 token 的时间戳是否过期
  // 获取 token 设置的时间
  const tokenTime = getTimeStamp()
  // 获取当前时间
  const currenTime = Date.now()
  if ((currenTime - tokenTime) / 1000 > timeOut) {
    // 如果它为true表示 过期了
    // token没用了 因为超时了
    store.dispatch('user/logout') // 登出操作
    // 跳转到登录页
    router.push('/login')
    return Promise.reject(new Error('登录过期了,请重新登录'))
  }
  config.headers['Authorization'] = getToken()
}
return config

},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)

// response interceptor
service.interceptors.response.use(
response => {
const { meta: { status, msg }, data } = response.data
// if the custom code is not 20000, it is judged as an error.
if (status !== 200 && status !== 201) {
// 处理 token 过期问题
if (status === 400 && msg === ‘无效的token’) {
removeToken()
store.dispatch(‘user/logout’)
router.push(‘login’)
}
Message({
message: msg || ‘Error’,
type: ‘error’,
duration: 5 * 1000
})
return Promise.reject(new Error(msg || ‘Error’))
} else {
return data
}
},
error => {
console.log(‘err’ + error) // for debug
Message({
message: error.message,
type: ‘error’,
duration: 5 * 1000
})
return Promise.reject(error)
}
)

export default service


在登录的时候,如果登录成功,我们就应该设置时间戳  
 `src/store/modules`



async login (context, userInfo) {
const { username, password } = userInfo
const res = await login({ username: username.trim(), password: password })
// 设置用户信息
const token = res.token
context.commit(‘set_token’, token)
context.commit(‘set_userInfo’, res)
// 设置用户权限信息
const permission = await getMenus()
const menus = filterPermission(permission)
context.commit(‘set_menus’, menus)
},


token失效处理  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210526103451414.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JsdWVfNjk4,size_16,color_FFFFFF,t_70)  
 `src/utils/request.js`



response => {
const { meta: { status, msg }, data } = response.data
// if the custom code is not 20000, it is judged as an error.
if (status !== 200 && status !== 201) {
// 处理 token 过期问题
if (status === 400 && msg === ‘无效的token’) {
removeToken()
store.dispatch(‘user/logout’)
router.push(‘login’)
}
Message({
message: msg || ‘Error’,
type: ‘error’,
duration: 5 * 1000
})
return Promise.reject(new Error(msg || ‘Error’))
} else {
return data
}


路由、页面、用户管理、权限管理等等需要什么页面自己开发即可,步骤相似的


### 多语言切换、tab页全屏


#### 全屏插件的引用


安装全局插件screenfull



npm i screenfull


封装全屏插件`src/components/ScreenFull/index.vue`




全局注册该组件 `src/components/index.js`



import ScreenFull from ‘./ScreenFull’
Vue.component(‘ScreenFull’, ScreenFull) // 注册全屏组件


放置`layout/navbar.vue`




.right-menu-item {
vertical-align: middle;
}


#### 设置动态主题


封装全屏插件 `src/components/ThemePicker/index.vue`


![img](https://img-blog.csdnimg.cn/img_convert/cc47208a91baa75e98a25d50d720cad5.png)
![img](https://img-blog.csdnimg.cn/img_convert/22e7936ffd88d65afc983f69b27431df.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

 Message({
        message: msg || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
      return Promise.reject(new Error(msg || 'Error'))
    } else {
      return data
    }

路由、页面、用户管理、权限管理等等需要什么页面自己开发即可,步骤相似的

多语言切换、tab页全屏

全屏插件的引用

安装全局插件screenfull

npm i screenfull

封装全屏插件src/components/ScreenFull/index.vue

<template>
  <!-- 放置一个图标 -->
  <div>
    <!-- 放置一个svg的图标 -->
    <svg-icon
      icon-class="fullscreen"
      style="color: #fff; width: 20px; height: 20px"
      @click="changeScreen"
    />
    <!-- <i class="el-icon-rank" @click="changeScreen" /> -->
  </div>
</template>

<script>
import ScreenFull from 'screenfull'
export default {
  methods: {
    //   改变全屏
    changeScreen () {
      if (!ScreenFull.isEnabled) {
        // 此时全屏不可用
        this.$message.warning('此时全屏组件不可用')
        return
      }
      // document.documentElement.requestFullscreen()  原生js调用
      //   如果可用 就可以全屏
      ScreenFull.toggle()
    }
  }
}
</script>

<style>
</style>


全局注册该组件 src/components/index.js

import ScreenFull from './ScreenFull'
Vue.component('ScreenFull', ScreenFull) // 注册全屏组件

放置layout/navbar.vue

<screen-full class="right-menu-item" />

-------------------------------

.right-menu-item {
   vertical-align: middle;
}

设置动态主题

封装全屏插件 src/components/ThemePicker/index.vue

[外链图片转存中…(img-9wtZJ9SP-1715824328049)]
[外链图片转存中…(img-FubGjMYR-1715824328049)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以用中文回答您的问题。 使用Vue2创建一个后台项目需要进行以下步骤: 1. 创建Vue项目:首先,您需要使用Vue CLI创建一个Vue项目。您可以通过以下命令来创建一个新的Vue项目: ``` vue create my-project ``` 其中,`my-project`是您的项目名称。 2. 安装Vue Router:Vue Router是一个Vue官方的路由库,可以帮助您管理前端路由。要安装Vue Router,请运行以下命令: ``` npm install vue-router ``` 3. 创建路由:在您的Vue项目中,您需要创建一个路由文件来定义页面之间的跳转。可以创建一个名为`router.js`的文件,将以下内容添加到文件中: ```javascript import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) const routes = [ { path: '/', name: 'Dashboard', component: () => import('./views/Dashboard.vue') }, { path: '/users', name: 'Users', component: () => import('./views/Users.vue') } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router ``` 在此示例中,我们定义了两个路由:Dashboard和Users。在`routes`数组中,我们为每个路由指定了一个路径,一个名称和一个组件。 4. 创建组件:您需要创建一个或多个组件来显示您的页面。可以创建一个名为`Dashboard.vue`的组件,其中包含您希望在仪表板页面上显示的内容。同样,可以创建一个名为`Users.vue`的组件来显示用户列表。 5. 在App.vue使用路由:最后,您需要在`App.vue`文件中使用Vue Router来渲染您的组件。可以将以下代码添加到`App.vue`文件中: ```html <template> <div id="app"> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script> ``` 这将使用Vue Router来渲染您定义的路由和组件。 这些是创建Vue2后台项目的基本步骤。当然,您可以添加更多的组件和路由,以根据您的需求定制您的项目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值