├── README-CN.md ├── README-FA.md ├── README-JP.md ├── README-KR.md ├── README-PTBR.md ├── README-RU.md ├── README.md ├── docs ├── .nojekyll └── index.html └── img └── logo.png /README-CN.md: -------------------------------------------------------------------------------- 1 | # Vue.js 组件编码规范 2 | 3 | > 这个 [链接](https://github.com/sqrthree/vuejs-component-style-guide/compare/master...pablohpsilva:master) 用来查看本翻译与英文版是否有差别(如果你没有看到 README.md 发生变化,那就意味着这份翻译文档是最新的)。 4 | 5 |

6 | 7 |

8 | 9 | ### 其它语言 10 | 11 | * [英文](https://pablohpsilva.github.io/vuejs-component-style-guide/#/) 12 | * [葡萄牙语](https://pablohpsilva.github.io/vuejs-component-style-guide/#/portuguese) 13 | * [日本](https://pablohpsilva.github.io/vuejs-component-style-guide/#/japanese) 14 | * [韩语](https://pablohpsilva.github.io/vuejs-component-style-guide/#/korean) 15 | * [俄语](https://pablohpsilva.github.io/vuejs-component-style-guide/#/russian) 16 | 17 | ## 目标 18 | 19 | 本规范提供了一种统一的编码规范来编写 [Vue.js](http://vuejs.org/) 代码。这使得代码具有如下的特性: 20 | 21 | * 其它开发者或是团队成员更容易阅读和理解。 22 | * IDEs 更容易理解代码,从而提供高亮、格式化等辅助功能 23 | * 更容易使用现有的工具 24 | * 更容易实现缓存以及代码包的分拆 25 | 26 | 本指南为 [De Voorhoede](https://github.com/voorhoede) 参考 [RiotJS 编码规范](https://github.com/voorhoede/riotjs-style-guide) 而写。 27 | 28 | ## 目录 29 | 30 | * [基于模块开发](#基于模块开发) 31 | * [vue 组件命名](#vue-组件命名) 32 | * [组件表达式简单化](#组件表达式简单化) 33 | * [组件 props 原子化](#组件-props-原子化) 34 | * [验证组件的 props](#验证组件的-props) 35 | * [将 `this` 赋值给 `component` 变量](#将-this-赋值给-component-变量) 36 | * [组件结构化](#组件结构化) 37 | * [组件事件命名](#组件事件命名) 38 | * [避免 `this.$parent`](#避免-this.$parent) 39 | * [谨慎使用 `this.$refs`](#谨慎使用-this.$refs) 40 | * [使用组件名作为样式作用域空间](#使用组件名作为样式作用域空间) 41 | * [提供组件 API 文档](#提供组件-api-文档) 42 | * [提供组件 demo](#提供组件-demo) 43 | * [对组件文件进行代码校验](#对组件文件进行代码校验) 44 | * [只在需要时创建组件](#只在需要时创建组件) 45 | 46 | 47 | 48 | ## 基于模块开发 49 | 50 | 始终基于模块的方式来构建你的 app,每一个子模块只做一件事情。 51 | 52 | Vue.js 的设计初衷就是帮助开发者更好的开发界面模块。一个模块是应用程序中独立的一个部分。 53 | 54 | ### 怎么做? 55 | 56 | 每一个 Vue 组件(等同于模块)[首先]((https://addyosmani.com/first/))必须专注于解决一个[单一的问题](http://en.wikipedia.org/wiki/Single_responsibility_principle),*独立的*、*可复用的*、*微小的* 和 *可测试的*。 57 | 58 | 如果你的组件做了太多的事或是变得臃肿,请将其拆分成更小的组件并保持单一的原则。一般来说,尽量保证每一个文件的代码行数不要超过 100 行。也请保证组件可独立的运行。比较好的做法是增加一个单独的 demo 示例。 59 | 60 | [↑ 回到目录](#目录) 61 | 62 | ## Vue 组件命名 63 | 64 | 组件的命名需遵从以下原则: 65 | 66 | * **有意义的**: 不过于具体,也不过于抽象 67 | * **简短**: 2 到 3 个单词 68 | * **具有可读性**: 以便于沟通交流 69 | 70 | 同时还需要注意: 71 | 72 | * 必须符合**自定义元素规范**: [使用连字符](https://www.w3.org/TR/custom-elements/#concepts)分隔单词,切勿使用保留字。 73 | * **`app-` 前缀作为命名空间**: 如果非常通用的话可使用一个单词来命名,这样可以方便于其它项目里复用。 74 | 75 | ### 为什么? 76 | 77 | * 组件是通过组件名来调用的。所以组件名必须简短、富有含义并且具有可读性。 78 | 79 | ### 如何做? 80 | 81 | ```html 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | ``` 92 | 93 | [↑ 回到目录](#目录) 94 | 95 | ## 组件表达式简单化 96 | 97 | Vue.js 的表达式是 100% 的 Javascript 表达式。这使得其功能性很强大,但也带来潜在的复杂性。因此,你应该尽量**保持表达式的简单化**。 98 | 99 | ### 为什么? 100 | 101 | * 复杂的行内表达式难以阅读。 102 | * 行内表达式是不能够通用的,这可能会导致重复编码的问题。 103 | * IDE 基本上不能识别行内表达式语法,所以使用行内表达式 IDE 不能提供自动补全和语法校验功能。 104 | 105 | ### 怎么做? 106 | 107 | 如果你发现写了太多复杂并难以阅读的行内表达式,那么可以使用 method 或是 computed 属性来替代其功能。 108 | 109 | ```html 110 | 111 | 116 | 133 | 134 | 135 | 140 | ``` 141 | 142 | [↑ 回到目录](#目录) 143 | 144 | ### 组件 props 原子化 145 | 146 | 虽然 Vue.js 支持传递复杂的 JavaScript 对象通过 props 属性,但是你应该尽可能的使用原始类型的数据。尽量只使用 [JavaScript 原始类型](https://developer.mozilla.org/en-US/docs/Glossary/Primitive)(字符串、数字、布尔值)和函数。尽量避免复杂的对象。 147 | 148 | ### 为什么? 149 | 150 | * 使得组件 API 清晰直观。 151 | * 只使用原始类型和函数作为 props 使得组件的 API 更接近于 HTML(5) 原生元素。 152 | * 其它开发者更好的理解每一个 prop 的含义、作用。 153 | * 传递过于复杂的对象使得我们不能够清楚的知道哪些属性或方法被自定义组件使用,这使得代码难以重构和维护。 154 | 155 | ### 怎么做? 156 | 157 | 组件的每一个属性单独使用一个 props,并且使用函数或是原始类型的值。 158 | 159 | ```html 160 | 161 | 168 | 169 | 170 | 171 | 172 | ``` 173 | 174 | [↑ 回到目录](#目录) 175 | 176 | ## 验证组件的 props 177 | 178 | 在 Vue.js 中,组件的 props 即 API,一个稳定并可预测的 API 会使得你的组件更容易被其他开发者使用。 179 | 180 | 组件 props 通过自定义标签的属性来传递。属性的值可以是 Vue.js 字符串(`:attr="value"` 或 `v-bind:attr="value"`)或是不传。你需要保证组件的 props 能应对不同的情况。 181 | 182 | ### 为什么? 183 | 184 | 验证组件 props 可以保证你的组件永远是可用的(防御性编程)。即使其他开发者并未按照你预想的方法使用时也不会出错。 185 | 186 | ### 怎么做? 187 | 188 | * 提供默认值。 189 | * 使用 `type` 属性[校验类型](http://vuejs.org/v2/guide/components.html#Prop-Validation)。 190 | * 使用 props 之前先检查该 prop 是否存在。 191 | 192 | ```html 193 | 196 | 214 | ``` 215 | 216 | [↑ 回到目录](#目录) 217 | 218 | ## 将 `this` 赋值给 `component` 变量 219 | 220 | 在 Vue.js 组件上下文中,`this`指向了组件实例。因此当你切换到了不同的上下文时,要确保 `this` 指向一个可用的 `component` 变量。 221 | 222 | 换句话说,如果你正在使用 **ES6** 的话,就不要再编写 `var self = this;` 这样的代码了,您可以安全地使用 Vue 组件。 223 | 224 | ### 为什么? 225 | 226 | * 使用 **ES6**,就不再需要将 `this` 保存到一个变量中了。 227 | * 一般来说,当你使用箭头函数时,会保留 `this` 的作用域。(译者注:箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域。) 228 | * 如果你没有使用 **ES6**,当然也就不会使用 `箭头函数` 啦,那你必须将 “this” 保存到到某个变量中。这是唯一的例外。 229 | 230 | ### 怎么做? 231 | 232 | ```html 233 | 245 | 246 | 247 | 260 | ``` 261 | 262 | [↑ 回到目录](#目录) 263 | 264 | ## 组件结构化 265 | 266 | 按照一定的结构组织,使得组件便于理解。 267 | 268 | ### 为什么? 269 | 270 | * 导出一个清晰、组织有序的组件,使得代码易于阅读和理解。同时也便于标准化。 271 | * 按首字母排序 properties、data、computed、watches 和 methods 使得这些对象内的属性便于查找。 272 | * 合理组织,使得组件易于阅读。(name; extends; props, data 和 computed; components; watch 和 methods; lifecycle methods 等)。 273 | * 使用 `name` 属性。借助于 [vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en) 可以让你更方便的测试。 274 | * 合理的 CSS 结构,如 [BEM](https://medium.com/tldr-tech/bem-blocks-elements-and-modifiers-6b3b0af9e3ea#.bhnomd7gw) 或 [rscss](https://github.com/rstacruz/rscss) - [详情?](#使用组件名作为样式作用域空间)。 275 | * 使用单文件 .vue 文件格式来组件代码。 276 | 277 | ### 怎么做? 278 | 279 | 组件结构化 280 | 281 | ```html 282 | 287 | 288 | 315 | 316 | 319 | ``` 320 | 321 | [↑ 回到目录](#目录) 322 | 323 | ## 组件事件命名 324 | 325 | Vue.js 提供的处理函数和表达式都是绑定在 ViewModel 上的,组件的每一个事件都应该按照一个好的命名规范来,这样可以避免不少的开发问题,具体可见如下 **为什么**。 326 | 327 | ### 为什么? 328 | 329 | * 开发者可以随意给事件命名,即使是原生事件的名字,这样会带来迷惑性。 330 | * 过于宽松的事件命名可能与 [DOM 模板不兼容](https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats)。 331 | 332 | ### 怎么做? 333 | 334 | * 事件名也使用连字符命名。 335 | * 一个事件的名字对应组件外的一组意义操作,如:upload-success、upload-error 以及 dropzone-upload-success、dropzone-upload-error (如果需要前缀的话)。 336 | * 事件命名应该以动词(如 client-api-load) 或是 名词(如 drive-upload-success)结尾。([出处](https://github.com/GoogleWebComponents/style-guide#events)) 337 | 338 | 339 | [↑ 回到目录](#目录) 340 | 341 | ## 避免 this.$parent 342 | 343 | Vue.js 支持组件嵌套,并且子组件可访问父组件的上下文。访问组件之外的上下文违反了[基于模块开发](#基于模块开发)的[第一原则](https://addyosmani.com/first/)。因此你应该尽量避免使用 **`this.$parent`**。 344 | 345 | ### 为什么? 346 | 347 | * 组件必须相互保持独立,Vue 组件也是。如果组件需要访问其父层的上下文就违反了该原则。 348 | * 如果一个组件需要访问其父组件的上下文,那么该组件将不能在其它上下文中复用。 349 | 350 | ### 怎么做? 351 | 352 | * 通过 props 将值传递给子组件。 353 | * 通过 props 传递回调函数给子组件来达到调用父组件方法的目的。 354 | * 通过在子组件触发事件来通知父组件。 355 | 356 | [↑ 回到目录](#目录) 357 | 358 | ## 谨慎使用 this.$refs 359 | 360 | Vue.js 支持通过 `ref` 属性来访问其它组件和 HTML 元素。并通过 `this.$refs` 可以得到组件或 HTML 元素的上下文。在大多数情况下,通过 `this.$refs`来访问其它组件的上下文是可以避免的。在使用的的时候你需要注意避免调用了不恰当的组件 API,所以应该尽量避免使用 `this.$refs`。 361 | 362 | ### 为什么? 363 | 364 | * 组件必须是保持独立的,如果一个组件的 API 不能够提供所需的功能,那么这个组件在设计、实现上是有问题的。 365 | * 组件的属性和事件必须足够的给大多数的组件使用。 366 | 367 | ### 怎么做? 368 | 369 | * 提供良好的组件 API。 370 | * 总是关注于组件本身的目的。 371 | * 拒绝定制代码。如果你在一个通用的组件内部编写特定需求的代码,那么代表这个组件的 API 不够通用,或者你可能需要一个新的组件来应对该需求。 372 | * 检查所有的 props 是否有缺失的,如果有提一个 issue 或是完善这个组件。 373 | * 检查所有的事件。子组件向父组件通信一般是通过事件来实现的,但是大多数的开发者更多的关注于 props 从忽视了这点。 374 | * **Props向下传递,事件向上传递!**。以此为目标升级你的组件,提供良好的 API 和 独立性。 375 | * 当遇到 props 和 events 难以实现的功能时,通过 `this.$refs`来实现。 376 | * 当需要操作 DOM 无法通过指令来做的时候可使用 `this.$ref` 而不是 `JQuery`、`document.getElement*`、`document.queryElement`。 377 | 378 | 379 | ```html 380 | 381 | 385 | ``` 386 | 387 | ```html 388 | 389 | 390 |

Basic Modal

391 | 392 |
393 | 394 | 395 | 396 | 401 | 402 | 421 | 422 | ``` 423 | 424 | ```html 425 | 426 | 432 | 433 | 444 | ``` 445 | 446 | [↑ 回到目录](#目录) 447 | 448 | ## 使用组件名作为样式作用域空间 449 | 450 | Vue.js 的组件是自定义元素,这非常适合用来作为样式的根作用域空间。可以将组件名作为 CSS 类的命名空间。 451 | 452 | ### 为什么? 453 | 454 | * 给样式加上作用域空间可以避免组件样式影响外部的样式。 455 | * 保持模块名、目录名、样式根作用域名一样,可以很好的将其关联起来,便于开发者理解。 456 | 457 | ### 怎么做? 458 | 459 | 使用组件名作为样式命名的前缀,可基于 BEM 或 OOCSS 范式。同时给 style 标签加上 scoped 属性。加上 scoped 属性编译后会给组件的 class 自动加上唯一的前缀从而避免样式的冲突。 460 | 461 | ```html 462 | 471 | ``` 472 | 473 | [↑ 回到目录](#目录) 474 | 475 | ## 提供组件 API 文档 476 | 477 | 使用 Vue.js 组件的过程中会创建 Vue 组件实例,这个实例是通过自定义属性配置的。为了便于其他开发者使用该组件,对于这些自定义属性即组件API应该在 `README.md` 文件中进行说明。 478 | 479 | ## 为什么? 480 | 481 | * 良好的文档可以让开发者比较容易的对组件有一个整体的认识,而不用去阅读组件的源码,也更方便开发者使用。 482 | * 组件配置属性即组件的 API,对于组件的用户来说他们更感兴趣的是 API 而不是实现原理。 483 | * 正式的文档会告诉开发者组件 API 变更以及向后的兼容性情况。 484 | * `README.md` 是标准的我们应该首先阅读的文档文件。代码托管网站(GitHub、Bitbucket、Gitlab 等)会默认在仓库中展示该文件作为仓库的介绍。 485 | 486 | ### 怎么做? 487 | 488 | 在模块目录中添加 `README.md` 文件: 489 | 490 | ``` 491 | range-slider/ 492 | ├── range-slider.vue 493 | ├── range-slider.less 494 | └── README.md 495 | ``` 496 | 497 | 在 README 文件中说明模块的功能以及使用场景。对于 vue 组件来说,比较有用的描述是组件的自定义属性即 API 的描述介绍。 498 | 499 | # Range slider 500 | 501 | ## 功能 502 | 503 | range slider 组件可通过拖动的方式来设置一个给定范围内的数值。 504 | 505 | 该模块使用 [noUiSlider](http://refreshless.com/nouislider/) 来实现跨浏览器和 touch 功能的支持。 506 | 507 | ## 如何使用 508 | 509 | `` 支持如下的自定义属性: 510 | 511 | 512 | | attribute | type | description 513 | | --- | --- | --- 514 | | `min` | Number | 可拖动的最小值. 515 | | `max` | Number | 可拖动的最大值. 516 | | `values` | Number[] *optional* | 包含最大值和最小值的数组. 如. `values="[10, 20]"`. Defaults to `[opts.min, opts.max]`. 517 | | `step` | Number *optional* | 增加减小的数值单位,默认为 1. 518 | | `on-slide` | Function *optional* | 用户拖动开始按钮或者结束按钮时的回调函数,函数接受 `(values, HANDLE)` 格式的参数。 如: `on-slide={ updateInputs }`, `component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }`. 519 | | `on-end` | Function *optional* | 当用户停止拖动时触发的回调函数,函数接受 `(values, HANDLE)` 格式的参数。 520 | 521 | 522 | 如需要自定义 slider 的样式可参考 [noUiSlider 文档]((http://refreshless.com/nouislider/more/#section-styling)) 523 | 524 | 525 | [↑ 回到目录](#目录) 526 | 527 | ## 提供组件 demo 528 | 529 | 添加 `index.html` 文件作为组件的 demo 示例,并提供不同配置情况的效果,说明组件是如何使用的。 530 | 531 | ### 为什么? 532 | 533 | * demo 可以说明组件是独立可使用的。 534 | * demo 可以让开发者预览组件的功能效果。 535 | * demo 可以展示组件各种配置参数下的功能。 536 | 537 | [↑ 回到目录](#目录) 538 | 539 | ## 对组件文件进行代码校验 540 | 541 | 代码校验可以保持代码的统一性以及追踪语法错误。.vue 文件可以通过使用 `eslint-plugin-html`插件来校验代码。你可以通过 `vue-cli` 来开始你的项目,`vue-cli` 默认会开启代码校验功能。 542 | 543 | ### 为什么? 544 | 545 | * 保证所有的开发者使用同样的编码规范。 546 | * 更早的感知到语法错误。 547 | 548 | ### 怎么做? 549 | 550 | 为了校验工具能够校验 `*.vue`文件,你需要将代码编写在 ` 666 | ``` 667 | 668 | [↑ 回到目录](#目录) 669 | 670 | --- 671 | 672 | ### 如何提供帮助? 673 | 674 | Fork 和提 PR 以帮助我们改进或者可以给我们提 [Issue](https://github.com/pablohpsilva/vuejs-component-style-guide/issues/new)。 675 | 676 | ## 译者 677 | 678 | * [杨小福](https://github.com/xiaofuzi) 679 | * [机智的马里奥](https://github.com/wysxhlyy) 680 | * [根号三](https://github.com/sqrthree) 681 | -------------------------------------------------------------------------------- /README-FA.md: -------------------------------------------------------------------------------- 1 | # راهنمای سبک نگارش کامپوننت ویو جی اس 2 | 3 |

4 | 5 |

6 | 7 | ### ترجمه ها 8 | 9 | - [پرتغالی برزیلی](https://pablohpsilva.github.io/vuejs-component-style-guide/#/portuguese) 10 | - [چینی](https://pablohpsilva.github.io/vuejs-component-style-guide/#/chinese) 11 | - [ژاپنی](https://pablohpsilva.github.io/vuejs-component-style-guide/#/japanese) 12 | - [کره ای](https://pablohpsilva.github.io/vuejs-component-style-guide/#/korean) 13 | - [روسی](https://pablohpsilva.github.io/vuejs-component-style-guide/#/russian) 14 | - [فارسی](https://pablohpsilva.github.io/vuejs-component-style-guide/#/farsi) 15 | 16 | ## هدف 17 | 18 | این راهنما یک راه یکسان برای ساختار دادن به کد [ویو جی اس](http://vuejs.org/) شما است و موارد زیر را ممکن می سازد: 19 | 20 | - برای توسعه دهندگان و اعضای تیم درک کردن و متوجه شدن موضوعات آسان تر می شود. 21 | - برای محیط های یکپارچه توسعه، تفسیر کد و فراهم کردن پشتیبانی آسان تر می شود. 22 | - استفاده از ابزار های بیلد آسان تر می شود. 23 | - نهان سازی و ارائه بسته های کد به طور جداگانه آسان تر می شود. 24 | 25 | این راهنما از مخزن [RiotJS Style Guide](https://github.com/voorhoede/riotjs-style-guide) که توسط [De Voorhoede](https://github.com/voorhoede) نوشته شده است الهام گرفته شده است. 26 | 27 | ## فهرست مطالب 28 | 29 | - [توسعه مبتنی بر ماژول](#توسعه-مبتنی-بر-ماژول) 30 | - [نام های کامپوننت ویو](#نام-های-کامپوننت-ویو) 31 | - [کد های کامپوننت را ساده نگه دارید](#کد-های-کامپوننت-را-ساده-نگه-دارید) 32 | - [پراپ های کامپوننت را ساده نگه دارید](#پراپ-های-کامپوننت-را-ساده-نگه-دارید) 33 | - [از پراپ های کامپوننت استفاده بهینه کنید](#از-پراپ-های-کامپوننت-استفاده-بهینه-کنید) 34 | - [`this` را به `کامپوننت` نسبت دهید](#this-را-به-کامپوننت-نسبت-دهید) 35 | - [ساختار کامپوننت](#ساختار-کامپوننت) 36 | - [نام های ایونت کامپوننت](#نام-های-ایونت-کامپوننت) 37 | - [از استفاده کردن از `this.$parent` پرهیز کنید](#avoid-thisparent) 38 | - [از `this.$refs` با احتیاط استفاده کنید](#use-thisrefs-with-caution) 39 | - [از نام کامپوننت به عنوان محدوده style استفاده کنید](#از-نام-کامپوننت-به-عنوان-محدوده-style-استفاده-کنید) 40 | - [برای ای پی آی کامپوننت خود مستند بنویسید](#برای-ای-پی-آی-کامپوننت-خود-مستند-بنویسید) 41 | - [دمو کامپوننت را اضافه کنید](#دمو-کامپوننت-را-اضافه-کنید) 42 | - [فایل های کامپوننت خود را لینت کنید](#فایل-های-کامپوننت-خود-را-لینت-کنید) 43 | - [کامپوننت ها را زمانی بسازید که به آن ها نیاز دارید](#کامپوننت-ها-را-زمانی-بسازید-که-به-آن-ها-نیاز-دارید) 44 | 45 | 46 | 47 | ## توسعه مبتنی بر ماژول 48 | 49 | همیشه برنامه خود را با استفاده از ماژول های کوچکی که فقط یک کار و آن کار را هم درست انجام می دهند، بسازید. 50 | 51 | ماژول یک بخش کوچک و مستقل از یک برنامه است. کتابخانه ویو جی اس به طور مشخص برای کمک کردن برای ساخت _ماژول های view-logic_ طراحی شده است . 52 | 53 | ### چرا؟ 54 | 55 | یادگیری، درک کردن، نگهداری، استفاده مجدد و رفع مشکلات ماژول های کوچک، چه برای خود شما و چه برای توسعه دهندگان دیگر راحت تر می شود. 56 | 57 | ### 58 | 59 | هر کامپوننت ویو (مثل یک ماژول) باید [در ابتدا](https://addyosmani.com/first/): _دارای یک هدف مشخص_ ([تک وظیفه‌ای](http://en.wikipedia.org/wiki/Single_responsibility_principle))، _مستقل_، _قابل استفاده مجدد_، _کوچک_ و _با قابلیت تست_ باشد. 60 | 61 | اگر کامپوننت شما کار های زیادی انجام می دهد و یا خیلی بزرگ شده است آن را به کامپوننت های کوچکتر تقسیم کنید به طوری که هر کدام فقط یه کار را انجام دهند و بر حسب تجربه، تلاش کنید که فایل هر کامپوننت کمتر از 100 خط کد باشد. 62 | همچنین مطمئن شوید کامپوننت های شما به صورت مستقل از هم کار می کنند، برای مثال یک دمو مستقل برای آن قرار دهید. 63 | 64 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 65 | 66 | ## نام های کامپوننت ویو 67 | 68 | نام هر کامپوننت باید موارد زیر را شامل شود: 69 | 70 | - **پر معنا**: نه بیش از حد دقیق و نه بیش از حد خلاصه شده و انتزاعی باشد. 71 | - **کوتاه**: 2 یا 3 کلمه. 72 | - **قابل تلفظ**: زیرا ما می خواهیم درباره آن حرف بزنیم و اسم آن را به زبان بیاوریم. 73 | 74 | همچنین نام هر کامپوننت ویو باید مطابق موارد زیر باشد: 75 | 76 | - **مطابق با تعریف عنصر سفارشی**: [شامل خط فاصله باشد](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name), و از نام های رزرو شده استفاده نشده باشد. 77 | - **`app-` namespaced**: نام باید عمومی و از طرف دیگر شامل یک کلمه باشد که بتوان به راحتی از آن در پروژه های دیگر استفاده مجدد کرد. 78 | 79 | ### چرا؟ 80 | 81 | - از نام برای ارتباط برقرار کردن با کامپوننت استفاده می شود. پس باید کوتاه، پر معنا و قابل تلفظ باشد. 82 | 83 | ### با چه روشی؟ 84 | 85 | ```html 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | ``` 101 | 102 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 103 | 104 | ## کد های کامپوننت را ساده نگه دارید 105 | 106 | کد های خطی ویو جی اس کلا جاوا اسکریپت هستند. و این قضیه آن ها را به شدت قدرتمند می سازد، اما ذاتا پیچیده هستند. بنابرین شما باید **کد های خطی را ساده نگه دارید**. 107 | 108 | ### چرا؟ 109 | 110 | - خواندن کد های خطی پیچیده، سخت است. 111 | - کد های خطی پیچیده نمی توانند در جای دیگر مورد استفاده مجدد قرار بگیرند که این می تواند منجر به تکرار و پوسیدگی کدها شود. 112 | - محیط های یکپارچه توسعه، معمولا پشتیبانی برای سینتکس های کد های خطی ندارد، بنابراین نمی توانند به طور خودکار تکمیل یا اعتبار سنجی شوند. 113 | 114 | ### با چه روشی؟ 115 | 116 | اگر کد خیلی پیچیده شد و یا خواندن آن سخت شد، **شما می بایست کد را به methods یا computed انتقال دهید**! 117 | 118 | ```html 119 | 120 | 123 | 140 | 141 | 142 | 148 | ``` 149 | 150 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 151 | 152 | ## پراپ های کامپوننت را ساده نگه دارید 153 | 154 | در حالی که ویو جی اس به خاطر ویژگی هایش از ارسال آبجکت های پیچیده جاوا اسکریپتی پشتیبانی می کند شما باید تلاش کنید تا **پراپ های کامپوننت را تا جای ممکن ساده نگه دارید**. تلاش کنید تا فقط از [داده های اولیه جاوا اسکریپت](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) که شامل (رشته ها، اعداد، بولین) و توابع می شوند، استفاده کنید. و از آبجکت های پیچیده پرهیز کنید. 155 | 156 | ### چرا؟ 157 | 158 | - زمانی از یک اتریبیوت به طور جداگانه برای هر پراپ استفاده می کنیم، کامپوننت ای پی آی واضح و صریحی دارد; 159 | - با استفاده کردن از داده های اولیه و توابع به عنوان مقادیر پراپ ها، ای پی آی های کامپوننت ما شبیه به ای پی آی های عنصر های بومی اچ تی ام ال 5 می شود; 160 | - با استفاده کردن از اتریبیوت ها به ازای هر پراپ، بقیه توسعه دهندگان به راحتی می توانند بفهمند که چه چیز هایی به نمونه کامپوننت ارسال شده است. 161 | - زمانی که آبجکت های پیچیده را ارسال می کنید، واضح نیست که چه ویژگی ها و متود هایی از آبجکت واقعا مورد استفاده کامپوننت های سفارشی قرار گرفته است. این باعث می شود ریفکتور کردن کد سخت شود و کد ها به سمت پوسیده شدن بروند. 162 | 163 | ### با چه روشی؟ 164 | 165 | به ازای هر اتریبیوت برای کامپوننت، از یک پراپ استفاده کنید، که مقدارشان داده اولیه یا تابع باشد: 166 | 167 | ```html 168 | 169 | 177 | 178 | 179 | 180 | 181 | ``` 182 | 183 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 184 | 185 | ## از پراپ های کامپوننت استفاده بهینه کنید 186 | 187 | در ویو جی اس پراپ های کامپوننت، ای پی آی شما هستند. یک ای پی آی منسجم و قابل پیش بینی، استفاده از کامپوننت شما را برای بقیه توسعه دهندگان راحت می کند. 188 | 189 | پراپ های کامپوننت از طریق اتریبیوت های اچ تی ام ال ارسال می شوند. مقادیر این اتریبیوت ها می تواند رشته های ساده ویو جی اس (`:attr="value"` یا `v-bind:attr="value"`) باشد یا به طور کامل صرف نظر شود. شما باید **پراپ های کامپوننت کنترل کنید** تا بتوانید سناریو های مختلف را امکان پذیر کنید. 190 | 191 | ### چرا؟ 192 | 193 | کنترل کردن پراپ های کامپوننت به شما اطمینان می دهند کامپوننت شما همیشه به درستی کار کند (برنامه نویسی تدافعی). حتی اگر بقیه توسعه دهندگان، در زمانی دیگر از کامپوننت های شما به شیوه دیگری استفاده کنند که شما فکرش را از قبل نکرده بودید. 194 | 195 | ### با چه روشی؟ 196 | 197 | - از پیش فرض ها برای مقادیر پراپ ها استفاده کنید 198 | - از گزینه `type` برای [اعتبارسنجی](http://vuejs.org/v2/guide/components.html#Prop-Validation) مقادیر به منظور دریافت نوع مورد انتظار استفاده کنید.**[1\*]** 199 | - قبل از استفاده کردن از پراپ ها، بررسی کنید تا ببینید پراپ ها وجود داشته باشند. 200 | 201 | ```html 202 | 205 | 229 | ``` 230 | 231 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 232 | 233 | ## `this` را به `کامپوننت` نسبت دهید 234 | 235 | در داخل فضای عنصر کامپوننت ویو جی اس، `this` به نمونه کامپوننت اشاره می کند. 236 | بنابراین زمانی که شما نیاز دارید در فضای دیگری ارجاع دهید، اطمینان پیدا کنید که `this` به عنوان `کامپوننت` در دسترس باشد. 237 | 238 | به عبارت دیگر: اگر میخواهید از استاندارد **ES6** استفاده کنید، چیز هایی شبیه `var self = this;` را دیگر **ننویسید**. شما با این کار، از کامپوننت های ویو به صورت ایمن استفاده می کنید. 239 | 240 | ### چرا؟ 241 | 242 | - با استفاده از در استاندارد ES6، نیازی نیست `this` را در یک متغیر ذخیره کنیدک 243 | -در کل، زمانی که از توابع Arrow استفاده می کنیم اسکوپ لکسیکال حفظ می شود. 244 | - اگر شما از استاندارد ES6 استفاده **نمی کنید**، بنابراین از توابع Arrow هم استفاده نمی کنید پس شما می بایست `this` را به یک متغیر نسبت دهید. این تنها حالت استثنا می باشد. 245 | 246 | ### با چه روشی؟ 247 | 248 | ```html 249 | 261 | 262 | 263 | 276 | ``` 277 | 278 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 279 | 280 | ## ساختار کامپوننت 281 | 282 | این دستورالعمل ها را دنبال کنید تا چگونگی آن را دریابید. 283 | 284 | ### چرا؟ 285 | 286 | - داشتن خروجی کامپوننت منجر به یک آبجکت گروه بندی شده و تمیز می شود، که باعث می شود خواندن کد آسان شود و توسعه دهندگان کد استانداردی را داشته باشند. 287 | - چینش properties، data، computed، watches، و methods بر اساس حروف الفبا باعث می شود پیدا کردن آن ها آسان تر شود. 288 | - دوباره می گوییم، گروه بندی کردن باعث می شود خوانایی کامپوننت بیشتر شود. (name; extends; props، data و computed; components; watch و methods; lifecycle methods، و غیره.); 289 | - Use the `name` attribute. Using [vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en) and that attribute will make your development/testing easier; 290 | - از متودولوژی های نامگذاری سی اس اس استفاده کنید ، مانند [BEM](https://medium.com/tldr-tech/bem-blocks-elements-and-modifiers-6b3b0af9e3ea#.bhnomd7gw), یا [rscss](https://github.com/rstacruz/rscss) - [details?](#use-component-name-as-style-scope); 291 | - از ساختار فایل .vue و template-script-style استفاده کنید, همان طور که توسط Evan You خالق ویو پیشنهاد شده است. 292 | 293 | ### با چه روشی؟ 294 | 295 | ساختار کامپوننت: 296 | 297 | ```html 298 | 303 | 304 | 331 | 332 | 337 | ``` 338 | 339 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 340 | 341 | ## Component event names 342 | 343 | Vue.js provides all Vue handler functions and expressions are strictly bound to the ViewModel. Each component events should follow a good naming style that will avoid issues during the development. See the **Why** below. 344 | 345 | ### چرا؟ 346 | 347 | - Developers are free to use native likes event names and it can cause confusion down the line; 348 | - آزادی برای نام گذاری ایونت ها میتواند به مورد رو به رو منجر شود [DOM ناسازگاری الگو های](https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats); 349 | 350 | ### با چه روشی؟ 351 | 352 | - نام ایونت ها باید kebab-cased باشد; 353 | - A unique event name should be fired for unique actions in your component that will be of interest to the outside world, like: upload-success, upload-error or even dropzone-upload-success, dropzone-upload-error (if you see the need for having a scoped prefix); 354 | - Events should either end in verbs in the infinitive form (e.g. client-api-load) or nouns (e.g drive-upload-success) ([source](https://github.com/GoogleWebComponents/style-guide#events)); 355 | 356 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 357 | 358 | ## Avoid `this.$parent` 359 | 360 | Vue.js supports nested components which have access to their parent context. Accessing context outside your vue component violates the [FIRST](https://addyosmani.com/first/) rule of [component based development](#module-based-development). Therefore you should **avoid using `this.$parent`**. 361 | 362 | ### چرا؟ 363 | 364 | - A vue component, like any component, must work in isolation. If a component needs to access its parent, this rule is broken. 365 | - If a component needs access to its parent, it can no longer be reused in a different context. 366 | 367 | ### با چه روشی؟ 368 | 369 | - Pass values from the parent to the child component using attribute/properties. 370 | - Pass methods defined on the parent component to the child component using callbacks in attribute expressions. 371 | - Emit events from child components and catch it on parent component. 372 | 373 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 374 | 375 | ## Use `this.$refs` with caution 376 | 377 | Vue.js supports components to have access to other components and basic HTML elements context via `ref` attribute. That attribute will provide an accessible way through `this.$refs` to a component or DOM element context. In most cases, the need to access **other components** context via `this.$refs` could be avoided. This is why you should be careful when using it to avoid wrong component APIs. 378 | 379 | ### چرا؟ 380 | 381 | - A vue component, like any component, **must work in isolation**. If a component does not support all the access needed, it was badly designed/implemented. 382 | - Properties and events should be sufficient to most of your components. 383 | 384 | ### با چه روشی؟ 385 | 386 | - Create a good component API. 387 | - Always focus on the component purpose out of the box. 388 | - Never write specific code. If you need to write specific code inside a generic component, it means its API isn't generic enough or maybe you need a new component to manage other cases. 389 | - Check all the props to see if something is missing. If it is, create an issue or enhance the component yourself. 390 | - Check all the events. In most cases developers forget that Child-Parent communication (events) is needed, that's why they only remember the Parent-Child communication (using props). 391 | - **Props down, events up!** Upgrade your component when requested with a good API and isolation as goals. 392 | - Using `this.$refs` on components should be used when props and events are exhausted and having it makes sense (see the example below). 393 | - Using `this.$refs` to access DOM elements (instead of doing `jQuery`, `document.getElement*`, `document.queryElement`) is just fine, when the element can't be manipulated with data bindings or for a directive. 394 | 395 | ```html 396 | 397 | 398 | ``` 399 | 400 | ```html 401 | 402 | 403 |

Basic Modal

404 | 405 |
406 | 407 | 408 | 409 | 414 | 415 | 434 | ``` 435 | 436 | ```html 437 | 438 | 441 | 442 | 453 | ``` 454 | 455 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 456 | 457 | ## از نام کامپوننت به عنوان محدوده style استفاده کنید 458 | 459 | Vue.js component elements are custom elements which can very well be used as style scope root. 460 | Alternatively the component name can be used as CSS class namespace. 461 | 462 | ### چرا؟ 463 | 464 | - Scoping styles to a component element improves predictability as its prevents styles leaking outside the component element. 465 | - Using the same name for the module directory, the Vue.js component and the style root makes it easy for developers to understand they belong together. 466 | 467 | ### با چه روشی؟ 468 | 469 | Use the component name as a namespace prefix based on BEM and OOCSS **and** use the `scoped` attribute on your style class. 470 | The use of `scoped` will tell your Vue compiler to add a signature on every class that your ` 487 | ``` 488 | 489 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 490 | 491 | ## برای ای پی آی کامپوننت خود مستند بنویسید 492 | 493 | A Vue.js component instance is created by using the component element inside your application. The instance is configured through its custom attributes. For the component to be used by other developers, these custom attributes - the component's API - should be documented in a `README.md` file. 494 | 495 | ### چرا؟ 496 | 497 | - Documentation provides developers with a high level overview to a component, without the need to go through all its code. This makes a component more accessible and easier to use. 498 | - A component's API is the set of custom attributes through which its configured. Therefore these are especially of interest to other developers which only want to consume (and not develop) the component. 499 | - Documentation formalises the API and tells developers which functionality to keep backwards compatible when modifying the component's code. 500 | - `README.md` is the de facto standard filename for documentation to be read first. Code repository hosting services (Github, Bitbucket, Gitlab etc) display the contents of the the README's, directly when browsing through source directories. This applies to our module directories as well. 501 | 502 | ### با چه روشی؟ 503 | 504 | Add a `README.md` file to the component's module directory: 505 | 506 | ``` 507 | range-slider/ 508 | ├── range-slider.vue 509 | ├── range-slider.less 510 | └── README.md 511 | ``` 512 | 513 | Within the README file, describe the functionality and the usage of the module. For a vue component its most useful to describe the custom attributes it supports as those are its API: 514 | 515 | # Range slider 516 | 517 | ## قابلیت 518 | 519 | The range slider lets the user to set a numeric range by dragging a handle on a slider rail for both the start and end value. 520 | 521 | This module uses the [noUiSlider](http://refreshless.com/nouislider/) for cross browser and touch support. 522 | 523 | ## نحوه استفاده 524 | 525 | `` supports the following custom component attributes: 526 | 527 | | attribute | type | description | 528 | | ---------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 529 | | `min` | Number | number where range starts (lower limit). | 530 | | `max` | Number | Number where range ends (upper limit). | 531 | | `values` | Number[] _اختیاری_ | Array containing start and end value. E.g. `values="[10, 20]"`. Defaults to `[opts.min, opts.max]`. | 532 | | `step` | Number _اختیاری_ | Number to increment / decrement values by. Defaults to 1. | 533 | | `on-slide` | Function _اختیاری_ | Function called with `(values, HANDLE)` while a user drags the start (`HANDLE == 0`) or end (`HANDLE == 1`) handle. E.g. `on-slide={ updateInputs }`, with `component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }`. | 534 | | `on-end` | Function _اختیاری_ | Function called with `(values, HANDLE)` when user stops dragging a handle. | 535 | 536 | For customising the slider appearance see the [Styling section in the noUiSlider docs](http://refreshless.com/nouislider/more/#section-styling). 537 | 538 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 539 | 540 | ## دمو کامپوننت را اضافه کنید 541 | 542 | Add a `index.html` file with demos of the component with different configurations, showing how the component can be used. 543 | 544 | ### چرا؟ 545 | 546 | - A component demo proves the component works in isolation. 547 | - A component demo gives developers a preview before having to dig into the documentation or code. 548 | - Demos can illustrate all the possible configurations and variations a component can be used in. 549 | 550 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 551 | 552 | ## فایل های کامپوننت خود را لینت کنید 553 | 554 | Linters improve code consistency and help trace syntax errors. .vue files can be linted adding the `eslint-plugin-html` in your project. If you choose, you can start a project with ESLint enabled by default using `vue-cli`; 555 | 556 | ### چرا؟ 557 | 558 | - لینت کردن فایل های کامپوننت این اطمینان را می دهد همه توسعه دهندگان از یک استایل کدی مشابه استفاده کنند 559 | - لینت کردن فایل ها کمک می کند که ارور های سینتکسی را قبل از اینکه به مشکل بخورید پیدا کنید 560 | 561 | ### با چه روشی؟ 562 | 563 | To allow linters to extract the scripts from your `*.vue` files, put script inside a ` 682 | ``` 683 | 684 | [↑ برگشت به فهرست مطالب](#فهرست-مطالب) 685 | 686 | --- 687 | 688 | ## می خواهید کمک کنید? 689 | 690 | فورک کنید و برای چیزی که فکر می کنید بهتر است بیان شود پول ریکوئست دهید یا یک [Issue](https://github.com/pablohpsilva/vuejs-component-style-guide/issues/new) بسازید. 691 | 692 | 731 | 732 | ## مترجم ها 733 | 734 | - [پرتغالی برزیلی](README-PTBR.md): Pablo Henrique Silva [github:pablohpsilva](https://github.com/pablohpsilva), [twitter: @PabloHPSilva](https://twitter.com/PabloHPSilva) 735 | - [روسی](https://pablohpsilva.github.io/vuejs-component-style-guide/#/russian): Mikhail Kuznetcov [github:shershen08](https://github.com/shershen08), [twitter: @legkoletat](https://twitter.com/legkoletat) 736 | - [فارسی](README-FA.md): Alireza Arabshahi [github:AlirezaArabshahi](https://github.com/AlirezaArabshahi), [twitter: @iialireza7](https://twitter.com/iialireza7) 737 | -------------------------------------------------------------------------------- /README-JP.md: -------------------------------------------------------------------------------- 1 | # Vue.js コンポーネント スタイル ガイド 2 | 3 |

4 | 5 |

6 | 7 | ### 翻訳 8 | * [英語](https://pablohpsilva.github.io/vuejs-component-style-guide/#/) 9 | * [ブラジルポルトガル語](https://pablohpsilva.github.io/vuejs-component-style-guide/#/portuguese) 10 | * [中国語](https://pablohpsilva.github.io/vuejs-component-style-guide/#/chinese) 11 | * [韓国語](https://pablohpsilva.github.io/vuejs-component-style-guide/#/korean) 12 | * [ロシア語](https://pablohpsilva.github.io/vuejs-component-style-guide/#/russian) 13 | 14 | ## 目的 15 | 16 | このガイドはあなたの[Vue.js](http://vuejs.org/) のコードを統一する方法を提供します。 17 | 18 | * 開発者/チームメンバがより問題を理解し、見つけやすくする。 19 | * IDEがよりコードを解釈し、支援を提供しやすくする。 20 | * すでに使用しているビルドツールを(再)利用しやすくする。 21 | * 別々のコードの塊を蓄え、供給しやすくする。 22 | 23 | このガイドは[De Voorhoede](https://github.com/voorhoede)による[RiotJS Style Guide](https://github.com/voorhoede/riotjs-style-guide)に刺激を受け作られました。 24 | 25 | ## 目次 26 | 27 | * [モジュールベースの開発](#モジュールベースの開発) 28 | * [Vueコンポーネントの名前](#vueコンポーネントの名前) 29 | 30 | * [コンポーネントの記述をシンプルに保つ](#コンポーネントの記述をシンプルに保つ) 31 | * [コンポーネントのpropsをプリミティブに保つ](#コンポーネントのpropsをプリミティブに保つ) 32 | * [コンポーネントのpropsの利用](#コンポーネントのpropsの利用) 33 | * [`this`を`component`に割り当てる](#thisをcomponentに割り当てる) 34 | * [コンポーネント構成](#コンポーネント構成) 35 | * [コンポーネントイベント名](#コンポーネントイベント名) 36 | * [`this.$parent`を避ける](#thisparentを避ける) 37 | * [`this.$refs`は注意して使用する](#thisrefsは注意して使用する) 38 | * [スタイルスコープとしてコンポーネント名を使用する](#スタイルスコープとしてコンポーネント名を使用する) 39 | * [コンポーネントAPIをドキュメント化する](#コンポーネントapiをドキュメント化する) 40 | * [コンポーネントデモの追加](#コンポーネントデモの追加) 41 | * [コンポーネントファイルをLintする](#コンポーネントファイルをlintする) 42 | * [必要に応じてコンポーネントを作成する](#必要に応じてコンポーネントを作成する) 43 | 44 | 45 | 46 | ## モジュールベースの開発 47 | 48 | 常に単一の機能を持つ小さなモジュールからアプリケーションを構築しましょう。 49 | 50 | モジュールはアプリケーションの自己完結型の小さな部品です。特にVue.jsライブラリはあなたが*view-logicなモジュール*を作れるように設計されています。 51 | 52 | ### 理由 53 | 54 | 小さなモジュールにすることで、あなたと他の開発者両方にとって、学びやすく、理解しやすく、維持しやすく、再利用しやすく、そして、 55 | デバッグしやすくなります。 56 | 57 | ### 方法 58 | 59 | 各Vueコンポーネント(モジュールのようなもの)は [FIRST](https://addyosmani.com/first/): ひとつのことに集中し (*Focused* ([単一責任](http://en.wikipedia.org/wiki/Single_responsibility_principle)))、独立していて(*Independent*)、 再利用可能で(*Reusable*)、小さく(*Small*) そしてテスト可能 (*Testable*)でなければなりません。 60 | 61 | もしあなたのコンポーネントが多くのことをしていて大きすぎる場合、ひとつのことだけをする、より小さなコンポーネントに分けましょう。 62 | 経験則から言うと、各コンポーネントは100行以下のコードになるようにするのがいいでしょう。また、例えばスタンドアローンのデモを追加することによって、 63 | Vueコンポーネントが独立して動作することを確認しましょう。 64 | 65 | [↑ 目次に戻る](#目次) 66 | 67 | 68 | ## Vueコンポーネントの名前 69 | 70 | 各コンポーネントの名前は、 71 | 72 | * **意味のある名前で**: 具体的過ぎず、抽象的過ぎず。 73 | * **短く**: 2または3語。 74 | * **発音可能**: それらについて話せるようにしたい。 75 | 76 | であるべきです。 77 | 78 | さらにVueコンポーネントの名前は、 79 | 80 | * **カスタム要素仕様に準拠**: [ハイフンを含み](https://www.w3.org/TR/custom-elements/#concepts)、 予約語は使用しない。 81 | * **`app-` ネームスペース**: 非常に汎用的、あるいは1語であれば、他のプロジェクトでも容易に再利用できる。 82 | 83 | であるべきです。 84 | 85 | ### 理由 86 | 87 | * 名前は、コンポーネントについて会話するときに使用されます。したがって、それは短く、意味があり、発音可能でなければなりません。 88 | 89 | ### 方法 90 | 91 | ```html 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ``` 102 | 103 | [↑ 目次に戻る](#目次) 104 | 105 | 106 | ## コンポーネントの記述をシンプルに保つ 107 | 108 | Vue.jsのインラインの記述は100%JavaScriptです。これは非常に強力なことですが、複雑になる可能性もあるということです。 109 | ですので、**シンプルな記述を保つようにしましょう。**. 110 | 111 | ### 理由 112 | 113 | * 複雑なインラインの記述は判読困難です。 114 | * インラインの記述は他の場所で再利用できません。これはコードの重複と腐敗につながります。 115 | * IDEは基本的に式の構文サポート機能を持っていないため、自動補完や検証を行うことができません。 116 | 117 | ### 方法 118 | 119 | もしあまりにも複雑だったり、判読困難な場合は**メソッド、またはcomputedプロパティに移動させましょう**! 120 | 121 | ```html 122 | 123 | 128 | 145 | 146 | 147 | 152 | ``` 153 | 154 | [↑ 目次に戻る](#目次) 155 | 156 | 157 | ## コンポーネントのpropsをプリミティブに保つ 158 | 159 | Vue.jsは複雑なJavaScriptオブジェクトを渡せるようになっていますが, **コンポーネントのpropsはできるだけプリミティブに保つ** ようにするべきです。複雑なオブジェクトの使用を避け、[JavaScriptプリミティブ](https://developer.mozilla.org/en-US/docs/Glossary/Primitive)と関数のみを使うようにしましょう。 160 | 161 | ### 理由 162 | 163 | * 各propの属性を別々に使用することにより、コンポーネントは明確で表現力豊かなAPIを持つことになります。 164 | * propsの値としてプリミティブとファンクションのみを使用することで、コンポーネントのAPIをネイティブHTML(5)のAPIに似たものにできます。 165 | * 各propの属性を使用することで、他の開発者がコンポーネントインスタンスに何が渡されるかを理解しやすくなります。 166 | * 複雑なオブジェクトが渡されると、そのオブジェクトのどのプロパティとメソッドが実際にカスタムコンポーネントで使われるかがわかりにくくなります。これによりコードのリファクタリングが難しくなり、腐敗を招くことになります。 167 | 168 | ### 方法 169 | 170 | プリミティブまたは関数を値としたpropsごとのコンポーネント属性を使用します。 171 | 172 | ```html 173 | 174 | 181 | 182 | 183 | 184 | 185 | ``` 186 | 187 | [↑ 目次に戻る](#目次) 188 | 189 | 190 | ## コンポーネントのpropsの利用 191 | 192 | Vue.jsでは、あなたのコンポーネントのpropsはあなたのAPIです。頑丈で予測しやすいAPIは、他の開発者があなたのコンポーネントを使用するのを簡単にします。 193 | 194 | コンポーネントのpropsはカスタムHTML属性を介して渡されます。 これらの属性の値はVue.jsプレーンストリング (`:attr="値"` または `v-bind:attr="値"`)か、または無いこともあります。 あなたは **コンポーネントのpropsを利用** して、それらの異なるケースに対応できるようにしましょう。 195 | 196 | ### 理由 197 | 198 | コンポーネントのpropsを利用することで、あなたのコンポーネントを常に機能するようになります(防御的プログラミング)。それは後で他の開発者が、あなたが想定していない方法でコンポーネントを使用する場合でもです。 199 | 200 | ### 方法 201 | 202 | * propsのデフォルト値を使用します。 203 | * 期待するタイプの値の[検証](http://vuejs.org/v2/guide/components.html#Prop-Validation)のために、`type`オプションを使用します。**[1\*]** 204 | * 使用される前にpropsが存在するかチェックします。 205 | 206 | ```html 207 | 210 | 228 | ``` 229 | 230 | [↑ 目次に戻る](#目次) 231 | 232 | 233 | ## `this`を`component`に割り当てる 234 | 235 | Vue.jsコンポーネントのコンテキスト内では、 `this`はコンポーネントインスタンスにバインドされています。 236 | したがって、別のコンテキストで参照する必要がある場合は、 `this` が`component`として使用できることを確認してください。 237 | 238 | 言い換えれば: `const self = this;`のようなコーディングはもう **しないで** ください。 Vueコンポーネントの使用は安全です。 239 | 240 | ### 理由 241 | 242 | * ES6を使っている場合、`this`を変数に保存しておく必要はありません。 243 | * 通常、アロー関数を使用すれば静的スコープは保持されます。 244 | * ES6を使用して**いない**ために、`アロー関数`を使用できない場合は、`this`を変数に格納する必要があります。それが唯一の例外です。 245 | 246 | ### 方法 247 | 248 | ```html 249 | 261 | 262 | 263 | 276 | ``` 277 | 278 | [↑ 目次に戻る](#目次) 279 | 280 | 281 | ## コンポーネント構成 282 | 283 | 論理的に考えやすく、思考の流れに従いやすいようにしましょう. 方法を見てください。 284 | 285 | ### 理由 286 | 287 | * コンポーネントを明確かつグループ化されたオブジェクトとすることで、コードを読みやすくし、開発者はコードの基準を簡単に持てるようになります。 288 | * props、data、computed、watches、そしてmethodsをアルファベット順に並べることで、見つけやすくなります。 289 | * 繰り返しになりますが, コンポーネントをグループ化することで読みやすくなります (name、extends、props、dataそしてcomputed、components、 watch、methods、lifecycle methods、など); 290 | * `name`属性を使いましょう. [vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en)とname属性を使うと、開発/テストが容易になります。 291 | * [BEM](https://medium.com/tldr-tech/bem-blocks-elements-and-modifiers-6b3b0af9e3ea#.bhnomd7gw)、または [rscss](https://github.com/rstacruz/rscss)のようなCSSの命名方法論を使いましょう。 - [詳細?](#スタイルスコープとしてコンポーネント名を使用する); 292 | * Vue.jsの製作者Evan Youが推奨するように、テンプレートスクリプト形式の.vueファイル構成を使用しましょう。 293 | 294 | ### 方法 295 | 296 | コンポーネンのト構成: 297 | 298 | ```html 299 | 304 | 305 | 330 | 331 | 334 | ``` 335 | 336 | [↑ 目次に戻る](#目次) 337 | 338 | ## コンポーネントイベント名 339 | 340 | Vue.jsはすべてのVueハンドラ関数を提供し、式はViewModelに厳密にバインドされています。各コンポーネントのイベントは、開発中の問題を回避するような良い名前付けのスタイルを適用しましょう。 以下の **理由** を参照してください。 341 | 342 | ### 理由 343 | 344 | * 開発者は好きなイベント名を自由に使うことができるため、混乱を招く可能性があります。 345 | * イベントに名前をつける自由は、 [DOMテンプレートの非互換性](https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats)につながる可能性があります。 346 | 347 | ### 方法 348 | 349 | * イベント名前はケバブケースにするべきです。 350 | * あなたのコンポーネントで外部で関心を持つ独自のアクションのため、upload-success、upload-error、さらにはdropzone-upload-success、 dropzone-upload-errorのような固有の名前をつける必要があります。(スコープ付きプレフィックスを使用する必要がある場合は) 351 | * イベント名は末尾が不定形の動詞(例 client-api-load)、または名詞(例 drive-upload-success)で終わるべきです。([出典](https://github.com/GoogleWebComponents/style-guide#events)); 352 | 353 | [↑ 目次に戻る](#目次) 354 | 355 | ## `this.$parent`を避ける 356 | 357 | Vue.jsは、親コンテキストにアクセスできるネストされたコンポーネントをサポートしています。 あなたのVueコンポーネントの外部のコンテキストにアクセスすることは、 [モジュールベースの開発](#module-based-development)の[FIRST](https://addyosmani.com/first/)のルールに違反するため、 ** `this.$parent`の使用を避ける ** べきです。 358 | 359 | ### 理由 360 | 361 | * vueコンポーネントは、他のコンポーネントと同様に、独立して動作する必要があります。 コンポーネントがその親にアクセスする必要がある場合、このルールは壊されます。 362 | * コンポーネントがその親にアクセスする必要がある場合、別のコンテキストで再利用することはできません。 363 | 364 | ### 方法 365 | 366 | * 属性/プロパティを使用して、親から子コンポーネントに値を渡します。 367 | * 属性の式のコールバックを使用して、親コンポーネントで定義されたメソッドを子コンポーネントに渡します。 368 | * 子コンポーネントからイベントを発行し、それを親コンポーネントでキャッチします。 369 | 370 | [↑ 目次に戻る](#目次) 371 | 372 | ## `this.$refs`は注意して使用する 373 | 374 | Vue.jsは`ref`属性を介して他のコンポーネントや、基本的なHTML要素のコンテキストにアクセスできるコンポーネントをサポートしています。この属性は`this.$refs`を介して、コンポーネントまたDOM要素のコンテキストにアクセス可能な方法を提供します。ほとんどの場合、 `this.$refs`を介して **他のコンポーネント** のコンテキストにアクセスする必要性は避けることができます。このため、間違ったコンポーネントAPIを避けるためにこれを使用するときは注意が必要です。 375 | 376 | ### 理由 377 | 378 | * vueコンポーネントは、他のコンポーネントと同様に、**独立して動作する必要があります**。 コンポーネントが必要なすべてのアクセスをサポートしていない場合、それは悪い設計/実装です。 379 | * ほとんどのコンポーネントでは、プロパティとイベントで十分です。 380 | 381 | ### 方法 382 | 383 | * 良いコンポーネントAPIを作りましょう。 384 | * 独創的なコンポーネントの目的に常に注意してください。 385 | * 特殊なコードを書かないでください。ジェネリックコンポーネント内に特殊なコードを記述する必要がある場合は、APIが十分に一般的でないか、他のケースを管理するために新しいコンポーネントが必要になるということです。 386 | * すべてのpropsをチェックして、欠けているものがあるかどうか確認します。 もしあれば、課題を作成するかあなたのコンポーネントを強化しましょう。 387 | * すべてのイベントをチェックしましょう。ほとんどのケースで、開発者は子-親のコミュニケーション(イベント)が必要であることを忘れてしまいます。 そのため、(propsを使用した)親-子のコミュニケーションだけを覚えているのです。 388 | * **Propsは下へ、eventsは上へ!** ゴールとして良いAPIと分離を要求された場合、コンポーネントをアップグレードしましょう。 389 | * propsやeventsが消耗し、コンポーネントでの`this.$refs`の利用が利にかなっているときは、それを使用するべきです。 (下の例を参照してください). 390 | * データバインディングやディレクティブで要素を操作できない場合、 (`jQuery`, `document.getElement*`, `document.queryElement`の代わりに) `this.$refs`を使用してDOM要素にアクセスすることは良い方法です。 391 | 392 | ```html 393 | 394 | 398 | ``` 399 | 400 | ```html 401 | 402 | 403 |

Basic Modal

404 | 405 |
406 | 407 | 408 | 409 | 414 | 415 | 434 | 435 | ``` 436 | 437 | ```html 438 | 439 | 445 | 446 | 457 | ``` 458 | 459 | [↑ 目次に戻る](#目次) 460 | 461 | 462 | ## スタイルスコープとしてコンポーネント名を使用する 463 | 464 | Vue.jsのコンポーネント要素は、スタイルスコープのルートとして非常によく使用されるカスタム要素です。 465 | あるいは、コンポーネント名はCSSクラスネームスペースとして、使用できます。 466 | 467 | ### 理由 468 | 469 | * コンポーネント要素のスタイルをスコープすると、コンポーネントの外にスタイルが漏れるのを防ぐため、予測可能性が向上します。 470 | 471 | * モジュールディレクトリに同じ名前を使用すると、Vue.jsコンポーネントとスタイルルートが同じところに属していることを開発者が理解しやすくなります。 472 | 473 | ### 方法 474 | 475 | BEMとOOCSSに基づくネームスペースプレフィックスとしてコンポーネント名を使いましょう。 **そして** スタイルクラスで`scoped`属性を使いましょう。 476 | `scoped`を使用すると、` 488 | ``` 489 | 490 | [↑ 目次に戻る](#目次) 491 | 492 | 493 | ## コンポーネントAPIをドキュメント化する 494 | 495 | Vue.jsコンポーネントのインスタンスは、アプリケーション内のコンポーネント要素を使用して作成されます。インスタンスはそのカスタム属性によって構成されます。他の開発者がコンポーネントを使用するときのため、これらのカスタム属性(コンポーネントのAPI)を`README.md`ファイルに記述しましょう。 496 | 497 | ### 理由 498 | 499 | * ドキュメンテーションは、開発者に、そのコードのすべてを伝えることなく、コンポーネントの概要を高レベルで表示します。これにより、コンポーネントのアクセスが容易になり、使いやすくなります。 500 | * コンポーネントのAPIは、それを構成するカスタム属性のセットです。したがって、これらは、コンポーネントを使用する(開発しない)開発者にとって特に重要です。 501 | * ドキュメンテーションはAPIを形式化し、コンポーネントのコードを変更するときに下位互換性を維持する機能を開発者に教えます。 502 | * `README.md`は最初に読み込まれるドキュメントのデファクトスタンダードファイル名です。 コードリポジトリホスティングサービス(Github、Bitbucket、Gitlabなど)は、ソースディレクトリを参照するときに、READMEファイルの内容を直接表示します。これは私たちのモジュールディレクトリにも当てはまります。 503 | 504 | ### 方法 505 | 506 | コンポーネントのモジュールディレクトリに`README.md`ファイルを追加しましょう。 507 | 508 | ``` 509 | range-slider/ 510 | ├── range-slider.vue 511 | ├── range-slider.less 512 | └── README.md 513 | ``` 514 | 515 | READMEファイルに、モジュールの機能と使用方法を記述しましょう。 vueコンポーネントの場合、APIとしてサポートされているカスタム属性を記述するのが最も役立ちます。 516 | 517 | 518 | # Range slider 519 | 520 | ## 機能 521 | 522 | range sliderは、スライダーレールのハンドルを開始値と終了値の両方でドラッグして数値範囲を設定できます。 523 | 524 | このモジュールはクロスブラウザとタッチサポートのため、noUiSliderを使用します。 525 | 526 | ## 使用方法 527 | 528 | `` 次のカスタムコンポーネント属性をサポートしています: 529 | 530 | | 属性 | 型 | 説明 531 | | --- | --- | --- 532 | | `min` | 数値 | レンジの始まりの数値 (下限)。 533 | | `max` | 数値 | レンジの終わりの数値 (上限). 534 | | `values` | 数値[] *任意* | 開始値と終了値を含む配列。 例. `values="[10, 20]"`. デフォルトは`[opts.min, opts.max]`. 535 | | `step` | 数値 *任意* | インクリメント/デクリメントの数値。デフォルトは1。 536 | | `on-slide` | 関数 *任意* | ユーザーが開始(`HANDLE == 0`)または終了(`HANDLE == 1`)ハンドルをドラッグしているときに、`(values, HANDLE)`で呼び出される関数。例. `on-slide={ updateInputs }` `component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }`. 537 | | `on-end` | 関数 *任意* | ユーザーがハンドルのドラッグを停止したとき、`(values, HANDLE)`で呼び出される関数。 538 | 539 | スライダの外観をカスタマイズするには[noUiSliderドキュメントのStylingセクション](http://refreshless.com/nouislider/more/#section-styling)を参照してください。 540 | 541 | 542 | [↑ 目次に戻る](#目次) 543 | 544 | 545 | ## コンポーネントデモの追加 546 | 547 | 構成の異なるコンポーネントのデモを含むindex.htmlファイルを追加し、コンポーネントの使用方法を示しましょう。 548 | 549 | ### 理由 550 | 551 | * コンポーネントのデモは、コンポーネントが単独で動作することを示します。 552 | * コンポーネントのデモは、ドキュメンテーションやコードを掘り起こす前に、開発者にプレビューを提供します。 553 | * デモでは、コンポーネントを使用できるすべての可能な構成とバリエーションを示すことができます。 554 | 555 | [↑ 目次に戻る](#目次) 556 | 557 | 558 | ## コンポーネントファイルをLintする 559 | 560 | Lintersはコードの一貫性を高め、構文エラーの追跡に役立ちます。.vueファイルはプロジェクトに`eslint-plugin-html`を追加してlintすることができます。vue-cliを使用すれば、ESLintをデフォルトで有効にしてプロジェクトを開始できます。 561 | 562 | ### 理由 563 | 564 | * コンポーネントファイルのLintは、すべての開発者が同じコードスタイルを使用するようにします。 565 | * コンポーネントファイルのLintは、遅くなる前に構文エラーの追跡をするのに役立ちます。 566 | 567 | ### 方法 568 | 569 | lintersがあなたの`*.vue`ファイルからスクリプトを抽出するためには, [スクリプトを` 134 | 135 | 136 | 141 | ``` 142 | 143 | [↑ 목차로 돌아가기](#목차) 144 | 145 | 146 | ## 컴포넌트 props를 원시 자료형으로 사용하기 147 | 148 | Vue.js는 다양한 속성을 통해 복잡한 JavaScript 객체를 전달할 수 있지만 **컴포넌트 옵션을 가능한 원시 자료형으로 유지하는 것이 좋습니다**. 즉, [JavaScript 원시 값](https://developer.mozilla.org/ko/docs/Glossary/Primitive) (string, number, boolean) 및 함수만을 사용하고 복잡한 Object는 피하는게 좋습니다. 149 | 150 | ### 왜 그렇게 하나요? 151 | 152 | * 개별적으로 `prop` 속성을 사용함으로써 컴포넌트는 명확한 API를 가집니다. 153 | * 원시 자료형과 함수만을 `props` 값으로 사용하면 컴포넌트 API가 네이티브 HTML(5) 엘리먼트의 API와 유사해집니다. 154 | * 개별적으로 `prop` 속성을 사용하면 다른 개발자가 컴포넌트 인스턴스로 전달되는 내용을 쉽게 이해할 수 있습니다. 155 | * 복잡한 Object를 전달할 때 전달한 Object의 속성과 메서드가 실제로 사용자 정의 컴포넌트에서 사용되는지 분명하지 않습니다. 이렇게 사용하면 코드를 리팩토링하기가 어려워지고 코드가 더러워 질 수 있습니다. 156 | 157 | ### 어떻게 하나요? 158 | 159 | 원시 자료형 혹은 함수를 사용하여 `props` 컴포넌트 속성을 사용하세요. 160 | 161 | ```html 162 | 163 | 170 | 171 | 172 | 173 | 174 | ``` 175 | 176 | [↑ 목차로 돌아가기](#목차) 177 | 178 | 179 | ## 컴포넌트 props를 잘 사용하기 180 | 181 | Vue.js에서는 컴포넌트 props가 당신의 API 입니다. 강력하고 예측가능한 API를 만들면 다른 개발자가 컴포넌트를 쉽게 사용할 수 있습니다. 182 | 183 | 컴포넌트 props는 사용자 정의 HTML 어트리뷰트에 의해 전달됩니다. 이러한 어트리뷰트의 값은 Vue.js 일반 문자열(`:attr="value"` 또는 `v-bind:attr="value"`)이거나 누락됩니다. 당신은 이러한 경우를 고려하여 **당신의 컴포넌트 props를 잘 사용해야 합니다**. 184 | 185 | ### 왜 그렇게 하나요? 186 | 187 | 컴포넌트 props를 잘 사용하면 당신의 컴포넌트는 항상 작동할 것 입니다(방어적 프로그래밍). 나중에 다른 개발자가 당신이 생각하지 못한 방법으로 컴포넌트를 사용하더라도 마찬가지 입니다. 188 | 189 | ### 어떻게 하나요? 190 | 191 | * props에 기본 값을 사용하세요. 192 | * 값을 [validate](https://kr.vuejs.org/v2/guide/components.html#Prop-검증) 하기위해 `type` 옵션을 사용하세요. **[1\*]** 193 | * 중복된 `props`가 있는지 확인하세요. 194 | 195 | ```html 196 | 199 | 217 | ``` 218 | 219 | [↑ 목차로 돌아가기](#목차) 220 | 221 | 222 | ## `this`를 `component`에 지정하기 223 | 224 | Vue.js 컴포넌트 엘리먼트의 컨텍스트 내에서 `this`는 컴포넌트 인스턴스에 바인딩됩니다. 225 | 그러므로 다른 컨텍스트에서 그것을 참조할 필요가 있을 때 `this`를 `component`로써 사용 가능합니다. 226 | 227 | 다른 말로하면 더이상 `const self = this;`와 같은 코드를 **사용하지 마세요**. Vue 컴포넌트를 사용하면 안전합니다. 228 | 229 | ### 왜 그렇게 하나요? 230 | 231 | * `this`를 `component`라는 변수에 지정됨으로써 개발자에게 변수가 사용되는 곳마다 컴포넌트 인스턴스에 바인딩되었다는 것을 알려줍니다. 232 | 233 | ### 어떻게 하나요? 234 | 235 | ```html 236 | 248 | 249 | 250 | 263 | ``` 264 | 265 | [↑ 목차로 돌아가기](#목차) 266 | 267 | 268 | ## 컴포넌트 구조 269 | 270 | 생각의 순서를 따라 컴포넌트 구조를 만들어보세요. `어떻게 하나요?`를 참고하세요. 271 | 272 | ### 왜 그렇게 하나요? 273 | 274 | * 컴포넌트를 명확하고 그룹화하여 `export`하면 개발자가 쉽게 표준적인 코드에 대해서 이해하고 코드를 작성할 수 있습니다. 275 | * 속성, 데이터, 계산된 속성, 감시자 및 메서드를 알파벳순으로 표시하면 쉽게 찾을 수 있습니다. 276 | * 다시말해, 그룹화하면 컴포넌트를 더 쉽게 읽을 수 있습니다. (name; extends; props; data와 computed; components; watch와 method; 라이프사이클 메서드 등) 277 | * `name` 속성을 사용하세요. [vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en)과 그 속성을 사용하면 개발/테스트가 더 쉬워집니다. 278 | * [BEM](https://medium.com/tldr-tech/bem-blocks-elements-and-modifiers-6b3b0af9e3ea#.bhnomd7gw) 또는 [rscss](https://github.com/rstacruz/rscss)와 같은 CSS 네이밍 규칙을 사용하세요. - [자세히 보기](#범위-스타일에-컴포넌트-이름-사용하기) 279 | * Vue.js 작성자(Evan You)가 권장하는 템플릿 스크립트 스타일인 .vue 파일을 사용하십시오. 280 | 281 | ### 어떻게 하나요? 282 | 283 | 아래 컴포넌트 구조를 참고하세요. 284 | 285 | ```html 286 | 291 | 292 | 317 | 318 | 321 | ``` 322 | 323 | [↑ 목차로 돌아가기](#목차) 324 | 325 | ## 컴포넌트 이벤트 이름 326 | 327 | Vue.js는 모든 Vue 핸들러 함수를 제공하며 표현식은 ViewModel에 엄격하게 바인딩됩니다. 각 컴포넌트 이벤트는 개발 도중 문제를 피할 수있는 좋은 네이밍 스타일을 따라야합니다. 아래 **왜 그렇게 하나요?**를 참조하십시오. 328 | 329 | ### 왜 그렇게 하나요? 330 | 331 | * 개발자가 이벤트 이름을 자유롭게 작성할 경우 혼란을 발생시킬 수 있습니다. 332 | * 이벤트 이름을 자유롭게 작성할 수 있기 때문에 [DOM 템플릿의 비 호환성](https://kr.vuejs.org/v2/guide/components.html#DOM-템플릿-구문-분석-경고)이 발생할 수 있습니다. 333 | 334 | ### 어떻게 하나요? 335 | 336 | * 이벤트 이름은 `kebab-cased`여야 합니다(하이픈으로 구분). 337 | * 특별한 이벤트 이름은 `upload-success`, `upload-error` 또는 `dropzone-upload-success`, `dropzone-upload-error`(만약 범위가 지정된 접두어가 필요하다면)와 같이 외부 세계에 관심을 가질 수 있는 컴포넌트의 특별한 동작에 대해 실행되야 합니다. 338 | * 이벤트는 부정사의 형태(e.g. client-api-load)이거나 명사(e.g. drive-upload-success)에서 동사로 끝나야 합니다. ([출처](https://github.com/GoogleWebComponents/style-guide#events)) 339 | 340 | [↑ 목차로 돌아가기](#목차) 341 | 342 | ## `this.$parent` 피하기 343 | 344 | Vue.js는 부모 컨텍스트에 접근 할 수 있는 중첩 컴포넌트를 지원합니다. 하지만 Vue 컴포넌트 외부의 컨텍스트에 접근하면 [컴포넌트 기반 개발](#module-based-development)의 [FIRST](https://addyosmani.com/first/) 규칙을 위반하게 됩니다. 따라서 **`this.$parent`를 사용을 피해야합니다**. 345 | 346 | ### 왜 그렇게 하나요? 347 | 348 | * Vue 컴포넌트는 다른 모든 컴포넌트와 마찬가지로 독립적으로 작동해야합니다. 컴포넌트가 부모에 접근해야할 경우 이 규칙은 무너지게 됩니다. 349 | * 컴포넌트가 부모에 접근하는 경우 다른 곳에서 재사용할 수 없습니다. 350 | 351 | ### 어떻게 하나요? 352 | 353 | * 어트리뷰트/프로퍼티를 사용하여 부모에서 자식 컴포넌트로 값을 전달합니다. 354 | * 어트리뷰트 표현식에서 콜백을 사용하여 부모 컴포넌트에 정의된 메소드를 자식 컴포넌트로 전달하십시오. 355 | * 자식 컴포넌트에서 이벤트를 `emit`하여 부모 컴포넌트에서 이벤트를 발생시킵니다. 356 | 357 | [↑ 목차로 돌아가기](#목차) 358 | 359 | ## `this.$refs`를 주의하여 사용하기 360 | 361 | Vue.js는 컴포넌트가 `ref` 어트리뷰트를 통해 다른 컴포넌트와 기본 HTML 엘리먼트에 접근 할 수 있도록 지원합니다. 이 어트리뷰트는 `this.$refs`를 통해 컴포넌트 또는 DOM 엘리먼트에 접근 할 수 있게 해줍니다. 대부분의 경우 `this.$refs`를 통해 **다른 컴포넌트**에 접근하는 것을 피할 수 있습니다. 이것은 잘못된 컴포넌트 API를 피하기 위해서 사용할 때 주의해야합니다. 362 | 363 | ### 왜 그렇게 하나요? 364 | 365 | * Vue 컴포넌트는 **독립적으로 작동해야합니다**. 컴포넌트가 필요한 모든 접근을 지원하지 않으면 잘못 설계/구현된 것 입니다. 366 | * 대부분의 컴포넌트는 프로퍼티와 이벤트가 충분해야합니다. 367 | 368 | ### 어떻게 하나요? 369 | 370 | * 좋은 컴포넌트 API를 작성합니다. 371 | * 항상 컴포넌트의 목적에 벗어나지 않도록 코드를 작성합니다. 372 | * 특정한 코드(예: 특정 디바이스에 관한 코드)를 쓰지 마십시오. 일반적인 컴포넌트 내에 특정한 코드를 작성해야하는 경우 해당 API가 충분히 일반적인 것이 아니거나 새 컴포넌트가 필요할 수도 있음을 의미합니다. 373 | * `props`를 모두 검사하여 놓친 부분이 있는지 확인하세요. 만약 놓친 부분이 있다면 이슈를 만들거나 직접 컴포넌트를 수정하세요. 374 | * 모든 이벤트를 확인하세요. 대부분의 경우 개발자는 자식에서 부모로의 통신(이벤트)하는 것이 필요하다는 것을 잊었습니다. 그 이유는 부모에서 자식으로의 통신(`props` 사용)만 기억하기 때문입니다. 375 | * **`props`는 아래로, 이벤트는 위로!** 좋은 API와 분리가 필요할 때 당신의 컴포넌트를 개선하세요. 376 | * `props`와 이벤트를 사용하기 힘들고 `ref`를 사용하는 것에 의미가 있는 경우 컴포넌트에 `this.$refs`를 사용해야 합니다. (아래 예제를 참고하세요) 377 | * 엘리먼트를 데이터 바인딩이나 디렉티브로 조작할 수 없는 경우 DOM 엘리먼트에 접근하기 위해 `jQuery`, `document.getElement*`, `document.queryElement`를 사용하는 대신 `this.$refs`를 사용하는 것은 좋은 방법입니다. 378 | 379 | ```html 380 | 381 | 385 | ``` 386 | 387 | ```html 388 | 389 | 390 |

Basic Modal

391 | 392 |
393 | 394 | 395 | 396 | 401 | 402 | 421 | ``` 422 | 423 | ```html 424 | 425 | 431 | 432 | 443 | ``` 444 | 445 | [↑ 목차로 돌아가기](#목차) 446 | 447 | 448 | ## 범위 스타일에 컴포넌트 이름 사용하기 449 | 450 | Vue.js 컴포넌트 엘리먼트는 범위 스타일의 루트로 잘 사용 될 수 있는 사용자 지정 엘리먼트입니다. 451 | 또한 컴포넌트 이름을 CSS 클래스 네임스페이스로 사용할 수 있습니다. 452 | 453 | ### 왜 그렇게 하나요? 454 | 455 | * 컴포넌트에 범위 스타일을 적용하면 컴포넌트 외부에 스타일이 적용되지 않으므로 예측 가능성이 향상됩니다. 456 | * Vue.js 컴포넌트와 스타일의 루트 이름를 모듈 디렉토리와 동일한 이름으로 사용하면 개발자가 이해하기 좀 더 쉽습니다. 457 | 458 | ### 어떻게 하나요? 459 | 460 | BEM 및 OOCSS에 기반한 네임스페이스 접두어로 컴포넌트 이름을 사용하고 `style`에 `scoped` 어트리뷰트를 사용하세요. 461 | `scoped`를 사용하면 Vue 컴파일러는 ` 473 | ``` 474 | 475 | [↑ 목차로 돌아가기](#목차) 476 | 477 | 478 | ## 컴포넌트 API를 문서화 하기 479 | 480 | Vue.js 컴포넌트 인스턴스는 어플리케이션 내부의 컴포넌트 엘리먼트를 사용하여 만듭니다. 인스턴스는 사용자 정의 어트리뷰트를 통해 구성됩니다. 다른 개발자가 컴포넌트를 사용하는 경우 이러한 사용자 지정 어트리뷰트(컴포넌트의 API)를 `README.md` 파일에 문서화해야합니다. 481 | 482 | ### 왜 그렇게 하나요? 483 | 484 | * 문서는 개발자가 코드 전체를 검토할 필요 없이 컴포넌트에 대한 간략한 개요를 제공합니다. 문서를 만들면 컴포넌트를 쉽게 접근하고 사용할 수 있습니다. 485 | * 컴포넌트의 API는 사용자 지정 어트리뷰트의 집합을 통해 구성됩니다. 그러므로 이것들은 컴포넌트를 사용하기 원하는 (다시 개발하지 원치 않는) 다른 개발자들에게 중요합니다. 486 | * 문서는 API를 형식을 갖추게하고 개발자에게 컴포넌트의 코드를 수정할 때 하위 호환성을 유지할 수 있도록 돕습니다. 487 | * `README.md`는 먼저 읽어야할 문서를 위한 사실상 표준적인 파일명입니다. 코드 저장소를 호스팅하는 서비스(Github, Bitbucket, Gitlab 등)는 소스 디렉토리를 탐색할 때 README.md 파일의 내용을 표시합니다. 이것은 모듈 디렉토리에도 똑같이 적용됩니다. 488 | 489 | ### 어떻게 하나요? 490 | 491 | `README.md` 문서를 컴포넌트의 모듈 디렉토리에 추가하세요. 492 | 493 | ``` 494 | range-slider/ 495 | ├── range-slider.vue 496 | ├── range-slider.less 497 | └── README.md 498 | ``` 499 | 500 | `README.md` 파일에서 모듈의 기능 및 사용법을 적으세요. Vue 컴포넌트의 경우 API와 마찬가지로 지원하는 사용자 정의 어트리뷰트에 대해서 설명하는 것이 좋습니다. 501 | 502 | 503 | # 범위 슬라이더 504 | 505 | ## 기능 506 | 507 | 범위 슬라이더를 사용하면 슬라이더 핸들을 드래그하여 시작과 끝 값내에 값을 설정할 수 있습니다. 508 | 509 | 이 모듈은 크로스 브라우징 및 터치 지원을 위해서 [noUiSlider](http://refreshless.com/nouislider/)를 사용합니다. 510 | 511 | ## 사용 방법 512 | 513 | ``는 다음과 같은 사용자 정의 컴포넌트 어트리뷰트를 지원합니다 : 514 | 515 | | 어트리뷰트 | 타입 | 설명 516 | | --- | --- | --- 517 | | `min` | Number | 범위가 시작되는 값 (최소값). 518 | | `max` | Number | 범위가 끝나는 값 (최대값). 519 | | `values` | Number[] *optional* | 시작과 끝값을 포함하는 배열. 예) `values="[10, 20]"`. 기본값은 `[opts.min, opts.max]` 입니다. 520 | | `step` | Number *optional* | 숫자를 증가/감소 시킬 값. 기본값은 1입니다. 521 | | `on-slide` | Function *optional* | 사용자가 시작(`HANDLE == 0`) 또는 끝(`HANDLE == 1`)에 핸들을 위치하면 호출되는 함수힙니다. 예) `on-slide={ updateInputs }`, `component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }`. 522 | | `on-end` | Function *optional* | 사용자가 핸들 드래그를 멈추면 `(values, HANDLE)` 함수가 호출됩니다. 523 | 524 | 슬라이더 모양을 사용자 정의하려면 [noUiSlider 문서의 Styling 섹션](http://refreshless.com/nouislider/more/#section-styling)을 참고하세요. 525 | 526 | [↑ 목차로 돌아가기](#목차) 527 | 528 | 529 | ## 컴포넌트 예제 추가하기 530 | 531 | `index.html` 파일을 추가하여 컴포넌트의 사용 방법을 보여줍니다. 532 | 533 | ### 왜 그렇게 하나요? 534 | 535 | * 컴포넌트 예제는 컴포넌트가 독립적으로 작동함을 증명합니다. 536 | * 컴포넌트 예제를 작성하면 개발자가 문서 또는 코드를 살펴보기 전에 작동 모습을 확인 할 수 있습니다. 537 | * 컴포넌트 예제는 컴포넌트를 사용할 수 있는 모든 설정을 보여줍니다. 538 | 539 | [↑ 목차로 돌아가기](#목차) 540 | 541 | 542 | ## 컴포넌트 파일을 Lint하기 543 | 544 | Lint는 코드 일관성을 개선하고 구문 오류를 추적하는 것을 도와줍니다. `.vue` 파일은 프로젝트에 `eslint-plugin-html`을 당신의 프로젝트에 추가할 수 있습니다. 만약 사용하길 원하면 당신은 `vue-cli`를 사용하여 ESLint가 활성화된 프로젝트를 시작할 수 있습니다. 545 | 546 | ### 왜 그렇게 하나요? 547 | 548 | * 컴포넌트 파일을 Lint하면 모든 개발자가 동일한 코드 스타일을 작성할 수 있도록 보장합니다. 549 | * 컴포넌트 파일을 Lint하면 구문 오류를 빠르게 수정할 수 있습니다. 550 | 551 | ### 어떻게 하나요? 552 | 553 | Lint가 `*.vue` 파일에서 스크립트를 추출할 수 있도록 하려면 [스크립트를 컴포넌트의 ` 137 | 138 | 139 | 144 | ``` 145 | 146 | [↑ voltar para o Índice](#indice) 147 | 148 | 149 | ## Mantenha `props` primitivas 150 | 151 | Enquanto Vue.js suporta passar objetos complexos em JavaScript via esses atributos, você deveria tentar **manter as `props` mais primitivas possíveis**. Tente usar somente [primitivas JavaScript](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) (strings, numbers, booleans) e functions. Evite objetos complexos. 152 | 153 | ### Porque? 154 | 155 | * Usando um atributo para cada props separadamente, torna o componente com uma API mais expressiva; 156 | * Usando somente primitivas e funções como props, a API do seu componente torna-se similar com a API nativa de elementos HTML(5); 157 | * Usando um atributo para cada prop, outros desenvolvedores podem facilmente entender o que é passado para a instância do componente; 158 | * Quando objetos complexos forem passados, não é aparente quais propriedades e métodos do objetos são realmente usados pelo componente. Isso torna a refatoração mais difícil e pode levar a má práticas. 159 | 160 | ### Como? 161 | 162 | Use um atributo por prop usando primitivas ou funções como valor: 163 | 164 | ```html 165 | 166 | 173 | 174 | 175 | 176 | 177 | ``` 178 | 179 | [↑ voltar para o Índice](#indice) 180 | 181 | 182 | ## Pense bem nas `props` do seu componente 183 | 184 | Em Vue.js, props são a API dos componentes. Uma API robusta e previsível torna o componente fácil de usar por outros desenvolvedores. 185 | 186 | As props dos componentes são passados via atributos HTML. Os valores desses atributos em Vue.js podem ser `:attr="value"` ou `v-bind:attr="value"` ou nunca ser usado. Você deveria **pensar bem nas `props` do seu componente** para permitir casos variados. 187 | 188 | ### Porque? 189 | 190 | Gastar um tempo pensando sobre as props que o seu componente terá, garantirá que o seu componente sempre funcione (defensive programming). Pense neles, especialmente quando considerando o uso por outros desenvolvedores mais tarde que podem ter expectativas diferentes, props que vocês ainda nem pensou que a props do seu componente teria. 191 | 192 | ### Como? 193 | 194 | * Use valores defaults para suas props; 195 | * Use a opção `type` para [validar](http://vuejs.org/v2/guide/components.html#Prop-Validation) valores para um tipo esperado.**[1\*]**; 196 | * Cheque se a prop existe antes de usá-la. 197 | 198 | ```html 199 | 202 | 220 | ``` 221 | 222 | [↑ voltar para o Índice](#indice) 223 | 224 | 225 | ## `this` já é o seu componente 226 | 227 | Dentro do contexto de Vue.js, o `this` está ligado diretamente a instância do componente. Sendo assim, quando for preciso referenciá-lo em contexto diferente, 228 | garanta que o `this` está disponível como o próprio componente. 229 | 230 | Em outras palavras mais resumidas: **NÃO** codifique usando códigos como `const self = this;` mais. Você está salvo para usar o `this` diretamente dentro do componente Vue. 231 | 232 | ### Porque? 233 | 234 | * Usando `this` diretamente, significa para todos os desenvolvedores que ele é o próprio componente, podendo ser usado em todo o seu componente, facilitando o desenvolvimento. 235 | 236 | ### Como? 237 | 238 | ```html 239 | 251 | 252 | 253 | 266 | ``` 267 | 268 | [↑ voltar para o Índice](#indice) 269 | 270 | 271 | ## Estrutura do componente 272 | 273 | Faz com que seja fácil de entender e de seguir uma sequência de pensamentos. Veja o porque logo abaixo. 274 | 275 | ### Porque? 276 | 277 | * Fazendo com que o componente exporte um objeto limpo e bem programado, torna o código mais fácil para desenvolvedores entender e ter um padrão a seguir; 278 | * Ordenando alfabeticamente as props, data, computed, watches e methods faz com que o conteúdo do mesmo seja mais fácil de ser encontrado; 279 | * Agrupando o objeto exportado do componente com visão do que os atributos fazem, torna a leitura mais fácil de ler e mais fácil de ler e mais organizada (name; extends; props, data and computed; components; watch and methods; lifecycle methods, etc.); 280 | * Use o atributo `name`. Usando o [vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en) e este atributo, tornará seu componente mais fácil de desenvolver, debugar e testar; 281 | * Use metodologias de nomenclatura CSS, como [BEM](https://medium.com/tldr-tech/bem-blocks-elements-and-modifiers-6b3b0af9e3ea#.bhnomd7gw), ou [rscss](https://github.com/rstacruz/rscss) - [details?](#use-o-nome-do-componente-como-escopo-para-o-style); 282 | * Use a ordem **template-script-style** na organização dos seus arquivos .vue, como é recomendado pelo Evan You, criador do Vue.js. 283 | 284 | ### Como? 285 | 286 | Estrutura do componente: 287 | 288 | ```html 289 | 294 | 295 | 320 | 321 | 324 | ``` 325 | 326 | [↑ voltar para o Índice](#indice) 327 | 328 | ## Nome de eventos do componente 329 | 330 | Vue.js liga todas as funções e expressões estritamente ligadas ao ViewModel do componente. Cada um dos componentes deve seguir uma boa nomenclatura que evitará problemas durante o desenvolvimento. Continue lendo. 331 | 332 | ### Porque? 333 | 334 | * Desenvolvedores estão livres para usar nome de eventos nativos, e isso pode causar problemas com o tempo; 335 | * A liberdade para nomear eventos podem levar a [incompatibilidade de templates do DOM](https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats); 336 | 337 | ### Como? 338 | 339 | * Eventos devem ser nomeados usando kebab-cased; 340 | * Um único evento deve ser emitido para cada ação no seu componente que pode ser interessante como uma API, por exemplo: upload-success, upload-error ou até mesmo dropzone-upload-success, dropzone-upload-error (se você acha que ter um escopo como prefixo seja necessário); 341 | * Eventos devem terminar em verbos e usar a nomes no infinitivo (exemplo, client-api-load) ou usar substantivos (exemplo, drive-upload-success) ([source](https://github.com/GoogleWebComponents/style-guide#events)); 342 | 343 | [↑ voltar para o Índice](#indice) 344 | 345 | ## Evite `this.$parent` 346 | 347 | Vue.js suporta componentes aninhados, assim como acesso ao contexto do pai deste componente. Acessar escopo fora do componente em desenvolvimento viola a regra de [FIRST](https://addyosmani.com/first/) de [desenvolvimento baseado em componentes](#desenvolvimento-baseado-em-modulo). Sendo assim, você deveria **evitar `this.$parent`**. 348 | 349 | ### Porque? 350 | 351 | * Um componente Vue, como qualquer outro componente, deve funcionar isoladamente. Se um componente precisa acessar seu pai, essa regra é quebrada; 352 | * Se um componente precisa acessar o seu pai, ele não mais pode ser usado em outro contexto/aplicação. 353 | 354 | ### Como? 355 | 356 | * Passe os valores do pai para o componente via props; 357 | * Passe os métodos definidos no componente pai para o componente filho usando callbacks em expressões; 358 | * Emita eventos do componente filho e escute-os no componente pai. 359 | 360 | [↑ voltar para o Índice](#indice) 361 | 362 | ## Use `this.$refs` com cuidado 363 | 364 | Componente em Vue.js permite o acesso do contexto de outros componentes e elementos básicos HTML via o atributo `ref`. Este atributo proverá uma forma de acesso via `this.$refs` do contexto de um componente ou elemento DOM. Na maioria dos casos, a necessidade de acessar **o contexto de outros componentes** via `this.$refs` poderia ser evitado. O uso constante dessa tática levará a uma má API, visto que ele poderia ser usado. 365 | 366 | ### Porque? 367 | 368 | * Um componente deve **funcionar isoladamente**. Se um componente não dá suporte a todos os acessos necessários, provavelmente o componente foi mau implementado/desenvolvido; 369 | * Props e eventos devem ser o suficiente para a grande maioria dos componentes. 370 | 371 | ### Como? 372 | 373 | * Cria uma boa API para o componente; 374 | * Sempre foque na proposta que o componente está oferecendo; 375 | * Nunca escreva código muito específico. Se voce precisa escrever um código específico dentro de um componente genérico, significa que a API ainda não está genérica o suficiente ou talvez você precise de um outro componente; 376 | * Cheque todas as props para ver se falta alguma coisa. Se esse for o caso, melhore-o ou crie uma issue com a proposta de melhoria; 377 | * Cheque todos os eventos. Na maioria dos casos, desenvolvedores esquecem a comunicação entre Pai-Filho (eventos); 378 | * **Props down, events up!** Melhore o seu componente quando for necessário com uma boa API e tenha isolamento como um objetivo; 379 | * Usando `this.$refs` em componentes, deveria ser usado somente quando props e eventos não podem mais ser usados ou quando faz mais sentido (veja o exemplo abaixo); 380 | * Usando `this.$refs` para acessar elementos DOM (ao invés de usar `jQuery`, `document.getElement*`, `document.queryElement`) é tranquilo, quando o elemento não pode ser manipulado com data binding ou com uma diretiva. 381 | 382 | ```html 383 | 384 | 388 | ``` 389 | 390 | ```html 391 | 392 | 393 |

Basic Modal

394 | 395 |
396 | 397 | 398 | 399 | 404 | 405 | 424 | 425 | ``` 426 | 427 | ```html 428 | 429 | 435 | 436 | 447 | ``` 448 | 449 | [↑ voltar para o Índice](#indice) 450 | 451 | 452 | ## Use o nome do componente como escopo para o ` 477 | ``` 478 | 479 | [↑ voltar para o Índice](#indice) 480 | 481 | 482 | ## Documente a API do seu componente 483 | 484 | A instância de um componente Vue.js é criada usando um elemento do componente que está dentro da sua aplicação. A instância é configurada através da configuração dos seus atributos. Para que o componente possa ser usado por outros desenvolvedores, esses atributos - a API do seu componente - devem ser documentados em um arquivo `README.md`. 485 | 486 | ### Porque? 487 | 488 | * Documentação provê aos desenvolvedores uma overview de alto nível, sem ter a necessidade de ler todo o código. Isso torna o componente mais acessível e fácil de usar; 489 | * Uma API de um componente é o conjunto de atributos. O interesse dessa API vem para desenvolvedores que querem usar (e não desenvolver) o componente; 490 | * Documentação formaliza a API e diz aos desenvolvedores quais as funcionalidades esperadas; 491 | * `README.md` é o nome de arquivo padrão para a primeira leitura de uma documentação. O serviço de repositório de código (Github, Bitbucket, Gitlab etc) mostram o conteúdo desses componentes, diretamente quando o usuário navega pelos diretórios. 492 | 493 | ### Como? 494 | 495 | Adicione um arquivo `README.md` ao diretório que contém o componente: 496 | 497 | ``` 498 | range-slider/ 499 | ├── range-slider.vue 500 | ├── range-slider.less 501 | └── README.md 502 | ``` 503 | 504 | Dentro do arquivo README, descreva a funcionaldiade e o uso desse módulo. Para um componente Vue.js é muito útil a descrição das props que ele suporta, pois essas compõem a API do componente. Exemplo: 505 | 506 | 507 | # Range slider 508 | 509 | ## Functionality 510 | 511 | The range slider lets the user to set a numeric range by dragging a handle on a slider rail for both the start and end value. 512 | 513 | This module uses the [noUiSlider](http://refreshless.com/nouislider/) for cross browser and touch support. 514 | 515 | ## Usage 516 | 517 | `` supports the following custom component attributes: 518 | 519 | | attribute | type | description 520 | | --- | --- | --- 521 | | `min` | Number | number where range starts (lower limit). 522 | | `max` | Number | Number where range ends (upper limit). 523 | | `values` | Number[] *optional* | Array containing start and end value. E.g. `values="[10, 20]"`. Defaults to `[opts.min, opts.max]`. 524 | | `step` | Number *optional* | Number to increment / decrement values by. Defaults to 1. 525 | | `on-slide` | Function *optional* | Function called with `(values, HANDLE)` while a user drags the start (`HANDLE == 0`) or end (`HANDLE == 1`) handle. E.g. `on-slide={ updateInputs }`, with `component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }`. 526 | | `on-end` | Function *optional* | Function called with `(values, HANDLE)` when user stops dragging a handle. 527 | 528 | For customising the slider appearance see the [Styling section in the noUiSlider docs](http://refreshless.com/nouislider/more/#section-styling). 529 | 530 | 531 | [↑ voltar para o Índice](#indice) 532 | 533 | 534 | ## Crie uma demonstração 535 | 536 | Adicione um `index.html` que tenha demonstrações do componente com configurações diferentes, mostrando como o componente deve ser usado. 537 | 538 | ### Porque? 539 | 540 | * Uma demonstração do componente prova que o componente funciona isoladamente; 541 | * Uma demonstração do componente dá aos desenvolvedores uma prévia antes de entrar na documentação ou no código; 542 | * Demonstrações ilustram todas as possíveis configurações e variações que um componente pode ser usado. 543 | 544 | [↑ voltar para o Índice](#indice) 545 | 546 | 547 | ## Lint os arquivos do seu componente 548 | 549 | Linters melhoram a consistência de código e ajudam a rastrear erros de sintaxe. Arquivos .vue podem usar Linters quando o plugin `eslint-plugin-html` for adicionado ao projeto. Se você quiser, você pode iniciar um projeto com o ESLInt ativado por padrão usando a ferramenta `vue-cli`; 550 | 551 | ### Porque? 552 | 553 | * Arquivos que usam Lint garantem que todos os desenvolvedores usem o mesmo estilo de código; 554 | * Arquivos que usam Lint ajudam no rastreio de erros antes que seja tarde demais. 555 | 556 | ### Como? 557 | 558 | Para fazer com que linters extraiam o script dos seus arquivos `*.vue`, configure o seu linter para acessar variáveis globais `vue` e props de componentes. 559 | 560 | #### ESLint 561 | 562 | [ESLint](http://eslint.org/) requer um [plugin ESLint HTML](https://github.com/BenoitZugmeyer/eslint-plugin-html#eslint-plugin-html) para extrair o script de um componente. 563 | 564 | Configure o ESLint em um arquivo `.eslintrc` (para que IDEs possam interpretá-lo bem): 565 | ```json 566 | { 567 | "extends": "eslint:recommended", 568 | "plugins": ["html"], 569 | "env": { 570 | "browser": true 571 | }, 572 | "globals": { 573 | "opts": true, 574 | "vue": true 575 | } 576 | } 577 | ``` 578 | 579 | Rode o ESLint 580 | ```bash 581 | eslint src/**/*.vue 582 | ``` 583 | 584 | #### JSHint 585 | 586 | [JSHint](http://jshint.com/) parsea o HTML (usando `--extra-ext`) e extrai o script (usando `--extract=auto`). 587 | 588 | Configure o JSHint em um arquivo `.jshintrc` (para que IDEs possam interpretá-lo bem): 589 | ```json 590 | { 591 | "browser": true, 592 | "predef": ["opts", "vue"] 593 | } 594 | ``` 595 | 596 | Rode os JSHint 597 | ```bash 598 | jshint --config módulos/.jshintrc --extra-ext=html --extract=auto módulos/ 599 | ``` 600 | Nota: JSHint não aceita as expressões `vue`, porém aceita as de `html`. 601 | 602 | [↑ voltar para o Índice](#indice) 603 | 604 | --- 605 | 606 | ## Quer ajudar? 607 | 608 | Faça um Fork do projeto e depois um Pull Request do que você acha que deve ser interessante ter nesse guia ou crie uma [Issue](https://github.com/pablohpsilva/vuejs-component-style-guide/issues/new). 609 | 610 | ## Sobre o tradutor 611 | 612 | Pablo Henrique Penha Silva 613 | 614 | - Github [pablohpsilva](https://github.com/pablohpsilva) 615 | - Twitter [@PabloHPSilva](https://twitter.com/PabloHPSilva) 616 | - Medium [@pablohpsilva](https://medium.com/@pablohpsilva) 617 | 618 | 619 | 620 | 659 | -------------------------------------------------------------------------------- /README-RU.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ### Переводы 6 | * [бразильский португальский](https://pablohpsilva.github.io/vuejs-component-style-guide/#/portuguese) 7 | * [английский](https://pablohpsilva.github.io/vuejs-component-style-guide/#) 8 | * [Японский](https://pablohpsilva.github.io/vuejs-component-style-guide/#/japanese) 9 | * [корейский язык](https://pablohpsilva.github.io/vuejs-component-style-guide/#/korean) 10 | * [китайский язык](https://pablohpsilva.github.io/vuejs-component-style-guide/#/chinese) 11 | 12 | Этот документ предлагает для вас ряд правил по разработке компонентов Vue которые: 13 | 14 | * потом будет легче для вашей команды (или для вас в будущем) понять или найти что и как работает 15 | * ваш редактор кода (IDE, среда разработки) поймет с меньшим количеством ошибок и предложит лучшие подсказки 16 | * улучшит переиспользование в данном проекте и в других ваших проектах 17 | * лучше кешируются и выделяются в отдельные компоненты 18 | 19 | ## Содержание 20 | 21 | * Модульная разработка 22 | * Наименование компонентов Vue 23 | * Выражения в компонентах должны быть простыми 24 | * Оставляйте свойства простыми 25 | * Правильно используйте свойства компонента 26 | * Определяйте `this` как `component` 27 | * Структура компонента 28 | * Именование событий 29 | * Избегайте `this.$parent` 30 | * Используйте `this.$refs` осторожно 31 | * Используйте ограниченные стили 32 | * Документируйте API компонента 33 | * Добавляйте демо 34 | * Форматируйте код файлов 35 | 36 | 37 | ## Модульная разработка 38 | 39 | Всегда старайтесь чтобы ваше приложение состояло из небольших модулей, каждый из которых умеет выполнять только одну функцию, но делает это хорошо. 40 | 41 | Модуль по определению это небольшая ограниченная часть приложения. "Строительный блок", самодостаточный функционально. Организация Vue позволяет создавать подобные модули ориентируясь на визуальные компоненты. 42 | 43 | ### Почему? 44 | 45 | Модули небольших размеров легче взять для использования - понять что они делают, дорабатывать или переиспользовать. И вам и всей вашей команде. 46 | 47 | ### Как? 48 | 49 | Старайтесь чтобы каждый Vue компонент соответствовал принципам [FIRST](https://addyosmani.com/first/): 50 | - решающий одну задачу, 51 | - независимый, 52 | - переиспользуемый, 53 | - небольшой, 54 | - простой в тестировании. 55 | 56 | [↑ наверх](#Содержание) 57 | 58 | 59 | 60 | ## Наименование компонентов Vue 61 | 62 | Имя каждого компонента должно соответствовать следующим критериям: 63 | 64 | * **Понятное**: в меру детальным, в меру абстрактным 65 | * **Короткое**: не более 2-3 слов 66 | * **Произносимое**: чтобы его можно было упомянуть в обсуждении 67 | 68 | ### Почему? 69 | 70 | * Имя компонента используется людьми и должно облегчать коммуникацию 71 | 72 | ### Как? 73 | 74 | ```html 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | ``` 85 | 86 | [↑ наверх](#Содержание) 87 | 88 | 89 | 90 | ## Выражения в компонентах должны быть простыми 91 | 92 | Вы можете использовать инлайн-выражения в шаблонах Vue - это самые обычные Javascript выражения. Они дают максимальную свободу и мощность, однако из-за этого они могут стать слишком сложными. Не злоупотребляйте этим - **оставляйте инлайн-выражения простыми**. 93 | 94 | ### Почему? 95 | 96 | * Сложные выражения сложнее прочесть и понять. 97 | * Инлайн-выражения нельзя переиспользовать, это очевидно, ведет дублированию кода и ухудшению его качества. 98 | * Редакторы и IDE обычно не могут парсить такие выражения, а значит у вас не будет автодополнения и валидации. 99 | 100 | ### Как? 101 | 102 | Простое правило - если код Javascript инлайн-выражения становится слишком сложным - **выносите его как отдельный метод в блок methods или computed-свойство, соответственно в блок computed**. 103 | 104 | ```html 105 | 106 | 111 | 128 | 129 | 130 | 135 | ``` 136 | 137 | [↑ наверх](#Содержание) 138 | 139 | ## Оставляйте свойства простыми 140 | 141 | Хотя Vue и поддерживает передачу атрибутов в виде сложных объектов, старайтесь избегать этого. Старайтесь ограничиться [простыми типами JavaScript](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) и функциями для этого. Не передавайте сложные объекты в компоненты-наследники. 142 | 143 | ### Почему? 144 | 145 | * Используя для каждого свойства отдельный атрибут - API вашего компонента будет более наглядным. 146 | * Такой подход совместим с API к которому мы все привыкли у нативных HTML(5) элементов. 147 | * Созданые вами атрибуты будет легче понять другим членам команды. 148 | * При передаче сложных объектов сразу не видно, какие из его свойств далее используются, - это затруднит рефакторинг. 149 | 150 | ### Как? 151 | 152 | Используйте отдельные атрибуты для каждой опции и передавайте в нее примитив (флаг, строку, число) или функцию. 153 | 154 | ```html 155 | 156 | 163 | 164 | 165 | 166 | 167 | ``` 168 | 169 | [↑ наверх](#Содержание) 170 | 171 | ## Ограничивайте использование свойств компонента 172 | 173 | Во Vue свойства компонента (`props`) это его API. Ясное и понятное API делает ваши компоненты более простыми для использования другими разработчиками. 174 | 175 | Свойства передаются с использованием специальных атрибутов тега. Эти атрибуты могут быть либо указаны как пустые значения (`:attr`), либо присвоены строкам (`:attr="value"` или `v-bind:attr="value"`). Обратите внимание на подобные возможности при описании свойств. 176 | 177 | ### Почему? 178 | 179 | Грамотное использование свойств гарантирует, что компонент всегда будет отрабатывать без ошибок. Даже если в последствии ваши компоненты будут использоваться не так как вы предполагали изначально. 180 | 181 | ### Как? 182 | 183 | * Используйте свойства по умолчанию для указания значений свойств. 184 | * Используйте свойство `type` для [валидации](http://vuejs.org/v2/guide/components.html#Prop-Validation) значений свойства. 185 | * Всегда проверяйте что свойство определено прежде чем его использовать. 186 | 187 | ```html 188 | 191 | 209 | ``` 210 | 211 | [↑ наверх](#Содержание) 212 | 213 | 214 | ## Определяйте `this` как `component` 215 | 216 | В контексте кода компонента Vue `this` всегда означает экземпляр самого компонента. Таким образом если вам понадобится обратиться к ней в другом контексте сделайте так, чтобы `this` означало `component`. 217 | 218 | То есть, **не используйте** устаревшие конструкции присваивания вроде `const self = this;`. Можно и нужно использовать `component` в Vue компонентах для этого. 219 | 220 | ### Почему? 221 | 222 | * Присваивая `this` к переменной названной `component` напрямую укажет тем кто это будет использовать, что это означает сам компонент. 223 | 224 | ### Как? 225 | 226 | 227 | ```html 228 | 240 | 241 | 242 | 255 | ``` 256 | [↑ наверх](#Содержание) 257 | 258 | 259 | 260 | ## Структура компонента 261 | 262 | Добейтесь, чтобы описание компонента было понятным и логичным. 263 | 264 | ### Почему? 265 | 266 | * Экспортируемый объект (речь о `.js` файле или блоке ` 308 | 309 | 312 | ``` 313 | 314 | [↑ наверх](#Содержание) 315 | 316 | 317 | 318 | ## Именование событий 319 | 320 | В Vue все инлайн-выражения и методы компонента напрямую относятся к VM (ViewModel) и меняют ее состояние. При декларации собственных событий важно их грамотно называть, чтобы избежать сложности при дальнейшей разработке и использовании компонента. 321 | 322 | ### Почему? 323 | 324 | * Разработчики могут использовать совпадающие имена, что может вызвать проблемы. 325 | * Полная свобода в выборе имён событий может также привести к проблемам с обработкой шаблонов. 326 | 327 | ### Как? 328 | 329 | * В названиях событий стоит использовать кебаб нотацию `kebab-cased`. 330 | * Название компонента должно быть уникальным и отражать что в нем происходит, например: `upload-success`, `upload-error` или `dropzone-upload-success`, `dropzone-upload-error` 331 | * В именах компонентов лучше использовать только существительные и глаголы, например: `client-api-load`, `drive-upload-success` ([источник](https://github.com/GoogleWebComponents/style-guide#events)) 332 | 333 | [↑ наверх](#Содержание) 334 | 335 | 336 | 337 | ## Избегайте использования `this.$parent` 338 | 339 | Vue поддерживает вложенности компонентов, поэтому дочерние компоненты могут обращаться к данным родителя. 340 | Обращение к внутреннему состоянию компонента снаружи нарушает принцип [FIRST](https://addyosmani.com/first/). Старайтесь избегать конструкции `this.$parent`. Возможны случаи, когда это разумный выход, но это слишком плохая практика, чтобы использовать его всегда. 341 | 342 | ### Почему? 343 | 344 | * Компонент Vue, как и любой другой, должен работать изолированно. Если для работы требуется взаимодействия с соседними скоупами, то нарушается принцип компонентной разработки. 345 | * Если компоненту требуется обращение к соседям - такой компонент не может быть полноценно переиспользован. 346 | 347 | 348 | ### Как? 349 | 350 | * Передавайте данные из родителя в дочерний компонент используя атрибуты и свойства. 351 | * Передавайте методы используя коллбеки и выражениях в атрибутах. 352 | * В обратную сторону: дочерние компоненты должны генерировать события, которые будет перехватывать родитель. 353 | 354 | [↑ наверх](#Содержание) 355 | 356 | 357 | ## Используйте `this.$refs` осторожно 358 | 359 | Vue как и React поддерживает обращение к другим компонентам и html-элементам с использованием атрибута `ref`. 360 | Через обращение к `this.$refs` разработчик может получить доступ к контексту других компонентов или тегов. В большинстве случаев можно не использовать `this.$refs` для обращения к другим компонентам. 361 | 362 | ### Почему? 363 | 364 | * Если компонент не работает в изоляции это признак плохого дизайна. 365 | * Для подавляющего большинства случаев, достаточно использовать свойства компонента и его события. 366 | 367 | ### Как? 368 | 369 | * Серьезно относитесь к дизайну API ваших компонентов. 370 | * Старайтесь избегать умножений и ветвлений пути исполнения кода в компонентах. Наличие таких фрагментов является признаком того, что API не достаточно общее, либо вам нужно создать и использовать другие компоненты для других юзкейсов. 371 | * Используя компонент, обратите внимание на свойства: если какого-то из них не хватает, то добавьте их сами и/или создайте тикет, если это osc библиотека. 372 | * Тоже самое с событиями - если чего-то не хватает, значит другой разработчик (или вы сами, в прошлом) не добавил их. Для исправления добавьте отсутствующее или проверьте бизнес-логику компонента, возможно, это событие уже не используется, тогда его можно просто удалить. 373 | * Используйте `this.$refs`, только если других путей нет и вам никак не обойтись событиями и свойствами. 374 | * Если по-другому никак, то отдавайте предпочтение `refs`, а не jQuery или `document.queryElement`. Так вы останетесь на одном уровне абстракции (который даёт Vue) и не будете мешать их в трудно понимаемую кучу. 375 | 376 | ```html 377 | 378 | 382 | ``` 383 | 384 | ```html 385 | 386 | 387 |

Basic Modal

388 | 389 |
390 | 391 | 392 | 393 | 398 | 399 | 418 | 419 | ``` 420 | 421 | ```html 422 | 423 | 429 | 430 | 441 | ``` 442 | [↑ наверх](#Содержание) 443 | 444 | 445 | 446 | ## Используйте ограниченные стили CSS 447 | 448 | В Vue тег компонента является кастомным HTML-тегом, который может использоваться как корневой элемент CSS стилей (`vertical-slider .list-element`). Или имя компонента может быть использовано как префикс CSS класса всех стилей компонента (`.vertical-slider .list-element`). 449 | 450 | ### Почему? 451 | 452 | * Ограничивать CSS стили областью компонента делает поведение UI более предсказуемым, а также предохраняет переопределение стилей других элементов на странице из-за сходства селекторов (т.н. "утечку стилей"). 453 | * Использование одинакового имени для названия папки модуля, названия компонента и корневого CSS стиля, делает прозрачным для разработчиков, что это части одного целого. 454 | 455 | ### Как? 456 | 457 | Используйте имя компонента как неймспейс префикс используя методологии BEM и OOCSS и **важно** не пропускайте атрибут `scoped` на теге ` 471 | ``` 472 | [↑ наверх](#Содержание) 473 | 474 | 475 | 476 | ## Документируйте API компонента 477 | 478 | Экземпляр Vue компонента создается при размещении элемента компонента в коде приложения. Дополнительная конфигурация экземпляра осуществляется при использовании атрибутов. Для того, чтобы компонент мог быть успешно переиспользован другими разработчиками, эти атрибуты и есть API вашего компонента. Они могут быть доходчиво описаны в сопроводительном файле `README.md`. 479 | 480 | ### Почему? 481 | 482 | * Документация предлагает разработчику высокоуровневое описание компонента без необходимости вникать в его код. Это делает использование компонента более быстрым и простым. 483 | * API компонента в Vue это набор его атрибутов. Именно с их помощью он может быть дополнительно настроен. То есть именно атрибуты компонента являются важными для тех разработчиков, которые будут его в дальнейшем использовать. 484 | * Документация формализует API, показывает разработчикам какая часть функционала сохраняется для обратной совместимости при модификации кода компонента. 485 | * Название `README.md` это по факту отраслевой стандарт названия для документации, которую разработчику стоит прочесть прежде чем использовать проект. Многие платформы управления кодом (Github, Bitbucket, Gitlab) по умолчанию показывают содержание README-файла при просмотре контента любой директории. 486 | 487 | ### Как? 488 | 489 | Добавляйте `README.md` файл в папку с файлами одного компонента: 490 | 491 | ``` 492 | range-slider/ 493 | ├── range-slider.vue 494 | ├── range-slider.less 495 | └── README.md 496 | ``` 497 | 498 | В этом README файле можно описать функционал модуля и варианты использования. Для компонентов Vue самым полезным является описать атрибуты, т.к. именно они являются выражением API компонента. 499 | 500 | [↑ наверх](#Содержание) 501 | 502 | 503 | 504 | ## Добавляйте демо компонента 505 | 506 | Добавьте `index.html` файл с демо вида компонента в разных конфигурациях показывая как компонент может быть использован. 507 | 508 | ### Почему? 509 | 510 | * Наличие демо показывает, что модуль работает отдельно. 511 | * Демо помогает другим разработчикам посмотреть на результаты - что получится прежде чем разбираться с кодом и/или документацией. 512 | * Демо компонента исчерпывающе показывает различные варианты конфигурации его использования. 513 | 514 | [↑ наверх](#Содержание) 515 | 516 | 517 | ## Форматируйте код ваших файлов 518 | 519 | Линтеры улучшают качество кода и это помогает отлавливать синтаксические ошибки. `.vue` файлы можно обрабатывать плагином `eslint-plugin-html`. Если вы используете `vue-cli` то ESLint является доступной опцией по умолчанию. 520 | 521 | ### Почему? 522 | 523 | * Использование линтера гарантирует, что все разработчики читают и пишут код с одинаковыми правилами форматирования. 524 | * Использование линтера помогает обнаружить и избежать ошибок до того как код файла сохранен. 525 | 526 | ### Как? 527 | 528 | Чтобы линтеры могли выделять Javascript код из ваших `vue` файлов, он должен быть внутри тега ``. Также старайтесь сохранять инлайн-выражения простыми (см. выше) так как линтер не может их распарсить. 529 | 530 | Настройте линтер, указав ему, что определена глобальная переменная `vue` в секции `opts`. 531 | 532 | #### ESLint 533 | 534 | [ESLint](http://eslint.org/) для использования требуется [плагин ESLint HTML](https://github.com/BenoitZugmeyer/eslint-plugin-html#eslint-plugin-html) чтобы извлечь (распарсить) Javascript из `.vue` файлов компонентов. 535 | 536 | Настройки ESLint сохраняем в файле `modules/.eslintrc` (так чтобы редактор кода также мог его интерпретировать): 537 | ```json 538 | { 539 | "extends": "eslint:recommended", 540 | "plugins": ["html"], 541 | "env": { 542 | "browser": true 543 | }, 544 | "globals": { 545 | "opts": true, 546 | "vue": true 547 | } 548 | } 549 | ``` 550 | 551 | Запуск ESLint 552 | ```bash 553 | eslint modules/**/*.vue 554 | ``` 555 | 556 | #### JSHint 557 | 558 | [JSHint](http://jshint.com/) может парсить HTML (используя `--extra-ext`) и выделять код в script (используя `--extract=auto`). 559 | 560 | Настройки JSHint сохраняем в файле `modules/.jshintrc` (так чтобы редактор кода также мог его интерпретировать): 561 | 562 | ```json 563 | { 564 | "browser": true, 565 | "predef": ["opts", "vue"] 566 | } 567 | ``` 568 | 569 | Запуск JSHint 570 | ```bash 571 | jshint --config modules/.jshintrc --extra-ext=html --extract=auto modules/ 572 | ``` 573 | Внимание: JSHint не работает с `.vue`, только `.html`. 574 | 575 | --- 576 | 577 | ## Хотите поучаствовать? 578 | 579 | Сделайте форк этого репозитория и далее предлагайте PR. Или просто создайте [тикет](https://github.com/pablohpsilva/vuejs-component-style-guide/issues/new). 580 | 581 | ## Автор перевода 582 | 583 | Mikhail Kuznetcov 584 | 585 | - Github [shershen08](https://github.com/shershen08) 586 | - Twitter [@legkoletat](https://twitter.com/legkoletat) 587 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue.js Component Style Guide 2 | 3 |

4 | 5 |

6 | 7 | ### Translations 8 | * [Brazilian Portuguese](https://pablohpsilva.github.io/vuejs-component-style-guide/#/portuguese) 9 | * [Chinese](https://pablohpsilva.github.io/vuejs-component-style-guide/#/chinese) 10 | * [Japanese](https://pablohpsilva.github.io/vuejs-component-style-guide/#/japanese) 11 | * [Korean](https://pablohpsilva.github.io/vuejs-component-style-guide/#/korean) 12 | * [Russian](https://pablohpsilva.github.io/vuejs-component-style-guide/#/russian) 13 | 14 | ## Purpose 15 | 16 | This guide provides a uniform way to structure your [Vue.js](http://vuejs.org/) code. Making it: 17 | 18 | * easier for developers/team members to understand and find things. 19 | * easier for IDEs to interpret the code and provide assistance. 20 | * easier to (re)use build tools you already use. 21 | * easier to cache and serve bundles of code separately. 22 | 23 | This guide is inspired by the [RiotJS Style Guide](https://github.com/voorhoede/riotjs-style-guide) by [De Voorhoede](https://github.com/voorhoede). 24 | 25 | ## Table of Contents 26 | 27 | * [Module based development](#module-based-development) 28 | * [vue component names](#vue-component-names) 29 | * [Keep component expressions simple](#keep-component-expressions-simple) 30 | * [Keep component props primitive](#keep-component-props-primitive) 31 | * [Harness your component props](#harness-your-component-props) 32 | * [Assign `this` to `component`](#assign-this-to-component) 33 | * [Component structure](#component-structure) 34 | * [Component event names](#component-event-names) 35 | * [Avoid `this.$parent`](#avoid-thisparent) 36 | * [Use `this.$refs` with caution](#use-thisrefs-with-caution) 37 | * [Use component name as style scope](#use-component-name-as-style-scope) 38 | * [Document your component API](#document-your-component-api) 39 | * [Add a component demo](#add-a-component-demo) 40 | * [Lint your component files](#lint-your-component-files) 41 | * [Create components when needed](#create-components-when-needed) 42 | 43 | 44 | 45 | 46 | ## Module based development 47 | 48 | Always construct your app out of small modules which do one thing and do it well. 49 | 50 | A module is a small self-contained part of an application. The Vue.js library is specifically designed to help you create *view-logic modules*. 51 | 52 | ### Why? 53 | 54 | Small modules are easier to learn, understand, maintain, reuse and debug. Both by you and other developers. 55 | 56 | ### How? 57 | 58 | Each Vue component (like any module) must be [FIRST](https://addyosmani.com/first/): *Focused* ([single responsibility](http://en.wikipedia.org/wiki/Single_responsibility_principle)), *Independent*, *Reusable*, *Small* and *Testable*. 59 | 60 | If your component does too much or gets too big, split it up into smaller components which each do just one thing. As a rule of thumb, try to keep each component file less than 100 lines of code. 61 | Also ensure your Vue component works in isolation. For instance by adding a stand-alone demo. 62 | 63 | [↑ back to Table of Contents](#table-of-contents) 64 | 65 | 66 | ## Vue Component Names 67 | 68 | Each component name must be: 69 | 70 | * **Meaningful**: not over specific, not overly abstract. 71 | * **Short**: 2 or 3 words. 72 | * **Pronounceable**: we want to be able to talk about them. 73 | 74 | Vue component names must also be: 75 | 76 | * **Custom element spec compliant**: [include a hyphen](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name), don't use reserved names. 77 | * **`app-` namespaced**: if very generic and otherwise 1 word, so that it can easily be reused in other projects. 78 | 79 | ### Why? 80 | 81 | * The name is used to communicate about the component. So it must be short, meaningful and pronounceable. 82 | 83 | ### How? 84 | 85 | ```html 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | ``` 96 | 97 | [↑ back to Table of Contents](#table-of-contents) 98 | 99 | 100 | ## Keep component expressions simple 101 | 102 | Vue.js's inline expressions are 100% Javascript. This makes them extremely powerful, but potentially also very complex. Therefore you should **keep expressions simple**. 103 | 104 | ### Why? 105 | 106 | * Complex inline expressions are hard to read. 107 | * Inline expressions can't be reused elsewhere. This can lead to code duplication and code rot. 108 | * IDEs typically don't have support for expression syntax, so your IDE can't autocomplete or validate. 109 | 110 | ### How? 111 | 112 | If it gets too complex or hard to read **move it to methods or computed properties**! 113 | 114 | ```html 115 | 116 | 121 | 138 | 139 | 140 | 145 | ``` 146 | 147 | [↑ back to Table of Contents](#table-of-contents) 148 | 149 | 150 | ## Keep component props primitive 151 | 152 | While Vue.js supports passing complex JavaScript objects via these attributes, you should try to **keep the component props as primitive as possible**. Try to only use [JavaScript primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) (strings, numbers, booleans) and functions. Avoid complex objects. 153 | 154 | ### Why? 155 | 156 | * By using an attribute for each prop separately the component has a clear and expressive API; 157 | * By using only primitives and functions as props values our component APIs are similar to the APIs of native HTML(5) elements; 158 | * By using an attribute for each prop, other developers can easily understand what is passed to the component instance; 159 | * When passing complex objects it's not apparent which properties and methods of the objects are actually being used by the custom components. This makes it hard to refactor code and can lead to code rot. 160 | 161 | ### How? 162 | 163 | Use a component attribute per props, with a primitive or function as value: 164 | 165 | ```html 166 | 167 | 174 | 175 | 176 | 177 | 178 | ``` 179 | 180 | [↑ back to Table of Contents](#table-of-contents) 181 | 182 | 183 | ## Harness your component props 184 | 185 | In Vue.js your component props are your API. A robust and predictable API makes your components easy to use by other developers. 186 | 187 | Component props are passed via custom HTML attributes. The values of these attributes can be Vue.js plain strings (`:attr="value"` or `v-bind:attr="value"`) or missing entirely. You should **harness your component props** to allow for these different cases. 188 | 189 | ### Why? 190 | 191 | Harnessing your component props ensures your component will always function (defensive programming). Even when other developers later use your components in ways you haven't thought of yet. 192 | 193 | ### How? 194 | 195 | * Use defaults for props values. 196 | * Use `type` option to [validate](http://vuejs.org/v2/guide/components.html#Prop-Validation) values to an expected type.**[1\*]** 197 | * Check if props exists before using it. 198 | 199 | ```html 200 | 203 | 221 | ``` 222 | 223 | [↑ back to Table of Contents](#table-of-contents) 224 | 225 | 226 | ## Assign `this` to `component` 227 | 228 | Within the context of a Vue.js component element, `this` is bound to the component instance. 229 | Therefore when you need to reference it in a different context, ensure `this` is available as `component`. 230 | 231 | In other words: Do **NOT** code things like `var self = this;` anymore if you're using **ES6**. You're safe using Vue components. 232 | 233 | ### Why? 234 | 235 | * Using ES6, there's no need to save `this` to a variable; 236 | * In general, when using arrow functions the lexical scope is kept 237 | * If you're **NOT** using ES6 and, therefore, not using `Arrow Functions`, you'd have to add `this` to a variable. That's the only exception. 238 | 239 | ### How? 240 | 241 | ```html 242 | 254 | 255 | 256 | 269 | ``` 270 | 271 | [↑ back to Table of Contents](#table-of-contents) 272 | 273 | 274 | ## Component structure 275 | 276 | Make it easy to reason and follow a sequence of thoughts. See the How. 277 | 278 | ### Why? 279 | 280 | * Having the component export a clear and grouped object, makes the code easy to read and easier for developers to have a code standard. 281 | * Alphabetizing the properties, data, computed, watches, and methods makes them easy to find. 282 | * Again, grouping makes the component easier to read (name; extends; props, data and computed; components; watch and methods; lifecycle methods, etc.); 283 | * Use the `name` attribute. Using [vue devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en) and that attribute will make your development/testing easier; 284 | * Use a CSS naming Methodology, like [BEM](https://medium.com/tldr-tech/bem-blocks-elements-and-modifiers-6b3b0af9e3ea#.bhnomd7gw), or [rscss](https://github.com/rstacruz/rscss) - [details?](#use-component-name-as-style-scope); 285 | * Use the template-script-style .vue file organization, as recomended by Evan You, Vue.js creator. 286 | 287 | ### How? 288 | 289 | Component structure: 290 | 291 | ```html 292 | 297 | 298 | 325 | 326 | 329 | ``` 330 | 331 | [↑ back to Table of Contents](#table-of-contents) 332 | 333 | ## Component event names 334 | 335 | Vue.js provides all Vue handler functions and expressions are strictly bound to the ViewModel. Each component events should follow a good naming style that will avoid issues during the development. See the **Why** below. 336 | 337 | ### Why? 338 | 339 | * Developers are free to use native likes event names and it can cause confusion down the line; 340 | * The freedom of naming events can lead to a [DOM templates incompatibility](https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats); 341 | 342 | ### How? 343 | 344 | * Event names should be kebab-cased; 345 | * A unique event name should be fired for unique actions in your component that will be of interest to the outside world, like: upload-success, upload-error or even dropzone-upload-success, dropzone-upload-error (if you see the need for having a scoped prefix); 346 | * Events should either end in verbs in the infinitive form (e.g. client-api-load) or nouns (e.g drive-upload-success) ([source](https://github.com/GoogleWebComponents/style-guide#events)); 347 | 348 | [↑ back to Table of Contents](#table-of-contents) 349 | 350 | ## Avoid `this.$parent` 351 | 352 | Vue.js supports nested components which have access to their parent context. Accessing context outside your vue component violates the [FIRST](https://addyosmani.com/first/) rule of [component based development](#module-based-development). Therefore you should **avoid using `this.$parent`**. 353 | 354 | ### Why? 355 | 356 | * A vue component, like any component, must work in isolation. If a component needs to access its parent, this rule is broken. 357 | * If a component needs access to its parent, it can no longer be reused in a different context. 358 | 359 | ### How? 360 | 361 | * Pass values from the parent to the child component using attribute/properties. 362 | * Pass methods defined on the parent component to the child component using callbacks in attribute expressions. 363 | * Emit events from child components and catch it on parent component. 364 | 365 | [↑ back to Table of Contents](#table-of-contents) 366 | 367 | ## Use `this.$refs` with caution 368 | 369 | Vue.js supports components to have access to other components and basic HTML elements context via `ref` attribute. That attribute will provide an accessible way through `this.$refs` to a component or DOM element context. In most cases, the need to access **other components** context via `this.$refs` could be avoided. This is why you should be careful when using it to avoid wrong component APIs. 370 | 371 | ### Why? 372 | 373 | * A vue component, like any component, **must work in isolation**. If a component does not support all the access needed, it was badly designed/implemented. 374 | * Properties and events should be sufficient to most of your components. 375 | 376 | ### How? 377 | 378 | * Create a good component API. 379 | * Always focus on the component purpose out of the box. 380 | * Never write specific code. If you need to write specific code inside a generic component, it means its API isn't generic enough or maybe you need a new component to manage other cases. 381 | * Check all the props to see if something is missing. If it is, create an issue or enhance the component yourself. 382 | * Check all the events. In most cases developers forget that Child-Parent communication (events) is needed, that's why they only remember the Parent-Child communication (using props). 383 | * **Props down, events up!** Upgrade your component when requested with a good API and isolation as goals. 384 | * Using `this.$refs` on components should be used when props and events are exhausted and having it makes sense (see the example below). 385 | * Using `this.$refs` to access DOM elements (instead of doing `jQuery`, `document.getElement*`, `document.queryElement`) is just fine, when the element can't be manipulated with data bindings or for a directive. 386 | 387 | ```html 388 | 389 | 393 | ``` 394 | 395 | ```html 396 | 397 | 398 |

Basic Modal

399 | 400 |
401 | 402 | 403 | 404 | 409 | 410 | 429 | 430 | ``` 431 | 432 | ```html 433 | 434 | 440 | 441 | 452 | ``` 453 | 454 | [↑ back to Table of Contents](#table-of-contents) 455 | 456 | 457 | ## Use component name as style scope 458 | 459 | Vue.js component elements are custom elements which can very well be used as style scope root. 460 | Alternatively the component name can be used as CSS class namespace. 461 | 462 | ### Why? 463 | 464 | * Scoping styles to a component element improves predictability as its prevents styles leaking outside the component element. 465 | * Using the same name for the module directory, the Vue.js component and the style root makes it easy for developers to understand they belong together. 466 | 467 | ### How? 468 | 469 | Use the component name as a namespace prefix based on BEM and OOCSS **and** use the `scoped` attribute on your style class. 470 | The use of `scoped` will tell your Vue compiler to add a signature on every class that your ` 483 | ``` 484 | 485 | [↑ back to Table of Contents](#table-of-contents) 486 | 487 | 488 | ## Document your component API 489 | 490 | A Vue.js component instance is created by using the component element inside your application. The instance is configured through its custom attributes. For the component to be used by other developers, these custom attributes - the component's API - should be documented in a `README.md` file. 491 | 492 | ### Why? 493 | 494 | * Documentation provides developers with a high level overview to a component, without the need to go through all its code. This makes a component more accessible and easier to use. 495 | * A component's API is the set of custom attributes through which its configured. Therefore these are especially of interest to other developers which only want to consume (and not develop) the component. 496 | * Documentation formalises the API and tells developers which functionality to keep backwards compatible when modifying the component's code. 497 | * `README.md` is the de facto standard filename for documentation to be read first. Code repository hosting services (Github, Bitbucket, Gitlab etc) display the contents of the the README's, directly when browsing through source directories. This applies to our module directories as well. 498 | 499 | ### How? 500 | 501 | Add a `README.md` file to the component's module directory: 502 | 503 | ``` 504 | range-slider/ 505 | ├── range-slider.vue 506 | ├── range-slider.less 507 | └── README.md 508 | ``` 509 | 510 | Within the README file, describe the functionality and the usage of the module. For a vue component its most useful to describe the custom attributes it supports as those are its API: 511 | 512 | 513 | # Range slider 514 | 515 | ## Functionality 516 | 517 | The range slider lets the user to set a numeric range by dragging a handle on a slider rail for both the start and end value. 518 | 519 | This module uses the [noUiSlider](http://refreshless.com/nouislider/) for cross browser and touch support. 520 | 521 | ## Usage 522 | 523 | `` supports the following custom component attributes: 524 | 525 | | attribute | type | description 526 | | --- | --- | --- 527 | | `min` | Number | number where range starts (lower limit). 528 | | `max` | Number | Number where range ends (upper limit). 529 | | `values` | Number[] *optional* | Array containing start and end value. E.g. `values="[10, 20]"`. Defaults to `[opts.min, opts.max]`. 530 | | `step` | Number *optional* | Number to increment / decrement values by. Defaults to 1. 531 | | `on-slide` | Function *optional* | Function called with `(values, HANDLE)` while a user drags the start (`HANDLE == 0`) or end (`HANDLE == 1`) handle. E.g. `on-slide={ updateInputs }`, with `component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }`. 532 | | `on-end` | Function *optional* | Function called with `(values, HANDLE)` when user stops dragging a handle. 533 | 534 | For customising the slider appearance see the [Styling section in the noUiSlider docs](http://refreshless.com/nouislider/more/#section-styling). 535 | 536 | 537 | [↑ back to Table of Contents](#table-of-contents) 538 | 539 | 540 | ## Add a component demo 541 | 542 | Add a `index.html` file with demos of the component with different configurations, showing how the component can be used. 543 | 544 | ### Why? 545 | 546 | * A component demo proves the component works in isolation. 547 | * A component demo gives developers a preview before having to dig into the documentation or code. 548 | * Demos can illustrate all the possible configurations and variations a component can be used in. 549 | 550 | [↑ back to Table of Contents](#table-of-contents) 551 | 552 | 553 | ## Lint your component files 554 | 555 | Linters improve code consistency and help trace syntax errors. .vue files can be linted adding the `eslint-plugin-html` in your project. If you choose, you can start a project with ESLint enabled by default using `vue-cli`; 556 | 557 | ### Why? 558 | 559 | * Linting component files ensures all developers use the same code style. 560 | * Linting component files helps you trace syntax errors before it's too late. 561 | 562 | ### How? 563 | 564 | To allow linters to extract the scripts from your `*.vue` files, put script inside a ` 679 | ``` 680 | 681 | [↑ back to Table of Contents](#table-of-contents) 682 | 683 | --- 684 | 685 | ## Wanna help? 686 | 687 | Fork it and Pull Request what you think it should be good to have or just create an [Issue](https://github.com/pablohpsilva/vuejs-component-style-guide/issues/new). 688 | 689 | 690 | 729 | 730 | 731 | ## Translation authors 732 | 733 | * [Brazilian Portuguese](README-PTBR.md): Pablo Henrique Silva [github:pablohpsilva](https://github.com/pablohpsilva), [twitter: @PabloHPSilva](https://twitter.com/PabloHPSilva) 734 | * [Russian](https://pablohpsilva.github.io/vuejs-component-style-guide/#/russian): Mikhail Kuznetcov [github:shershen08](https://github.com/shershen08), [twitter: @legkoletat](https://twitter.com/legkoletat) 735 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/vuejs-component-style-guide/ef3988ef2d4979071a5a6515f2fe174b2c26c717/docs/.nojekyll -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | docs 8 | 9 | 14 | 15 | 16 |
17 | 18 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/vuejs-component-style-guide/ef3988ef2d4979071a5a6515f2fe174b2c26c717/img/logo.png --------------------------------------------------------------------------------