├── .editorconfig ├── .env ├── .env.development ├── .env.production ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── init.sh ├── package.json ├── public ├── favicon.ico └── index.html ├── push.sh ├── src ├── App.vue ├── api │ └── common.js ├── assets │ ├── iconfont │ │ ├── README.md │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ ├── img │ │ └── common │ │ │ ├── cross_a.png │ │ │ ├── cross_h.png │ │ │ ├── cross_n.png │ │ │ └── icon_1.png │ └── logo.png ├── common │ ├── README.md │ ├── request.js │ ├── sniff.js │ └── util.js ├── components │ ├── CountDown.js │ ├── CountDown.vue │ ├── Dialog.vue │ ├── HelloWorld.vue │ └── toast │ │ ├── Toast.vue │ │ └── index.js ├── config │ └── env.js ├── filters │ └── index.js ├── layouts │ └── index.vue ├── locale │ ├── cn │ │ ├── home.js │ │ └── index.js │ ├── en │ │ ├── home.js │ │ └── index.js │ ├── index.js │ └── messages.js ├── main.js ├── router │ └── index.js ├── store │ ├── actions.js │ ├── home │ │ ├── index.js │ │ └── user.js │ ├── index.js │ ├── mutation-types.js │ └── mutations.js ├── style │ ├── _var.scss │ ├── common.scss │ ├── mixin.scss │ ├── normalize.scss │ └── reset.scss └── views │ ├── about.vue │ ├── home.vue │ └── template.vue ├── vue.config.js └── 使用说明.md /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 4 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # 在所有的环境中都被载入的环境变量 2 | 3 | #接口地址 4 | #VUE_APP_API = 'http://api.zhuishushenqi.com' -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # 只在开发环境存在的环境变量 2 | 3 | # 接口地址 4 | VUE_APP_API = 'http://api.zhuishushenqi.com' -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | # 只在生产环境存在的环境变量 2 | 3 | # 接口地址 4 | VUE_APP_API = 'http://api.zhuishushenqi.com' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /devdist 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw* 23 | 24 | yarn.lock 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 东半球少女的梦 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

vue-vuex-router

2 |

vue-vuex-router

3 |

基于Vue CLI 3构建的项目初始化文件,master、mobile两个分支,pc端、mobile端开箱即用。

4 | 5 | ## 文档内容 6 | 7 | - [注意](#注意) 8 | - [安装和使用](#安装和使用) 9 | - [项目结构](#项目结构) 10 | - [推荐规范](#推荐规范) 11 | - [常见问题](#常见问题) 12 | - [更多自定义配置](#更多自定义配置) 13 | - [进阶vue3](#进阶vue3) 14 | - [License](#License) 15 | 16 | ## 注意 17 | 18 | 注意!这是一份Vue的最佳实践,包括了实践展示,但是并不包括新手入门,如果你是Vue新手,可以按如下路径学习Vue: 19 | 20 | ``` 21 | 1、用Vue+Vue-Router做一个展示网站。网站按页面划分模块,每个页面按section(部分)再划分模块。培养自己的模块化思想。 22 | 2、用Vue+Vue-Router+Axios做一个带请求的网站。把请求结果放在页面上展示出来。锻炼请求接口的能力,了解前后端分离思想。 23 | 3、用Vue+Vue-Router+Axios+Vuex做一个能管理数据的网站。把请求放到Vuex中,用store管理数据。搞懂Vuex在开发中的帮助,提升项目开发能力。 24 | 25 | 做完上面三步你就已经入门Vue了,接下来就可以用这个最佳实践来构建更优雅的代码、组织更简洁的项目。 26 | ``` 27 | 28 | ## 安装和使用 29 | 30 | ``` 31 | 初始化项目 32 | ./init.sh 33 | 34 | 安装插件 35 | yarn install 36 | 37 | 项目启动 38 | yarn serve 39 | 40 | 项目打包 41 | yarn build 42 | 43 | 分析打包体积 44 | yarn analyz 45 | 46 | 提交代码 47 | yarn push 48 | ``` 49 | 50 | ## 项目结构 51 | 52 | ``` 53 | - src 54 | - api // 接口管理目录 55 | - assets // 图片资源目录 56 | - common // 公共资源目录(函数库、请求封装) 57 | - components // 组件目录 58 | - config // 配置文件目录 59 | - env.js // 环境配置 60 | - fliters // 公共过滤器 61 | - layouts // 外层布局 62 | - locale // i18n语言目录 63 | - router // 路由 64 | - store // Vuex管理目录 65 | - style // 公共样式目录 66 | - views // 页面目录 67 | ``` 68 | 69 | ## 推荐规范 70 | 71 | 1、命名 72 | 73 | 组件命名: 74 | 75 | ``` 76 | 文件与组件命名保持一致,使用 PascalCase,即驼峰命名法,如:CountDown.vue 为一个倒计时组件。 77 | 78 | 参考链接: 79 | https://cn.vuejs.org/v2/guide/components-registration.html#%E7%BB%84%E4%BB%B6%E5%90%8D%E5%A4%A7%E5%B0%8F%E5%86%99 80 | ``` 81 | 82 | 页面命名: 83 | 84 | ``` 85 | Vue中什么都是组件,包括页面,但是我们为了与UI、业务组件作出区分,凡是页面组件的命名均以"小驼峰法"命名,如:home.vue。 86 | ``` 87 | 88 | 变量命名: 89 | ``` 90 | 常量——全大写+下划线,如: 91 | 92 | let IMAGE_SERVER = 'http://img.alibaba.com'; 93 | let MAX_LENGTH = 200; 94 | 95 | 变量——小驼峰式命名法,如: 96 | let maxCount = 10; 97 | let tableTitle = 'LoginTable'; 98 | 99 | 全局变量——g+变量名,如: 100 | var gConfig = { 101 | a:1, 102 | b:2 103 | }; 104 | 105 | 私有变量——下划线+变量名,如: 106 | let _name = '小明'; 107 | ``` 108 | 2、样式 109 | 110 | 样式统一在 style 文件夹里维护 111 | 112 | |- common.scss 里面放公共的、全局的、使用频率比较高的样式,这样可以方便组织样式。如:.hide{display: none;} 113 | |- mixin.scss 里面放全局的样式方法,已经在webpack中全局引入,使用的时候 @include ct(); 114 | |- reset.scss 里面放页面样式重置的css,不需要修改 115 | |- var.scss 里面放公共变量,方便全局样式,如:颜色、字体大小等 116 | 117 | 3、vuex 118 | 119 | store 按页面或者业务划分,然后统一由 store/index.js 输出 120 | 121 | 所有的mutations方法,需要现在最外层的 mutation-type.js 说明后,然后在单个 mutations.js 中引入使用 122 | 123 | 4、请求 124 | 125 | 请求统一在 api 文件夹下管理,可以按照页面或者业务划分。所有的请求放在vuex的action中,不得放在页面内,数据统一存储在state中,取数据用getter,修改用mutations,保持数据的单向性。 126 | 127 | ``` 128 | 如何Vuex的作用及处理数据的方式? 129 | 130 | 在前端可以把Vuex看做后端mvc中的m层,即数据处理层,它与控制器分开,只有它与数据库接触,控制器只是用它调用或是获取数据,并不能直接修改数据库数据,也是需要m层来修改数据库。 131 | 132 | 而在Vuex(store)中,action就负责取数据(请求接口),getter负责处理数据返回相应格式,mutation负责改变数据(即改变数据库),而state就是那个数据库。 133 | 134 | 即Vuex就是单纯做数据处理的,它应该与页面分开,保持数据的独立和单向性。 135 | ``` 136 | 137 | 5、格式化方法 138 | 139 | 数据的格式化,如时间戳、隐藏手机号、格式化银行卡等操作,不建议在vue页面中用方法修改数据,建议在 fliters 中说明过滤器,然后在模版中 {{data | fliter}} 格式化数据,可以使数据更干净。 140 | 141 | 6、语言 142 | 143 | 建议一直使用i18n作为语言的处理工具,方便国际化和统一管理,它在 config/lang 中(建议按页面区分)。 144 | 145 | 它的使用方法是,在.vue文件中 {{$t('name')}} 146 | 147 | 在js中,获取当前语言的方法是,console.log(this.$i18n.locale),设置语言的方法同样 this.$18n.local = 'zh-CN' 148 | 149 | 7、vue-router 150 | 151 | 统一采用按需加载,如:const Home = () => import( /* webpackChunkName: "home" */ '../views/home.vue'),其中的 webpackChunkName 指的是打包出来的包名。 152 | 153 | 8、布局 154 | 155 | 布局在 layouts 文件夹中,然后在 App.vue 中引入,放在了路由的最外层,充当整个项目的公共布局,如:页眉、页脚等。 156 | 157 | 9、参考 158 | 159 | [凹凸实验室前端代码规范](https://guide.aotu.io/docs/) 160 | [风格指南](https://cn.vuejs.org/v2/style-guide/) 161 | 162 | ## 常见问题 163 | 164 | 1、yarn push 不能用怎么办? 165 | 166 | ``` 167 | 命令行工具切到项目目录下,执行 chmod 755 push.sh 168 | ``` 169 | 170 | 2、如何用手机调试,或者让别人看到? 171 | 172 | ``` 173 | 项目启动的时候已经是你的本地ip了,只需要将手机和电脑连在同一个网络环境下(如:连同一个WIFI),复制地址栏的地址发送给手机即可访问。 174 | 175 | 之后,你改动任何一个地方,就能方便的在手机上看到改动了。也可以将这个地址发给同一网络环境的其他人,他们也就可以看到效果了。 176 | ``` 177 | 178 | 3、我要开发移动端H5怎么做? 179 | 180 | ``` 181 | 1、切换到mobile_template分支,这是为移动端开发专门准备的模版,执行命令:git checkout mobile_template。 182 | 2、查看设计稿的宽度,如750px、375px。 183 | 3、将设计稿宽度/10,然后修改 package.json 中的 postcss-px2rem 下的 remUnit 184 | 4、样式、css等就可以按照设计稿的大小用px来写了 185 | 186 | 例子: 187 | "postcss": { 188 | "plugins": { 189 | "autoprefixer": {}, 190 | "postcss-px2rem": { 191 | "remUnit": 37.5 // 修改这个值为"设计稿宽度/10" 192 | } 193 | } 194 | }, 195 | ``` 196 | 197 | 4、我想把格式化后4个空格改成2个怎么改? 198 | 199 | ``` 200 | .editorconfig 中 indent_size = 2 即可 201 | ``` 202 | 203 | 5、我怎么在组件中引入图片? 204 | 205 | ``` 206 | 图片目录在src/assets下,在组件中引入方式如下: 207 | 208 | 209 | Tips:建议动态引入,避免调整页面带来的路径问题 210 | ``` 211 | 212 | 6、我怎么无视层级导入css,或是引入图片? 213 | 214 | ``` 215 | 使用 ~ 216 | 217 | @import "~@/scss/_var.css"; 218 | @import "~@/assets/iconfont/iconfont.css"; 219 | background: url("~@/assets/img/xxx.png"); 220 | 221 | 原理: 222 | CSS loader 会把把非根路径的url解释为相对路径,加~前缀才会解释成模块路径。 223 | 224 | 参考文档: 225 | https://cli.vuejs.org/zh/guide/css.html#%E5%BC%95%E7%94%A8%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90 226 | https://cli.vuejs.org/zh/guide/html-and-static-assets.html#url-%E8%BD%AC%E6%8D%A2%E8%A7%84%E5%88%99 227 | ``` 228 | 229 | 7、我想修改Toast的样式怎么办? 230 | 231 | ``` 232 | src/components/toast/toast.vue 233 | 修改此文件即可,更多修改可以查找 "vue插件" 资料。 234 | ``` 235 | 236 | 8、我想在本地和服务端调试怎么弄? 237 | 238 | ``` 239 | 修改 vue.config.js 中的 proxy 为你的服务端地址即可,如: 240 | 241 | proxy: 'http://xxx.com' 242 | ``` 243 | 244 | 9、我引入了第三方组件,如何修改样式? 245 | 246 | ``` 247 | 有两个方法可以解决这个问题: 248 | 249 | 方法一: 250 | 在scoped的scss中使用 >>> 或者 /deep/ ,它们是vue提供的"深度作用选择器",你可以参考 —— https://vue-loader.vuejs.org/zh/guide/scoped-css.html#%E6%B7%B1%E5%BA%A6%E4%BD%9C%E7%94%A8%E9%80%89%E6%8B%A9%E5%99%A8 251 | 255 | 256 | 方法二: 257 | 单独写一个style,不加scoped,在这里面单独修改 258 | 261 | ``` 262 | 263 | 10、UI说我移动端的border太粗了,和他UI严重不符,怎么解决? 264 | 265 | ``` 266 | 移动端屏幕像素比(dpr)导致的,如果你开发移动端,我为你准备了现成的1px border,不要使用border: 1px solid #ff6632,而是用: 267 | 268 | @include border-bottom(); 269 | @include border-top(); 270 | @include border-left(); 271 | @include border-right(); 272 | @include border(); 273 | 274 | 同时你也可以传入一些配置项来设置border的颜色、粗细等等,详细的请切换到 mobile_template 分支,查看 src/style/mixin.scss 里面的 border 类。 275 | ``` 276 | 277 | 11、在数学运算时,出现了1.1999999999这种无限小数位,我该怎么解决啊? 278 | 279 | ``` 280 | 浮点数运算失精,可以用 number-precision 这个插件,具体使用方法为: 281 | 282 | yarn add number-precision 283 | 284 | import NP from 'number-precision' 285 | 286 | NP.plus(0.1, 0.2) 287 | 288 | ...... 289 | 290 | 更多使用方法参考官方文档:https://github.com/nefe/number-precision 291 | ``` 292 | 293 | 12、前端好多日期展示,每次在methods里面处理好麻烦,我又不想修改原数据,有更方便的办法吗? 294 | 295 | ``` 296 | 有!你完全不需要每次写方法处理,只需要在需要