Поскольку компания недавно собирается разработать систему управления фоном, я проконсультировался со многими фреймворками vue. Я думаю, что element прост и удобен, поэтому я выбираю его в качестве нашего предпочтительного фреймворка и делюсь им со всеми. Если вы думаете, что есть какой-либо потребность в улучшении, вы можете обсудить это вместе. ,адрес гитхаба. Эта статья относительно длинная, я надеюсь, что студенты смогут терпеливо ее прочитать, если вы не понимаете, вы можете оставить сообщение ниже
один,содержание
Во-вторых, проект инициализации
Сначала установите строительные леса vue глобально, в настоящее время это третья версия vue-cli3.x, вот инструмент управления пакетами npm для установки, если ваша сеть не очень хороша, вы можете сначала установить зеркало Taobao.npm install -g cnpm -registry=https://registry.npm.taobao.org, а затем установить его через cnpm
cnpm install -g @vue/cli or npm install -g @vue/cli
После установки вы также можете проверить правильность версии (3.x) с помощью этой команды:
vue --version
После установки строительных лесов начинаем создавать наш проект
vue create vue-admin-project
Затем появятся два варианта
cd appи запускаем локальный серверnpm run serve, когда операция завершится, вам будет предложено вызвать локальный портhttp://localhost:8080, появится страница приветствия, на этом инициализация вашего проекта vue завершена.
3. Введение и организация каталога файлов
Исходный каталог перед сортировкой
|-- vue-admin-project
|-- .gitignore //git项目忽视文件
|-- babel.config.js //babel 配置文件
|-- package-lock.json //记录安装包的具体版本号
|-- package.json //包的类型
|-- README.md
|-- public //项目打包后的目录
| |-- favicon.ico
| |-- index.html
|-- src //项目开发目录
|-- App.vue //主入口文件
|-- main.js //主入口文件
|-- router.js //vue-router文件
|-- store.js //vuex
|-- assets //静态文件
|-- logo.png
|-- components //组件存放目录
|-- HelloWorld.vue
|-- views //视图目录
|-- About.vue
|-- Home.vue
Организованное оглавление, основные изменения/srcкаталог в папке
|-- vue-admin-project
|-- .gitignore
|-- babel.config.js
|-- package-lock.json
|-- package.json
|-- README.md
|-- public
|-- favicon.ico
|-- index.html
|-- src
|-- App.vue
|-- main.js
|-- assets
|-- logo.png
|-- components
|-- HelloWorld.vue
|-- router //路由配置文件夹
|-- router.js
|-- store //状态管理文件夹
|-- store.js
|-- views
|-- About.vue
|-- Home.vue
В-четвертых, среда разработки и конфигурация онлайн-среды
Основное отличие vue-cli 3.0x от vue-cli 2.0x в том, что папка структуры проекта упрощена, что тоже приносит много проблем, многие конфигурации нужно настраивать под себя.cofig/Среда разработки и онлайн-среда настраиваются в папке, а 3.0x необходимо настроить самостоятельно.
Сначала настройте среду разработки и создайте новый файл в корневом каталоге проекта..envдокумент.
NODE_ENV="development" //开发环境
BASE_URL="http://localhost:3000/" //开发环境接口地址
Далее настраиваем онлайн-окружение, а также создаем новый файл в корневой директории проекта.env.prodЭто указывает на производственную среду.
NODE_ENV="production" //生产环境
BASE_URL="url" //生产环境的地址
Теперь, как мы оцениваем текущую среду в проекте?
мы можем согласноprocess.env.BASE_URLчтобы получить, является ли это онлайн-средой или средой разработки, которая будет использоваться позже
if(process.env.NODE_ENV='development'){
console.log( process.env.BASE_URL) //http://localhost:3000/
}else{
console.log( process.env.BASE_URL) //url
}
На данный момент мы успешно настроили среду разработки и онлайн-среду.
Пять, конфигурация vue.config.js
Говоря оvue.config.jsФайл конфигурации проекта, я должен сказать, разница между 3.x и 2.x, элементы конфигурации, связанные с веб-пакетом в 2.x, находятся непосредственно в проекте.build/webpack.base.conf.jsвнутри конфигурации, а 3.x полностью вvue.config.jsВ конфигурации это делает весь проект более лаконичным и понятным, и проект работает быстрее.
Поскольку проект инициализируется безvue.config.jsфайл конфигурации, поэтому нам нужно создать новый в корневом каталоге проектаvue.config.jsэлемент конфигурации.
В этом элементе конфигурации этот проект в основном настраивает три вещи, первая — это псевдоним каталога.alias, другой — автоматически открывать браузер при запуске проекта, а последний — обрабатывать импортированный глобальный файл scss. Есть конечноvue.config.jsКонфигурация намного больше, чем это Заинтересованные студенты могут пойти и посмотретьvue.config.jsКонкретная конфигурация, конкретный код выглядит следующим образом.
let path=require('path');
function resolve(dir){
return path.join(__dirname,dir)
}
module.exports = {
chainWebpack: config => {
//设置别名
config.resolve.alias
.set('@',resolve('src'))
},
devServer: {
open:true //打开浏览器窗口
},
//定义scss全局变量
css: {
loaderOptions: {
sass: {
data: `@import "@/assets/scss/global.scss";`
}
}
}
}
Шесть, введение ElementUI
Начать установку ElementUI
vue add element
Следующие два варианта, первый импортировать все, второй импортировать по требованию, я выбираю первыйFully import, вы можете решить в соответствии с вашим собственным проектом. Далее будет задан вопрос ввести ли scss, тут выбор да, а язык ж-сп.
Далее вам будет предложено, что установка прошла успешно, и на домашней странице проекта есть кнопка в стиле элемента.
Семь, введение в маршрутизацию vue-router
Управление маршрутизацией также является основной частью этого проекта.
1. Импорт файлов
import Vue from 'vue'
import Router from 'vue-router'
import store from '../store/store' //引入状态管理
import NProgress from 'nprogress' //引入进度条组件 cnpm install nprogress --save
import 'nprogress/nprogress.css'
Vue.use(Router)
2. Маршрутизация ленивой загрузки
/**
*@parma {String} name 文件夹名称
*@parma {String} component 视图组件名称
*/
const getComponent = (name,component) => () => import(`@/views/${name}/${component}.vue`);
3. Конфигурация маршрутизации
const myRouter=new Router({
routes: [
{
path: '/',
redirect: '/home',
component: getComponent('login','index')
},
{
path: '/login',
name: 'login',
component: getComponent('login','index')
},
{
path: '/',
component:getComponent('layout','Layout'),
children:[{
path:'/home',
name:'home',
component: getComponent('home','index'),
meta:{title:'首页'}
},
{
path:'/icon',
component: getComponent('icons','index'),
name:'icon',
meta:{title:'自定义图标'}
},
{
path:'/editor',
component: getComponent('component','editor'),
name:'editor',
meta:{title:'富文本编译器'}
},
{
path:'/countTo',
component: getComponent('component','countTo'),
name:'countTo',
meta:{title:'数字滚动'}
},
{
path:'/tree',
component: getComponent('component','tree'),
name:'tree',
meta:{title:'自定义树'}
},
{
path:'/treeTable',
component: getComponent('component','treeTable'),
name:'treeTable',
meta:{title:'表格树'}
},
{
path:'/treeSelect',
component: getComponent('component','treeSelect'),
name:'treeSelect',
meta:{title:'下拉树'}
},
{
path:'/draglist',
component: getComponent('draggable','draglist'),
name:'draglist',
meta:{title:'拖拽列表'}
},
{
path:'/dragtable',
component: getComponent('draggable','dragtable'),
name:'dragtable',
meta:{title:'拖拽表格'}
},
{
path:'/cricle',
component: getComponent('charts','cricle'),
name:'cricle',
meta:{title:'饼图'}
},
]
}
]
})
4. В этом проекте есть токен для проверки проблемы с разрешением, поэтому вам нужно оценить, есть ли токен при входе на страницу, если нет, перейти на страницу входа.
//判断是否存在token
myRouter.beforeEach((to,from,next)=>{
NProgress.start()
if (to.path !== '/login' && !store.state.token) {
next('/login') //跳转登录
NProgress.done() // 结束Progress
}
next()
})
myRouter.afterEach(() => {
NProgress.done() // 结束Progress
})
5. Экспорт маршрутов
export default myRouter
Восемь, введение axios и упаковка
1. Я выбираю axios для обработки интерфейса.Поскольку он соответствует спецификации промиса, он вполне может избежать ада обратных вызовов. Теперь приступим к установке
cnpm install axios -S
2. ВsrcСоздайте новую папку в каталоге с именемapi, Создайте внутри два новых файла, одинapi.js, для интеграции интерфейса другойrequest.js, инкапсулировать запросы axios в соответствии со связанными сервисами.
- request.js
1. Введите зависимости
import axios from "axios";
import router from "../router/router";
import {
Loading
} from "element-ui";
import {messages} from '../assets/js/common.js' //封装的提示文件
import store from '../store/store' //引入vuex
2. Напишите базовые настройки axios
axios.defaults.timeout = 60000; //设置接口超时时间
axios.defaults.baseURL = process.env.BASE_URL; //根据环境设置基础路径
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded;charset=UTF-8"; //设置编码
let loading = null; //初始化loading
3. Напишите перехват запросов, то есть что делать перед запросом интерфейса
/*
*请求前拦截
*用于处理需要请求前的操作
*/
axios.interceptors.request.use(
config => {
loading = Loading.service({
text: "正在加载中......",
fullscreen: true
});
if (store.state.token) {
config.headers["Authorization"] = "Bearer " + store.state.token;
}
return config;
},
error => {
return Promise.reject(error);
}
);
4. Написать перехват ответа на запрос для обработки операций возврата данных
/*
*请求响应拦截
*用于处理数据返回后的操作
*/
axios.interceptors.response.use(
response => {
return new Promise((resolve, reject) => {
//请求成功后关闭加载框
if (loading) {
loading.close();
}
const res = response.data;
if (res.err_code === 0) {
resolve(res)
} else{
reject(res)
}
})
},
error => {
console.log(error)
//请求成功后关闭加载框
if (loading) {
loading.close();
}
//断网处理或者请求超时
if (!error.response) {
//请求超时
if (error.message.includes("timeout")) {
console.log("超时了");
messages("error", "请求超时,请检查互联网连接");
} else {
//断网,可以展示断网组件
console.log("断网了");
messages("error", "请检查网络是否已连接");
}
return;
}
const status = error.response.status;
switch (status) {
case 500:
messages("error", "服务器内部错误");
break;
case 404:
messages(
"error",
"未找到远程服务器"
);
break;
case 401:
messages("warning", "用户登陆过期,请重新登陆");
localStorage.removeItem("token");
setTimeout(() => {
router.replace({
path: "/login",
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
case 400:
messages("error", "数据异常");
break;
default:
messages("error", error.response.data.message);
}
return Promise.reject(error);
}
);
5. Вещи, связанные с запросом, были завершены, и теперь начнем инкапсулировать получение, отправку запроса.
/*
*get方法,对应get请求
*@param {String} url [请求的url地址]
*@param {Object} params [请求时候携带的参数]
*/
export function get(url, params) {
return new Promise((resolve, reject) => {
axios
.get(url, {
params
})
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
});
});
}
/*
*post方法,对应post请求
*@param {String} url [请求的url地址]
*@param {Object} params [请求时候携带的参数]
*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios
.post(url, params)
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
});
});
}
- api.js
После инкапсуляции бизнес-логики axios естественно начать, использовать и сначала представитьgetа такжеpostметод
import {get,post} from './request';
Далее начинаем инкапсулировать интерфейс и экспортировать его
//登陆
export const login=(login)=>post('/api/post/user/login',login)
//上传
export const upload=(upload)=>get('/api/get/upload',upload)
Итак, как мы называем интерфейс? Возьмите целевую страницу в качестве примера.
import { login } from "@/api/api.js"; //引入login
/**
* @oarma {Object} login 接口传递的参数
*/
login(login)
.then(res => {
//成功之后要做的事情
})
.catch(err => {
//出错时要做的事情
});
Логика, связанная с интерфейсом, была переработана.
Девять, введение vuex
Из-за сложности передачи данных между компонентами в проекте vue официальное введение глобального управления состоянием, то есть vuex, о котором сейчас нужно сказать, vuex может лучше управлять данными и облегчать связь между компонентами.
Теперь создайте четыре новых файла в папке магазина.state.js,mutations.js,getter.js,action.js.
- state.js
Состояние — это общедоступное состояние в Vuex.Я рассматриваю состояние как данные всех компонентов, которые используются для сохранения общедоступных данных всех компонентов.
const state = {
token: '',//权限验证
tagsList: [], //打开的标签页个数,
isCollapse: false, //侧边导航是否折叠
}
export default state //导出
- mutations.js
Под мутациями я понимаю методы в хранилище, а объект мутации содержит функцию обратного вызова для изменения данных, имя функции официально называется type, первый параметр — состояние, а второй параметр — полезная нагрузка, это пользовательский параметр. значение состояния должно пройти через мутации
const mutations = {
//保存token
COMMIT_TOKEN(state, object) {
state.token = object.token;
},
//保存标签
TAGES_LIST(state, arr) {
state.tagsList = arr;
},
IS_COLLAPSE(state, bool) {
state.isCollapse = bool;
}
}
export default mutations
- getter.js
Под свойством геттеров я понимаю вычисляемое свойство всех компонентов, то есть вычисляемое свойство. В официальной документации vuex также говорится, что геттеры можно понимать как вычисляемые свойства хранилища.Возвращаемое геттерами значение будет кэшироваться в соответствии с его зависимостями и будет пересчитываться только при изменении значений его зависимостей.
const getters={
//你要计算的属性
}
export default getters
- action.js
действия аналогичны мутациям, за исключением того, что:
1. действия отправляют мутации вместо прямого изменения состояния
2.Асинхронные операции можно включать в действия, а асинхронные операции категорически нельзя в мутации
3. Первым параметром функции обратного вызова в действиях является контекст, который представляет собой объект с теми же свойствами и методами, что и экземпляр хранилища.
const actions={
}
export default actions
- store.js
store.js — это файл интеграции модуля vuex.Поскольку обновление страницы приведет к потере данных vuex, здесь представлен подключаемый модуль сохранения данных vuex для сохранения данных в состоянии в локальном хранилище.
Установитьvuex-persistedstate
npm install vuex-persistedstate --save
import Vue from 'vue'
import Vuex from 'vuex'
import state from "./state";
import mutations from "./mutations";
import actions from "./actions";
import getters from "./getters";
//引入vuex 数据持久化插件
import createPersistedState from "vuex-persistedstate"
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
actions,
getters,
plugins: [createPersistedState()]
})
На этом знакомство с vuex завершено, если учащиеся все еще не понимают, они могут прочитать его.vuexдокументация.
10. Введение в макет домашней страницы
Теперь приступаем к оформлению страницы. Во-первых, давайте проанализируем ситуацию с главной страницей.
- Боковая панель
- верхняя полоса
- Раздел контента
Сначала мыviewСоздайте новый в папкеlayoutпапка, добавьте ещеlayout.vue,а такжеcompententsпапка.
- Боковая панель
Создайте новый в папке компонентовAside.vueфайл для реализации логики, связанной с переходами маршрутизации, используя режим маршрутизации меню навигации элемента, если вы не понимаете, вы можете перейти кМеню навигации ElementUIИди проверь.
<template>
<div class="aside">
<el-menu
:default-active="onRoutes"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
:collapse="isCollapse"
active-text-color="#bdb7ff"
router
>
<template v-for="item in items">
<template v-if="item.subs">
<el-submenu :index="item.index" :key="item.index">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs">
<el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
<template slot="title">{{ subItem.title }}</template>
<el-menu-item
v-for="(threeItem,i) in subItem.subs"
:key="i"
:index="threeItem.index"
>{{ threeItem.title }}</el-menu-item>
</el-submenu>
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.index" :key="item.index">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</div>
</template>
import { mapState } from "vuex";
export default {
data() {
return {
//配置目录
items: [
{
icon: "el-icon-edit-outline",
index: "home",
title: "系统首页"
},
{
icon: "el-icon-edit-outline",
index: "icon",
title: "自定义图标"
},
{
icon: "el-icon-edit-outline",
index: "component",
title: "组件",
subs: [
{
index: "editor",
title: "富文本编译器"
},
{
index: "countTo",
title: "数字滚动"
},
{
index: "trees",
title: "树形控件",
subs: [
{
index: "tree",
title: "自定义树"
},
{
index: "treeSelect",
title: "下拉树"
}
// ,{
// index:'treeTable',
// title:'表格树',
// }
]
},
]
},
{
icon: "el-icon-edit-outline",
index: "draggable",
title: "拖拽",
subs: [
{
index: "draglist",
title: "拖拽列表"
},
{
index: "dragtable",
title: "拖拽表格"
}
]
},
{
icon: "el-icon-edit-outline",
index: "charts",
title: "图表",
subs: [
{
index: "cricle",
title: "饼图"
},
]
},
{
icon: "el-icon-edit-outline",
index: "7",
title: "错误处理",
subs: [
{
index: "permission",
title: "权限测试"
},
{
index: "404",
title: "404页面"
}
]
},
]
};
},
computed: {
onRoutes() {
return this.$route.path.replace("/", "");
},
...mapState(["isCollapse"]) //从vuex里面获取菜单是否折叠
},
methods: {
//下拉展开
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
//下来关闭
handleClose(key, keyPath) {
console.log(key, keyPath);
}
}
};
- верхняя полоса
существуетview/compententsСоздайте новый в папкеHeader.vue
<template>
<div class="head-container clearfix">
<div class="header-left">
<showAside :toggle-click="toggleClick"/>
</div>
<div class="header-right">
<div class="header-user-con">
<!-- 全屏显示 -->
<div class="btn-fullscreen" @click="handleFullScreen">
<el-tooltip effect="dark" :content="fullscreen?`取消全屏`:`全屏`" placement="bottom">
<i class="el-icon-rank"></i>
</el-tooltip>
</div>
<!-- 消息中心 -->
<div class="btn-bell">
<el-tooltip effect="dark" :content="message?`有${message}条未读消息`:`消息中心`" placement="bottom">
<router-link to="/tabs">
<i class="el-icon-bell"></i>
</router-link>
</el-tooltip>
<span class="btn-bell-badge" v-if="message"></span>
</div>
<!-- 用户名下拉菜单 -->
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img
src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3266090804,66355162&fm=26&gp=0.jpg"
class="user-avatar"
>
{{username }}<i class="el-icon-caret-bottom"/>
</div>
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<router-link class="inlineBlock" to="/">
<el-dropdown-item>首页</el-dropdown-item>
</router-link>
<el-dropdown-item>个人设置</el-dropdown-item>
<el-dropdown-item divided>
<span style="display:block;" @click="logout">退出登陆</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</template>
import showAside from "@/components/showAside.vue";//引入了一个侧边栏是否折叠的组件
export default {
// name:'header',
components: {
showAside
},
data() {
return {
fullscreen: false,
name: "linxin",
message: 2,
username: "zyh"
};
},
computed: {
isCollapse: {
get: function() {
return this.$store.state.isCollapse;
},
set: function(newValue) {
console.log(newValue);
this.$store.commit("IS_COLLAPSE", newValue);//提交到vuex
}
}
},
methods: {
toggleClick() {
this.isCollapse = !this.isCollapse;
},
// 用户名下拉菜单选择事件
logout(command) {
this.$router.push("/login");
},
// 全屏事件
handleFullScreen() {
let element = document.documentElement;
if (this.fullscreen) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
// IE11
element.msRequestFullscreen();
}
}
this.fullscreen = !this.fullscreen;
}
}
};
сейчас наsrc/componentsСоздайте новый в папкеshowAside.vueкомпоненты
<template>
<div class="clearfix">
<div class="showAside pull-left" @click="toggleClick">
<i class="el-icon-menu"></i>
</div>
</div>
</template>
export default {
name: "showAside",
props: {
toggleClick: {
type: Function,
default: null
}
}
};
- Компонент метки верхней панели навигации
существуетview/compententsСоздайте новый в папкеTags.vue
<template>
<!-- 打开标签的容器 -->
<div class="tags">
<ul>
<li
class="tags-li"
v-for="(item,index) in tagsList"
:key="index"
:class="{'active': isActive(item.path)}"
>
<router-link :to="item.path" class="tags-li-title">{{item.title}}</router-link>
<span class="tags-li-icon" @click="closeTags(index)">
<i class="el-icon-close"></i>
</span>
</li>
</ul>
<div class="tags-close-box">
<el-dropdown @command="handleCommand">
<el-button size="mini" type="primary">
标签选项
<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu size="small" slot="dropdown">
<el-dropdown-item command="closeOther">关闭其他</el-dropdown-item>
<!-- <el-dropdown-item command="all">关闭所有</el-dropdown-item> -->
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
import { messages } from "@/assets/js/common.js";
export default {
created() {
//判断标签里面是否有值 有的话直接加载
if (this.tagsList.length == 0) {
this.setTags(this.$route);
}
},
computed: {
//computed 方法里面没有set方法因此不能使用mapState,需要重新定义set方法
tagsList: {
get: function() {
return this.$store.state.tagsList;
},
set: function(newValue) {
this.$store.commit("TAGES_LIST", newValue);
// this.$store.state.tagsList = newValue;
}
}
},
watch: {
//监听路由变化
$route(newValue, oldValue) {
this.setTags(newValue);
}
},
methods: {
//选中的高亮
isActive(path) {
return path === this.$route.fullPath;
},
handleCommand(command) {
if (command == "closeOther") {
// 关闭其他标签
const curItem = this.tagsList.filter(item => {
return item.path === this.$route.fullPath;
});
this.tagsList = curItem;
}
},
//添加标签
setTags(route) {
let isIn = this.tagsList.some(item => {
//判断标签是否存在
return item.path === route.fullPath;
});
//不存在
if (!isIn) {
// 判断当前的标签个数
if (this.tagsList.length >= 10) {
messages("warning", "当标签大于10个,请关闭后再打开");
} else {
this.tagsList.push({
title: route.meta.title,
path: route.fullPath,
name: route.name
});
//存到vuex
this.$store.commit("TAGES_LIST", this.tagsList);
}
}
},
closeTags(index) {
console.log(this.tagsList.length);
if (this.tagsList.length == 1) {
messages("warning", "不可全都关闭");
} else {
//删除当前
let tags = this.tagsList.splice(index, 1);
this.$store.commit("TAGES_LIST", this.tagsList);
}
}
}
};
следующий вview/compententsСоздайте новый в папкеMain.vue, в основном для объединения верхней панели вкладок навигации и раздела содержимого.
<template>
<div class="container">
<tags />
<div class="contents">
<transition name="fade-transform" mode="out-in">
<router-view></router-view>
</transition>
</div>
</div>
</template>
import Tags from './Tags.vue'
export default {
components:{
Tags
}
}
Связанные компоненты записываются и обобщаются в компоненте макета.
<template>
<div class="wrapper">
<Aside class="aside-container"/>
<div class="main-container" :class="isCollapse==true?'container_collapse':''">
<Header/>
<Main/>
</div>
</div>
</template>
import Aside from "./components/Aside.vue";
import Header from "./components/Header.vue";
import Main from "./components/Main.vue";
import { mapState } from "vuex";
export default {
name: "Layout",
components: {
Aside,
Header,
Main
},
computed: {
...mapState(["isCollapse"])
}
};
Пока спланирован макет главной страницы, если не уверены, можете проверить.адрес проекта
11. Заключение
Существуют различные системы управления, и у каждой компании своя бизнес-логика.Эта статья является лишь руководством.Есть еще много областей, которые необходимо пересмотреть и улучшить.Если у студентов есть идеи получше, они могут выступить вперед и надеяться, что все смогут улучшить эту книгу вместе проект.
|-- vue-admin-project
|-- .env
|-- .env.prod
|-- .env.test
|-- .gitignore
|-- babel.config.js
|-- package-lock.json
|-- package.json
|-- README.md
|-- vue.config.js
|-- public
| |-- favicon.ico
| |-- index.html
|-- src
|-- App.vue
|-- element-variables.scss
|-- main.js
|-- api
| |-- api.js
| |-- request.js
|-- assets
| |-- logo.png
| |-- css
| | |-- normalize.css
| | |-- public.css
| |-- icon
| | |-- demo.css
| | |-- demo_index.html
| | |-- iconfont.css
| | |-- iconfont.eot
| | |-- iconfont.js
| | |-- iconfont.svg
| | |-- iconfont.ttf
| | |-- iconfont.woff
| | |-- iconfont.woff2
| |-- img
| | |-- tou.jpg
| |-- js
| | |-- common.js
| |-- scss
| |-- global.scss
|-- components
| |-- showAside.vue
|-- plugins
| |-- element.js
|-- router
| |-- router.js
|-- store
| |-- actions.js
| |-- getters.js
| |-- mutations.js
| |-- state.js
| |-- store.js
|-- views
|-- layout
| |-- Layout.vue
| |-- components
| |-- Aside.vue
| |-- Header.vue
| |-- Main.vue
| |-- Tags.vue
Окончательная файловая структура каталога проекта
Ссылки на связанные статьи
Разрешение на создание каркаса фона элемента от 0 до 1
[Оптимизация упаковки] Построить рамку оптимизации фонового фреймворка элемента от 0 до 1