基本功能
基本功能
初始目录结构
通过 lavas init
初始化项目完成之后,我们应该能够看到如下的文件结构:
12345678910111213lavas-project
├── assets/
├── components/
├── core/
├── middlewares/
├── node_modules/
├── pages/
├── static/
├── store/
├── lavas.config.js
├── server.dev.js, server.prod.js
├── .babelrc, .editorconfig, .fecsignore, .fecsrc, .gitignore
└── LINCENSE, package.json, README.md
assets, static
把这两个目录放在一起,是因为这两个目录都是存放外部静态资源的,例如 iconfont(用字体实现矢量小图标的库), icons(用于添加到手机桌面时使用的各种尺寸的图标), manifest.json(同样用于添加到桌面时使用)等。
这些静态资源在构建时会一并被放入生成目录中(/dist
),但两者也有差别:
/assets
里的内容会被 webpack 构建到生成目录的文件中,不再会单独以文件形式存在。因此 iconfont 放置在/assets
中
components
/components
存放 Vue 的组件,供其他页面复用。在 Lavas 中,初始状态下提供了三个组件,均在一些页面框架中使用,因此会作用于整个项目的所有页面。
UpdateToast.vue
也在/core/App.vue
中被引用,用于 Service Worker 更新时提示用户
如果开发者有其他多个页面需要复用的组件,也可以放在 /components
目录中。
core
/core
目录中存放一些散落但必须的文件,作用也相对复杂,包括 webpack entry, 全局样式框架,Vue app 启动器等等。详细可以参考 core 目录文档 进行详细查看。
middlewares
之前在 /core/middlewares.js
中有提过,用户可以在这个目录编写自定义中间件,用来获取或者修改每次到达服务器的网络请求。关于中间件的具体写法及其包含的能力可以参考文档的中间件部分。
pages
/pages/ 目录存放每个页面的 vue 组件。我们在开发实际站点的时候,可能大部分的工作都在这个目录中进行。每个页面组件都是一个标准的 Vue 组件,包含 <template>, <script> 和 <style> 三部分,开发方式也和 Vue 一模一样,这里就不再多做介绍了。
值得注意的是,/pages/
目录中的所有页面都会自动生成
一条路由规则,无需用户再行配置。举例来说,在初始项目中我们看到一个 /pages/Appshell.vue
,则 Lavas 自动生成
的路由将会是 /appshell
。更多生成规则可以参考本文下半部分的“ Lavas 自动路由生成方法” 部分。
当然如果开发者对自动生成的路由并不满意,或者有其他特殊需求需要自定义路由规则的,也可以通过 router
配置项进行修改,这部分将在文档的路由部分进行说明。
store
之前在 /core/store.js
中有提及,所有位于 /store
目录的 js 文件都会以 Vuex 模块 (module) 进行加载。因此开发者只需要提供一个完整的 Vuex 模块就可以在 vue 中使用它。一般来说,一个完整的 Vuex 模块需要包含以下内容:
1234567891011121314// someStore.js with path: /store/namespace/someStore.js
// state MUST be a function to support SSR
export const state = () => {
// define states
};
export const mutations = {
// define functions to change states
};
export const actions = {
// send async requests and commit changes
};
这样就可以在 /pages/
目录中的 vue 中使用它了,例如
123456// ...
computed: mapState('namespace/someStore', [
'state1',
'state2'
])
// ...
更多 store 相关的写法可以参见文档的 store 部分。
lavas.config.js
Lavas 提供了许多配置项,方便开发者进行各种自定义的灵活配置。所有的配置项都集中在 lavas.config.js
中,并提供一套默认配置,适用于大部分普通开发者快速上手。配置总共分为以下几个部分,您都可以在文档的进阶部分找到对应的章节进行详述:
build
构建相关
其他文件
除了上述目录,还有其他一些散落的文件。但因为修改的可能性较小,因此放在这里统一简述一下:
- server.dev.js, server.prod.js
这两个文件作用于用户输入命令
lavas dev
和lavas start
时配合 Lavas 使用的,用户一般不需要修改。Lavas 集成的命令简介将在 Lavas 命令中介绍。
.lavas
细心的开发者可能注意到了,一旦 Lavas 项目运行过一次,根目录下还会增加一个 /.lavas
目录。这个目录是 Lavas 在运行之前事先生成的,如之前提到过的自动生成的路由规则,以及处理热加载 (hotreload) 等都放置在这里,开发者不应该
修改这个目录的内容,并且将目录留在 /.gitignore
中,防止协作开发时互相影响。
Lavas 自动路由生成方法
Lavas 2.0 的一大功能点是能够根据 /pages/
目录的 vue 文件和层级自动生成路由规则,帮助开发者快速搭建站点,避免繁琐且重复的路由规则配置。因此这里我们来了解一下 Lavas 是如何自动生成路由规则的。
普通情况
绝大部分情况下,Lavas 会直接根据 /pages/
中的 vue 文件层级生成对应的路由规则。此外因为 vue 建议的命名规范,一般 vue 文件都会命名为首字母大写的形式(如 /pages/Appshell.vue
),而路由规则一般均采用小写,所以这里 Lavas 会将 vue 文件名的首字母改为小写
处理,但不会
处理中间目录的大小写。
举例来说
12/pages/Appshell.vue => /appshell
/pages/Error.vue => /error
Index.vue 的特殊处理
存在有一类特殊情况:当 vue 文件命名为 Index.vue 时,开发者可能是想让它担任首页(至少是某个模块内的首页)的角色。因此这种情况下 Lavas 会进行特殊处理,去掉这里的 index
。
举例来说
1/pages/Index.vue => /
注意:
如 /pages/Index.vue
时依然采用 /index
是无法
访问到目标页面的!
动态参数
有些页面需要一个动态参数来进行访问。例如某博客站点需要展现某篇博客的内容详情,它的路由规则就很可能是 /detail/[id]
, 其中 [id]
可能是数字,用来标识博客文章的 ID。这种情况我们需要用到 Lavas 动态参数功能。
我们可以在 /pages/detail/
目录中建立一个 vue 文件并命名为 _id.vue
(下划线开头表示动态参数)。在这个 vue 文件中,我们可以通过 this.$route.params.id
( script 中 )或者 {{$route.params.id}}
( template 中 ) 获取这个参数。
嵌套路由
Lavas 同样支持 vue-router 的嵌套路由。开发者需要在 /pages
目录中新建两个同名的目录和 Vue 文件(但首字母大小写不同,目录小写,文件大写)即可实现。
Vue 文件作为父路由的框架页面,包含 <router-view> 节点;目录内的其他 Vue 文件作为每个子路由的页面,填充在父路由的 <router-view> 节点内。
举例来说,我们有一套商品详情页面拥有相同的头部,通过嵌套路由来实现是,目录结构大约是:(尤其注意 detail 的大小写)
1234567lavas-project
└── pages/
├── Detail.vue
└── detail/
├── Product.vue
├── Service.vue
└── Mixed.vue
Detail.vue 中需要包含 <router-view> 节点,如下:
1234<template>
<header>xxx</header>
<router-view></router-view>
</template>
detail/
目录内部的 Vue 文件和普通的没有太大差别,正常开发即可。
在这种情况下,生成的路由会是 /detail/product
, /detail/service
等等,用 vue-router 的 router.js
来描述的话,大概是:
123456789101112131415161718let routes = [{
path: '/detail',
name: 'detail',
component: xxx,
children: [{
path: 'product',
name: 'detailProduct',
component: xxx
},{
path: 'service',
name: 'detailService',
component: xxx
},{
path: 'mixed',
name: 'detailMixed',
component: xxx
}]
}]