目录说明

2021-11-23 大约 7 分钟

# 目录说明

基于 yicode 的项目,目录结构都有其特定含义,请同学们仔细阅读以下说明,以便更加熟练地使用 yicode 开发项目。

# assets 内部资源目录

所谓的内部资源,就是项目会被项目依赖,并进行统一打包和构建的非代码类资源。

如:图片,音频,视频,字体等。

结构如下:

├─audio
├─fonts
├─images
│  ├─article
│  ├─bagua
│  ├─book
│  ├─code
│  ├─film
│  ├─friends
│  ├─game
│  ├─navigation
│  ├─novel
│  ├─softs
│  └─tool
└─videos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# static 外部资源目录

所谓的外部资源目录,就是不会被项目依赖,不会进行统一打包构件,以传统的<script><link>等标签直接在 html 文件模板里面引入的资源。

如:网站收藏图标,jquery 相关库和插件,第三方没有 npm 包的文件等。

├─css
│  ├─jquery.min.js
│  ├─swiper.min.js
├─fonts
└─images
│  ├─favicon.png
└───
1
2
3
4
5
6
7

# tpls 模板目录

单页应用 html 文件模板目录,所有的外部资源引导请对此目录下的文件进行修改。

├─tpls
│  ├─index.html
└───
1
2
3

index.html 文件代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>陈随易</title>
        <link rel="icon" type="image/png" href="./static/images/favicon.png" sizes="32x32" />
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no" />
    </head>
    <body>
        <div id="app"></div>
        <script src="./static/fonts/iconfont.js"></script>
    </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13

# layout 项目骨架目录

大部分项目,都有一些页面公共元素,比如官网项目,有顶部导航,底部信息。

后台管理项目,除了顶部栏,还有左侧的菜单面板等。

为此,理应把这些页面共用的区域,提取出来,做成所有页面的骨架,便叫做 layout

layout 层的结构如下:

├─layout
│  ├─default # 默认风格骨架
│      ├─header.vue
│      ├─footer.vue
│      ├─menu.vue
│      ├─index.vue
│  ├─redStyle # 红色风格骨架
│      ├─header.vue
│      ├─footer.vue
│      ├─menu.vue
│      ├─index.vue
└───
1
2
3
4
5
6
7
8
9
10
11
12

使用方式,则是在 pages 目录下的页面路由文件 route.js 中,进行 vue-router 路由配置,将骨架导入。

export default {
    path: "/",
    /**
     * layout 框架层
     * 此处采用默认的 default 框架
     * 如果默认框架不符合你的需求,请不要删除此框架层的导入
     * 直接修改 layout/default 目录下的默认框架层代码即可
     * 如果是类似官网项目,不需要框架层,也请不要将此框架层移除
     * 当做有一个全屏的框架层即可,提高需求变更的灵活性
     * 也给自己留一条退路(其实主要是框架作者的强迫症)
     * 如有问题或建议,请联系作者:chensuiyi.com
     */
    component: () => import("@src/layout/default/index.vue"), // 导入默认骨架
    children: [
        {
            path: "/",
            component: () => import("@src/pages/index/index.vue"),
        },
    ],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

如果想更换项目骨架结构,将每个页面目录下的route.js文件中的骨架导入名称修改即可。

# pages 页面目录

yicode 采取的是【约定大于配置】的原则,pages 便是这个原则指导下,一个非常重要的目录。

├─pages
│  ├─index
│      ├─index.vue
│      ├─route.js
│  ├─news
│      ├─index.vue
│      ├─route.js
1
2
3
4
5
6
7

如上所示,pages 目录下,一个目录就表示一个【页面】,一个页面默认表示一个独立的【一级路由】。

使用 yicode new --page 页面名称,可以自动在 pages 目录下,生成对应的页面目录和文件

生成页面元素的细节,请看后面的【页面分配】教程详解。

# comps 全局组件目录

全局组件,顾名思义,就是创建后,到处都可以使用。比如 回到顶部天猫右侧固定导航等。

├─comps
│  ├─test1 # 全局组件 test1
│      ├─index.vue
│  ├─test2 # 全局组件 test2
│      ├─index.vue
│  ├─index.js # 全局组件统自动导入文件
1
2
3
4
5
6

与其他框架不同的是,yicode 不仅提供一键创建全局组件命令yicode new --comp 组件名称

还提供了创建后,无需手动挂载,自动挂载组件到Vue实例的功能,提高开发效率和体验。

如上创建的test1组件,直接按如下方式书写即可。

<CompTest1></CompTest1>
1

注意:组件使用时,应在组件名前,加上Comp前缀,表示全局组件!

# env 环境变量

环境变量,专门用于应对开发环境和发布环境,不同参数的切换。

其下只有两个文件,development.env 文件和 production.env 文件。

参考如下方式设置即可。

# 协议类型
protocol="http://"
# 本地存储命名空间
namespace="yicode"
1
2
3
4

# mixin 全局混入

全局混入,主要用于设置大部分页面通用的 data created methods 等。

├─mixin
│  ├─index.js # 全局混入入口文件
1
2

内容如下:

/**
 * 全局混入
 * 此文件尽量只添加新东西,不要删除以下配置好的东西
 * 一切皆有道理
 * 如果明白了解,请自行发挥
 * 全局混入,是为了解决 vue 组件参数复用问题
 * 不要什么都放进来,请把大部分组件共用的东西放进来
 * 如有问题或建议,请联系作者:chensuiyi.com
 */
import Vue from "vue";
import Vuex from "vuex";

Vue.mixin({
    computed: {
        ...Vuex.mapState([]),
    },
    methods: {
        ...Vuex.mapMutations(["save"]),
    },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# plugins 插件目录

插件目录,用于分门别类地管理第三方引入,默认只设置了 basil.js 这一个浏览器本地存储操作库。

├─plugins
│  ├─index.js
│  ├─basil.js
1
2
3

# router 路由目录

路由,是 vue 单页应用的灵魂之一,为了简便路由的管理,yicode 路由目录下,只有一个 index.js 文件。

其内容如下:

/**
 * 此文件为路由核心入口文件
 * 一般情况下,不需要动此文件
 * 此文件将会自动加载当前项目 pages 目录下的所有路由
 * 如有问题或建议,请联系作者:chensuiyi.com
 */
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);

let routeList = [];
let importAll = require.context("@src/pages", true, /route\.js$/);
importAll.keys().map((path) => {
    let router = importAll(path).default || importAll(path);
    routeList.push(router);
});

// 导入自动生成的路由文件
let router = new VueRouter({
    routes: routeList,
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

index.js文件,担任起了统一导入项目路由的功能,无需开发者手动设置。

# request 异步请求目录

目前,单页应用 + 前后分离,是 web 前端市场开发主流,异步请求更是前后端交互的核心一环。

综合实践经验,yicode 抛弃传统的单接口服务器方式,默认采用了多接口服务器配置。

├─request
│  ├─index.js
│  ├─api1.js # 请求登录服务器
│  ├─api2.js # 请求数据服务器
│  ├─api3.js # 请求日志服务器
1
2
3
4
5

也就是说,我们可以登录请求的是 A 服务器,数据请求指向 B 服务器,灵活管理多变的请求环境。

# vuex 全局数据管理目录

vuex 官方推荐大型项目使用,但是,我认为,不管小型,中型还是大型项目,都推荐使用。

好的东西,不管什么样的项目,都应该积极使用。

为了提高开发效率,yicode 全局存储默认提供了 save 设置数据的通用方法。

具体用法请看如下代码,或查看 【进阶指南】阶段的 vuex操作 说明。

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);
const store = new Vuex.Store({
    state: {},
    mutations: {
        /**
         * 通用全局存储方法
         * --------------------------------
         * 普通项目修改 vuex 状态方式:
         * 调用处:
         * this.$store.emit('SAVE_NAME',{name:chensuiyi})
         * 定义处:
         * SAVE_NAME(state,params){
         *     state.userinfo.name = params.name
         * }
         * --------------------------------
         * yicode 项目修改 vuex 状态方法
         * 调用处:
         * this.YiMutation('userinfo.name','chensuiyi')
         * 定义处:
         * 无需定义,级联赋值!!!
         */
        YiMutation: (state, params) => {
            // 判断路径
            if (!params.path) return;
            // 判断数据
            if (!params.data) return;
            // 分割路径
            let keyPath = params.path.split(".");
            // 路径长度
            let keyLength = keyPath.length;
            // 状态别名
            let keySave = state;
            // 默认通过
            let isPass = true;
            // 循环赋值
            for (let i = 0; i < keyLength - 1; i++) {
                keySave = keySave[keyPath[i]];
                if (!keySave) {
                    isPass = false;
                    break;
                }
            }

            // 提前返回
            if (!isPass) return;
            let keyLast = keyPath[keyLength - 1];
            // 判断动作
            if (params.action) {
                if (params.action === "-") keySave[keyLast] = keySave[keyLast] - params.data;
                if (params.action === "+") keySave[keyLast] = keySave[keyLast] + params.data;
                if (params.action === "*") keySave[keyLast] = keySave[keyLast] * params.data;
                if (params.action === "/") keySave[keyLast] = keySave[keyLast] / params.data;
                return;
            } else {
                keySave[keyLast] = params.data;
            }
        },
    },
});

export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
上次编辑于: 2021年11月23日 13:44
贡献者: chensuiyi