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 |
121 |
147 |
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 |
203 |
204 |
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 |
299 |
300 |
301 |
302 |
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 |
410 |
411 |
412 |
413 |
414 |
415 |
434 | ```
435 |
436 | ```html
437 |
438 |
439 |
440 |
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 |
140 |
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 |
197 |
198 |
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 |
287 |
288 |
289 |
290 |
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 |
397 |
398 |
399 |
400 |
401 |
402 |
421 | ```
422 |
423 | ```html
424 |
425 |
426 |
430 |
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 |
140 |
143 |
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 |
200 |
201 |
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 |
290 |
291 |
292 |
293 |
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 |
400 |
401 |
402 |
403 |
404 |
405 |
424 |
425 | ```
426 |
427 | ```html
428 |
429 |
430 |
434 |
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 |
107 |
134 |
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 |
189 |
190 |
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 |
394 |
395 |
396 |
397 |
398 |
399 |
418 |
419 | ```
420 |
421 | ```html
422 |
423 |
424 |
428 |
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 |
117 |
144 |
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 |
201 |
202 |
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 |
293 |
294 |
295 |
296 |
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 |
405 |
406 |
407 |
408 |
409 |
410 |
429 |
430 | ```
431 |
432 | ```html
433 |
434 |
435 |
439 |
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
--------------------------------------------------------------------------------