├── .gitignore
├── LICENSE
├── README.md
├── deploy.sh
├── docs
├── .vuepress
│ ├── components
│ │ └── GitHubStarButton.vue
│ ├── config.js
│ └── public
│ │ └── learn-vue-logo.png
├── README.md
├── patterns
│ └── README.md
├── sponsors
│ └── README.md
└── useful-links
│ └── README.md
├── generate-toc.md
├── package.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/node
3 |
4 | ### Node ###
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 |
24 | # nyc test coverage
25 | .nyc_output
26 |
27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
28 | .grunt
29 |
30 | # Bower dependency directory (https://bower.io/)
31 | bower_components
32 |
33 | # node-waf configuration
34 | .lock-wscript
35 |
36 | # Compiled binary addons (https://nodejs.org/api/addons.html)
37 | build/Release
38 |
39 | # Dependency directories
40 | node_modules/
41 | jspm_packages/
42 |
43 | # TypeScript v1 declaration files
44 | typings/
45 |
46 | # Optional npm cache directory
47 | .npm
48 |
49 | # Optional eslint cache
50 | .eslintcache
51 |
52 | # Optional REPL history
53 | .node_repl_history
54 |
55 | # Output of 'npm pack'
56 | *.tgz
57 |
58 | # Yarn Integrity file
59 | .yarn-integrity
60 |
61 | # dotenv environment variables file
62 | .env
63 |
64 | # parcel-bundler cache (https://parceljs.org/)
65 | .cache
66 |
67 | # next.js build output
68 | .next
69 |
70 | # nuxt.js build output
71 | .nuxt
72 |
73 | # vuepress build output
74 | .vuepress/dist
75 |
76 | # Serverless directories
77 | .serverless
78 |
79 |
80 | # End of https://www.gitignore.io/api/node
81 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Ilkwon Sim
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-patterns-cn
2 |
3 | > 有用的Vue模式,技巧,提示和技巧以及有帮助的精选链接。
4 |
5 | ## 翻译
6 |
7 | 英文原版:[learn-vuejs](https://github.com/learn-vuejs/vue-patterns)
8 | 简体中文:[ZYSzys](https://github.com/ZYSzys/vue-patterns-cn)
9 | 繁体中文:[yoyoys](https://github.com/yoyoys/vue-patterns-cht)
10 |
11 | ## 目录
12 |
13 | - [组件声明](#组件声明)
14 | - [单文件组件 (SFC) - 最常用](#单文件组件-sfc---最常用)
15 | - [字符串模板 (ES6模板字面值)](#字符串模板-es6模板字面值)
16 | - [渲染函数](#渲染函数)
17 | - [JSX](#jsx)
18 | - [vue-class-component](#vue-class-component)
19 | - [组件通信](#组件通信)
20 | - [Props 和 Events](#props和events)
21 | - [组件事件处理](#组件事件处理)
22 | - [组件条件渲染](#组件条件渲染)
23 | - [指令 (v-if / v-else / v-else-if / v-show)](#指令-v-if--v-else--v-else-if--v-show)
24 | - [JSX](#jsx-1)
25 | - [动态组件](#动态组件)
26 | - [带is属性的组件](#带is属性的组件)
27 | - [构建](#构建)
28 | - [基础构建](#基础构建)
29 | - [继承](#继承)
30 | - [混入](#混入)
31 | - [插槽 (默认)](#插槽-默认)
32 | - [具名插槽](#具名插槽)
33 | - [作用域插槽](#作用域插槽)
34 | - [渲染 Props](#渲染-props)
35 | - [传递 Props](#传递-props)
36 | - [高阶组件 (HOC)](#高阶组件-HOC)
37 | - [依赖注入](#依赖注入)
38 | - [Provide / Inject](#provide--inject)
39 | - [@Provide / @Inject Decorator](#provide--inject-decorator)
40 | - [错误处理](#错误处理)
41 | - [错误捕获钩子](#错误捕获钩子)
42 | - [高效提示](#高效提示)
43 | - [有帮助的链接](#有帮助的链接)
44 | - [风格指南](#风格指南)
45 | - [重构](#重构)
46 | - [状态管理](#状态管理)
47 | - [Vuex](#vuex)
48 | - [Mobx](#mobx)
49 | - [无渲染组件](#无渲染组件)
50 | - [文件结构](#文件结构)
51 | - [提示技巧](#提示技巧)
52 | - [路由](#路由)
53 | - [Anti Patterns](#anti-patterns)
54 | - [视频 / 音频](#视频--音频)
55 | - [仓库](#仓库)
56 | - [付费](#付费)
57 | - [Typescript](#typescript)
58 | - [Flowtype](#flowtype)
59 | - [GraphQL](#graphql)
60 | - [Misc](#misc)
61 | - [全栈Vue图书](#全栈-vue-图书)
62 |
63 | ## 组件声明
64 |
65 | ### [单文件组件 (SFC)](https://vuejs.org/v2/guide/single-file-components.html) - 最常用
66 |
67 | ```html
68 |
69 |
72 |
73 |
74 |
88 |
89 |
94 | ```
95 |
96 | ### 字符串模板 (ES6模板字面值)
97 |
98 | ```js
99 | Vue.component('my-btn', {
100 | template: `
101 |
104 | `,
105 | data() {
106 | return {
107 | text: 'Click me',
108 | };
109 | },
110 | methods: {
111 | handleClick() {
112 | console.log('clicked');
113 | },
114 | },
115 | });
116 | ```
117 |
118 | ### [渲染函数](https://vuejs.org/v2/guide/render-function.html)
119 |
120 | ```js
121 | Vue.component('my-btn', {
122 | data() {
123 | return {
124 | text: 'Click me',
125 | };
126 | },
127 | methods: {
128 | handleClick() {
129 | console.log('clicked');
130 | },
131 | },
132 | render(h) {
133 | return h('button', {
134 | attrs: {
135 | class: 'btn-primary'
136 | },
137 | on: {
138 | click: this.handleClick,
139 | },
140 | }, this.text);
141 | },
142 | });
143 | ```
144 |
145 | ### [JSX](https://vuejs.org/v2/guide/render-function.html#JSX)
146 |
147 | ```jsx
148 | Vue.component('my-btn', {
149 | data() {
150 | return {
151 | text: 'Click me',
152 | };
153 | },
154 | methods: {
155 | handleClick() {
156 | console.log('clicked');
157 | },
158 | },
159 | render() {
160 | return (
161 |
164 | );
165 | },
166 | });
167 | ```
168 |
169 | ### [vue-class-component](https://github.com/vuejs/vue-class-component)
170 |
171 | ```html
172 |
173 |
176 |
177 |
178 |
191 |
192 |
197 | ```
198 |
199 | #### 参考:
200 |
201 | * [Official - Single File Component](https://vuejs.org/v2/guide/single-file-components.html)
202 | * [Official - Render Functions & JSX](https://vuejs.org/v2/guide/render-function.html)
203 | * [7 Ways To Define A Component Template in VueJS](https://medium.com/js-dojo/7-ways-to-define-a-component-template-in-vuejs-c04e0c72900d)
204 |
205 | ## 组件通信
206 |
207 | ### Props和Events
208 |
209 | 基本上,vue组件遵循单向数据流,即props向下([参见官方指南](https://vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow) 和 event向上。
210 | props是只读数据,因此无法从子组件更改props。
211 | 当props更改时,子组件将自动重新渲染(props是响应性数据源)。
212 | 子组件只能将event事件直接发送到父组件,因此父组件可以更改`data`,映射到子组件的`props`。
213 |
214 | ```html
215 |
216 |
217 |
218 |
219 |
227 | ```
228 |
229 | ```html
230 |
231 |
232 |
233 |
234 |
250 | ```
251 |
252 | #### 参考:
253 |
254 | * [Official - Props](https://vuejs.org/v2/guide/components-props.html)
255 | * [Vue.js Component Communication Patterns](https://alligator.io/vuejs/component-communication/)
256 | * [Creating Custom Inputs With Vue.js](https://www.smashingmagazine.com/2017/08/creating-custom-inputs-vue-js/)
257 | * [Vue Sibling Component Communication](https://vegibit.com/vue-sibling-component-communication/)
258 | * [Managing State in Vue.js](https://medium.com/fullstackio/managing-state-in-vue-js-23a0352b1c87)
259 | * [Vue.js communication part 2: parent-child components](https://gambardella.info/2017/09/13/vue-js-communication-part-2-parent-child-components/)
260 |
261 | ## 组件事件处理
262 |
263 | #### 参考:
264 |
265 | * [Official - Custom Events](https://vuejs.org/v2/guide/components-custom-events.html)
266 | * [Leveraging Vue events to reduce prop declarations](https://itnext.io/leveraging-vue-events-to-reduce-prop-declarations-e38f5dce2aaf)
267 | * [Vue.js Component Hooks as Events](https://alligator.io/vuejs/component-event-hooks/)
268 | * [Creating a Global Event Bus with Vue.js](https://alligator.io/vuejs/global-event-bus/)
269 | * [Vue.js Event Bus + Promises](https://medium.com/@jesusgalvan/vue-js-event-bus-promises-f83e73a81d72)
270 |
271 | ## 组件条件渲染
272 |
273 | ### 指令 (`v-if` / `v-else` / `v-else-if` / `v-show`)
274 |
275 | `v-if`
276 |
277 | ```html
278 |
Render only if v-if condition is true
279 | ```
280 |
281 | `v-if` and `v-else`
282 |
283 | ```html
284 | Render only if v-if condition is true
285 | Render only if v-if condition is false
286 | ```
287 |
288 | `v-else-if`
289 |
290 | ```html
291 | Render only if `type` is equal to `A`
292 | Render only if `type` is equal to `B`
293 | Render only if `type` is equal to `C`
294 | Render if `type` is not `A` or `B` or `C`
295 | ```
296 |
297 | `v-show`
298 |
299 | ```html
300 | Always rendered, but it should be visible only if `v-show` conditions is true
301 | ```
302 |
303 | 如果要有条件地渲染多个元素,
304 | 你可以在``元素上使用指令(`v-if` /`v-else` /`v-else-if` /`v-show`)。
305 | 请注意,``元素实际上并未渲染为DOM。 它是一个不可见的封装。
306 |
307 | ```html
308 |
309 | All the elements
310 | will be rendered into DOM
311 | except `template` element
312 |
313 | ```
314 |
315 | ### JSX
316 |
317 | 如果在vue应用程序中使用JSX,则可以应用所有技术,例如`if else`和`switch case`语句以及`ternary`和`logical`运算符。
318 |
319 | `if else` 声明
320 |
321 | ```jsx
322 | export default {
323 | data() {
324 | return {
325 | isTruthy: true,
326 | };
327 | },
328 | render(h) {
329 | if (this.isTruthy) {
330 | return Render value is true
;
331 | } else {
332 | return Render value is false
;
333 | }
334 | },
335 | };
336 | ```
337 |
338 | `switch case` 声明
339 |
340 | ```jsx
341 | import Info from './Info';
342 | import Warning from './Warning';
343 | import Error from './Error';
344 | import Success from './Success';
345 |
346 | export default {
347 | data() {
348 | return {
349 | type: 'error',
350 | };
351 | },
352 | render(h) {
353 | switch (this.type) {
354 | case 'info':
355 | return ;
356 | case 'warning':
357 | return ;
358 | case 'error':
359 | return ;
360 | default:
361 | return ;
362 | }
363 | },
364 | };
365 | ```
366 |
367 | 或者你可以使用 `object` 映射来简化 `switch case`
368 |
369 | ```jsx
370 | import Info from './Info';
371 | import Warning from './Warning';
372 | import Error from './Error';
373 | import Success from './Success';
374 |
375 | const COMPONENT_MAP = {
376 | info: Info,
377 | warning: Warning,
378 | error: Error,
379 | success: Success,
380 | };
381 |
382 | export default {
383 | data() {
384 | return {
385 | type: 'error',
386 | };
387 | },
388 | render(h) {
389 | const Comp = COMPONENT_MAP[this.type || 'success'];
390 |
391 | return ;
392 | },
393 | };
394 | ```
395 |
396 | 三元运算符
397 |
398 | ```jsx
399 | export default {
400 | data() {
401 | return {
402 | isTruthy: true,
403 | };
404 | },
405 | render(h) {
406 | return (
407 |
408 | {this.isTruthy ? (
409 |
Render value is true
410 | ) : (
411 | Render value is false
412 | )}
413 |
414 | );
415 | },
416 | };
417 | ```
418 |
419 | 逻辑运算符
420 |
421 | ```jsx
422 | export default {
423 | data() {
424 | return {
425 | isLoading: true,
426 | };
427 | },
428 | render(h) {
429 | return {this.isLoading &&
Loading ...
};
430 | },
431 | };
432 | ```
433 | #### 参考
434 |
435 | * [Official - Conditional Rendering](https://vuejs.org/v2/guide/conditional.html)
436 | * [Difference Between v-if and v-show [With Video at End]](https://dzone.com/articles/difference-between-v-if-and-v-show-with-a-video)
437 |
438 | ## 动态组件
439 |
440 | ### 带is属性的组件
441 |
442 | * [Example 1](https://jsfiddle.net/chrisvfritz/o3nycadu/)
443 | * [Example 2](https://jsfiddle.net/chrisvfritz/b2qj69o1/)
444 | * [Example 3](https://alligator.io/vuejs/dynamic-components/)
445 |
446 | ```html
447 |
448 | ```
449 |
450 | 在上面的代码示例中,如果在``中呈现不同的组件,则将销毁渲染的组件。 如果你想让组件保持它们的实例而不在``标签中被销毁,你可以将``标签包装在``标签中,如下所示:
451 |
452 | ```html
453 |
454 |
455 |
456 | ```
457 |
458 | #### 参考
459 |
460 | * [Official - Dynamic Components](https://vuejs.org/v2/guide/components.html#Dynamic-Components)
461 | * [Official - Dynamic & Async Components](https://vuejs.org/v2/guide/components-dynamic-async.html)
462 | * [Dynamic Component Templates with Vue.js](https://medium.com/scrumpy/dynamic-component-templates-with-vue-js-d9236ab183bb)
463 |
464 | ## 构建
465 |
466 | #### 库
467 |
468 | * [Proppy - Functional props composition for components](https://proppyjs.com/)
469 |
470 | ### 基础构建
471 |
472 | ```html
473 |
474 |
475 |
476 |
477 |
478 |
479 |
488 | ```
489 |
490 | #### References
491 |
492 | * [Official - Composing with Components](https://vuejs.org/v2/guide/#Composing-with-Components)
493 |
494 | ### 继承
495 |
496 | 当你想要继承单个vue组件时
497 |
498 | ```html
499 |
500 |
503 |
504 |
505 |
513 | ```
514 |
515 | #### 参考:
516 |
517 | * [Official - extends](https://vuejs.org/v2/api/#extends)
518 | * [Extending VueJS Components](https://medium.com/js-dojo/extending-vuejs-components-42fefefc688b)
519 |
520 | ### 混入
521 |
522 | ```js
523 | // closableMixin.js
524 | export default {
525 | props: {
526 | isOpen: {
527 | default: true
528 | }
529 | },
530 | data: function() {
531 | return {
532 | shown: this.isOpen
533 | }
534 | },
535 | methods: {
536 | hide: function() {
537 | this.shown = false;
538 | },
539 | show: function() {
540 | this.shown = true;
541 | },
542 | toggle: function() {
543 | this.shown = !this.shown;
544 | }
545 | }
546 | }
547 | ```
548 |
549 | ```html
550 |
551 |
552 | {{text}}
553 |
554 |
555 |
556 |
557 |
565 | ```
566 |
567 | #### 参考:
568 |
569 | * [Official - mixins](https://vuejs.org/v2/guide/mixins.html)
570 | * [Practical use of Components and Mixins in Vue JS](http://www.qcode.in/practical-use-of-components-and-mixins-in-vue-js/)
571 |
572 |
573 | ### 插槽 (默认)
574 |
575 | ```html
576 |
577 |
580 |
581 |
582 |
587 | ```
588 |
589 | ```html
590 |
591 |
592 |
593 | Login
594 |
595 |
596 |
597 |
606 | ```
607 |
608 | #### 参考:
609 |
610 | * [Official - Slot Content](https://vuejs.org/v2/guide/components-slots.html#Slot-Content)
611 | * [Understanding Component Slots with Vue.js](https://alligator.io/vuejs/component-slots/)
612 | * [Composing Custom Elements With Slots And Named Slots](https://alligator.io/web-components/composing-slots-named-slots/)
613 | * [Writing Abstract Components with Vue.js](https://alligator.io/vuejs/vue-abstract-components/)
614 |
615 | ### 具名插槽
616 |
617 | BaseLayout.vue
618 |
619 | ```html
620 |
621 |
624 |
625 |
626 |
627 |
630 |
631 | ```
632 |
633 | App.vue
634 |
635 | ```html
636 |
637 |
638 | Here might be a page title
639 |
640 |
641 | A paragraph for the main content.
642 | And another one.
643 |
644 |
645 | Here's some contact info
646 |
647 |
648 | ```
649 |
650 | #### 参考
651 |
652 | * [Official - Named Slots](https://vuejs.org/v2/guide/components-slots.html#Named-Slots)
653 |
654 | ### 作用域插槽
655 |
656 | ```html
657 |
658 |
659 | -
663 |
664 |
665 |
666 | {{ todo.text }}
667 |
668 |
669 |
670 |
671 |
672 |
683 | ```
684 |
685 | ```html
686 |
687 |
688 |
689 | ✓
690 | {{ todo.text }}
691 |
692 |
693 |
694 |
695 |
714 | ```
715 |
716 | #### 参考:
717 |
718 | * [Official - Scoped Slots](https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots)
719 | * [Getting Your Head Around Vue.js Scoped Slots](https://medium.com/js-dojo/getting-your-head-around-vue-js-scoped-slots-281bf82a1e4e)
720 | * [Understanding scoped slots in Vue.js](https://medium.com/corebuild-software/understanding-scoped-slots-in-vue-js-db5315a42391)
721 | * [Scoped Component Slots in Vue.js](https://alligator.io/vuejs/scoped-component-slots/)
722 | * [The Trick to Understanding Scoped Slots in Vue.js](https://adamwathan.me/the-trick-to-understanding-scoped-slots-in-vuejs/)
723 | * [The Power of Scoped Slots in Vue](https://pineco.de/power-scoped-slots-vue/)
724 | * [Building a list keyboard control component with Vue.js and scoped slots](https://medium.com/@tkwebdev/building-a-list-keyboard-control-component-with-vue-js-and-scoped-slots-c74db4fcf84f)
725 |
726 | ### 渲染 Props
727 |
728 | 在大多数情况下,您可以使用 `scoped` 插槽而不是渲染 `props`。 但是,在某些情况下它可能有用。
729 |
730 | 单文件组件(`SFC`)中
731 |
732 | ```html
733 |
734 |
735 |
736 |
737 |
738 |
739 |
757 |
764 | ```
765 |
766 | `JSX`中
767 |
768 | ```js
769 | const Mouse = {
770 | name: "Mouse",
771 | props: {
772 | render: {
773 | type: Function,
774 | required: true
775 | }
776 | },
777 | data() {
778 | return {
779 | x: 0,
780 | y: 0
781 | };
782 | },
783 | methods: {
784 | handleMouseMove(event) {
785 | this.x = event.clientX;
786 | this.y = event.clientY;
787 | }
788 | },
789 | render(h) {
790 | return (
791 |
792 | {this.$props.render(this)}
793 |
794 | );
795 | }
796 | };
797 |
798 | export default Mouse;
799 | ```
800 |
801 | #### 参考:
802 |
803 | * [Official - Render Functions & JSX](https://vuejs.org/v2/guide/render-function.html)
804 | * [Leveraging Render Props in Vue](https://medium.com/@dillonchanis/leveraging-render-props-in-vue-7eb9a19c262d)
805 | * [Use a Vue.js Render Prop!](https://medium.com/js-dojo/use-a-vue-js-render-prop-98880bc44e05)
806 |
807 | ## 传递 Props
808 |
809 | 有时,你可能希望将 `props`和 `listeners`传递给子组件,而无需声明所有子组件的 `props`。
810 | 您可以在子组件中绑定 `$attrs` 和 `$listeners`,并将 [`inheritAttrs` 设置为 `false`](https://vuejs.org/v2/api/#inheritAttrs)(否则div和子组件都将接收属性)
811 |
812 | 子组件中:
813 | ```html
814 |
815 |
816 |
{{title}}
817 |
818 |
819 |
820 |
821 |
833 | ```
834 |
835 | 在父组件中,你可以这样做:
836 | ```html
837 |
838 |
843 |
844 |
845 |
846 |
860 | ```
861 |
862 | #### 参考:
863 |
864 | * [Transparent Wrapper Components in Vue](https://zendev.com/2018/05/31/transparent-wrapper-components-in-vue.html)
865 |
866 | ## 高阶组件 (HOC)
867 |
868 | #### 参考:
869 |
870 | * [Higher Order Components in Vue.js](https://medium.com/bethink-pl/higher-order-components-in-vue-js-a79951ac9176)
871 | * [Do we need Higher Order Components in Vue.js?](https://medium.com/bethink-pl/do-we-need-higher-order-components-in-vue-js-87c0aa608f48)
872 | * [Higher-Order Components in Vue.js](https://medium.com/tldr-tech/higher-order-components-in-vue-js-38b500c6d49f)
873 |
874 | ## 依赖注入
875 |
876 | Vue支持依赖/注入机制,无论组件层次结构有多深,只要它们位于同一父链中,就可以将`object`提供给它的所有后代。 请注意,`provide`和`inject`绑定不是响应式的,除非你传递一个观察对象。
877 |
878 | ```html
879 |
880 |
881 |
882 |
883 |
884 | ```
885 |
886 | 在上面的示例组件层次结构中,为了从`parent-component`派生数据,您应该将数据(对象)作为`props`传递给`child-component`和`grand-child-component`。 但是,如果`parent-component``提供`数据(对象),`grand-child-component`只能从`parent-component`定义`inject`提供的对象。
887 |
888 | #### 参考:
889 |
890 | * [Official API](https://vuejs.org/v2/api/#provide-inject)
891 | * [Official Guide](https://vuejs.org/v2/guide/components-edge-cases.html#Dependency-Injection)
892 | * [Component Communication](https://alligator.io/vuejs/component-communication/#provide--inject)
893 | * [Dependency Injection in Vue.js App with TypeScript](https://blog.kloud.com.au/2017/03/22/dependency-injection-in-vuejs-app-with-typescript/)
894 |
895 | ### Provide / Inject
896 |
897 | ```js
898 | // ParentComponent.vue
899 |
900 | export default {
901 | provide: {
902 | theme: {
903 | primaryColor: 'blue',
904 | },
905 | },
906 | };
907 | ```
908 |
909 | ```html
910 | // GrandChildComponent.vue
911 |
912 |
913 |
916 |
917 |
918 |
929 | ```
930 |
931 | ### [@Provide / @Inject Decorator](https://github.com/kaorun343/vue-property-decorator)
932 |
933 | ```js
934 | // ParentComponent.vue
935 |
936 | import { Component, Vue, Provide } from 'vue-property-decorator';
937 |
938 | @Component
939 | export class ParentComponent extends Vue {
940 | @Provide
941 | theme = {
942 | primaryColor: 'blue',
943 | };
944 | }
945 | ```
946 |
947 | ```html
948 | // GrandChildComponent.vue
949 |
950 |
951 |
954 |
955 |
956 |
966 | ```
967 |
968 | ## 错误处理
969 |
970 | ### 错误捕获钩子
971 |
972 | ```js
973 | export default {
974 | name: 'ErrorBoundary',
975 | data() {
976 | return {
977 | error: false,
978 | errorMessage: '',
979 | };
980 | },
981 | errorCaptured (err, vm, info) {
982 | this.error = true;
983 | this.errorMessage = `${err.stack}\n\nfound in ${info} of component`;
984 |
985 | return false;
986 | },
987 | render (h) {
988 | if (this.error) {
989 | return h('pre', { style: { color: 'red' }}, this.errorMessage);
990 | }
991 |
992 | return this.$slots.default[0]
993 | }
994 | };
995 | ```
996 |
997 | ```
998 |
999 |
1000 |
1001 | ```
1002 |
1003 | #### Examples
1004 |
1005 | * [Example 1](https://jsfiddle.net/Linusborg/z84wspcg/)
1006 |
1007 | #### 参考
1008 |
1009 | * [Handling Errors in Vue with Error Boundaries](https://medium.com/@dillonchanis/handling-errors-in-vue-with-error-boundaries-91f6ead0093b)
1010 |
1011 | ## 高效提示
1012 |
1013 | watch on create
1014 |
1015 | ```js
1016 | // don't
1017 | created() {
1018 | this.fetchUserList();
1019 | },
1020 | watch: {
1021 | searchText: 'fetchUserList',
1022 | }
1023 | ```
1024 |
1025 | ```js
1026 | // do
1027 | watch: {
1028 | searchText: {
1029 | handler: 'fetchUserList',
1030 | immediate: true,
1031 | }
1032 | }
1033 | ```
1034 |
1035 | ## 有帮助的链接
1036 |
1037 | ### 风格指南
1038 |
1039 | * [Official - Style Guide](https://vuejs.org/v2/style-guide/)
1040 | * [Vue.js Component Style Guide](https://github.com/pablohpsilva/vuejs-component-style-guide)
1041 |
1042 | ### 重构
1043 |
1044 | * [Refactoring Vue: Cleaning Up a List of Posts With Better Component Splitting and More ES6](https://mattstauffer.com/blog/refactoring-vue-cleaning-up-a-list-of-posts-with-better-component-splitting-and-more-es6/?utm_campaign=Revue%20newsletter&utm_medium=Newsletter&utm_source=Vue.js%20Feed)
1045 | * [Clean up your Vue modules with ES6 Arrow Functions](https://gist.github.com/JacobBennett/7b32b4914311c0ac0f28a1fdc411b9a7)
1046 | * [Examples of Vue’s Clean Code](https://webdesign.tutsplus.com/tutorials/examples-of-vues-clean-code--cms-29619)
1047 | * [Optimizing Performance with Computed Properties](https://codingexplained.com/coding/front-end/vue-js/optimizing-performance-computed-properties)
1048 | * [Simplify Your Components with Computed Setters](https://tahazsh.com/vuebyte-computed-setters)
1049 |
1050 | ### 状态管理
1051 |
1052 | * [Managing State in Vue.js](https://medium.com/fullstackio/managing-state-in-vue-js-23a0352b1c87)
1053 |
1054 | ### Vuex
1055 |
1056 | * [Decouple Vuex modules with the Mediator pattern](https://itnext.io/decouple-vuex-actions-with-the-mediator-pattern-58a8879de1b4)
1057 | * [Vuex getters are great, but don’t overuse them](https://codeburst.io/vuex-getters-are-great-but-dont-overuse-them-9c946689b414)
1058 | * [Reusable Vuex Mutation Functions](https://itnext.io/reusable-vuex-mutation-functions-9b4920aa737b)
1059 | * [A pattern to handle ajax requests in Vuex](https://medium.com/@lachlanmiller_52885/a-pattern-to-handle-ajax-requests-in-vuex-2d69bc2f8984)
1060 | * [[vuex Mutations] Single Changes vs. Single Responsibility](https://forum.vuejs.org/t/vuex-mutations-single-changes-vs-single-responsibility/16396)
1061 | * [Components and How They Interact in Vue and Vuex](https://dzone.com/articles/how-do-components-interact-in-vue-and-what-is-vuex)
1062 | * [Why VueX Is The Perfect Interface Between Frontend and API](https://codeburst.io/why-vuex-is-the-perfect-interface-between-frontend-and-api-271d92161709)
1063 | * [Composing actions with Vuex](https://codeburst.io/composing-actions-with-vuex-b63466264a37)
1064 | * [How to Build Complex, Large-Scale Vue.js Apps With Vuex](https://code.tutsplus.com/tutorials/how-to-build-complex-large-scale-vuejs-applications-with-vuex--cms-30952)
1065 | * [Should I Store This Data in Vuex?](https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/)
1066 | * [Anyway, this is how to use v-model with Vuex. Computed setter in action.](https://itnext.io/anyway-this-is-how-to-use-v-model-with-vuex-computed-setter-in-action-320eb682c976)
1067 | * [5 Vuex Plugins For Your Next VueJS Project](https://medium.com/js-dojo/5-vuex-plugins-for-your-next-vuejs-project-df9902a70de2)
1068 | * [Writing Vuex modules in neat Typescript classes](https://medium.com/coding-blocks/writing-vuex-modules-in-neat-typescript-classes-9bf7b505e7b5)
1069 |
1070 | ### Mobx
1071 |
1072 | * [Build A View-Framework-Free Data Layer Based on MobX — Integration With Vue (1)](https://itnext.io/build-a-view-framework-free-data-layer-based-on-mobx-integration-with-vue-1-8b524b86c7b8)
1073 |
1074 | ### 无渲染组件
1075 |
1076 | * [Renderless Components in Vue.js](https://adamwathan.me/renderless-components-in-vuejs/)
1077 | * [Building Renderless Components to Handle CRUD Operations in Vue.js](https://markus.oberlehner.net/blog/building-renderless-components-to-handle-crud-operations-in-vue/)
1078 |
1079 | #### 示例
1080 |
1081 | * [Renderless Calendar component](https://codesandbox.io/s/v65lx0xvy5)
1082 |
1083 | ### 文件结构
1084 |
1085 | * [How you can improve your workflow using the JavaScript console](https://medium.freecodecamp.org/how-you-can-improve-your-workflow-using-the-javascript-console-bdd7823a9472)
1086 | * [How to Structure a Vue.js Project](https://itnext.io/how-to-structure-a-vue-js-project-29e4ddc1aeeb)
1087 | * [Large-scale Vuex application structures](https://medium.com/3yourmind/large-scale-vuex-application-structures-651e44863e2f)
1088 | * [Vue.js Application Structure and CSS Architecture](https://markus.oberlehner.net/blog/vue-application-structure-and-css-architecture/)
1089 |
1090 | ### 提示技巧
1091 |
1092 | * [How To Build Vue Components Like A Pro 😎](https://blog.bitsrc.io/how-to-build-vue-components-like-a-pro-fd89fd4d524d)
1093 | * [Four tips for working with Vue.js](https://itnext.io/four-tips-for-working-with-vue-js-b362d97de852)
1094 | * [Tips from a Lowly VueJS Developer](https://medium.com/@denny.headrick/tips-from-a-lowly-vuejs-developer-381b6956aece)
1095 | * [Throttling and Debouncing Events with Vue.js and lodash](https://alligator.io/vuejs/lodash-throttle-debounce/)
1096 | * [Are partially applied functions in event handlers possible?](https://forum.vuejs.org/t/are-partially-applied-functions-in-event-handlers-possible/10187)
1097 | * [Vue.js — Considerations and Tricks](https://blog.webf.zone/vue-js-considerations-and-tricks-fa7e0e4bb7bb)
1098 | * [Six random issues and their solutions in VueJS.](https://medium.com/@stijlbreuk/six-random-issues-and-their-solutions-in-vuejs-b16d470a6462)
1099 | * [When VueJS Can't Help You](https://vuejsdevelopers.com/2017/05/01/vue-js-cant-help-head-body/)
1100 | * [Things that won’t work using Vue](https://winnercrespo.com/things-that-wont-work-using-vue/)
1101 | * [Tip#15 Delay execution with _.debounce](https://medium.com/vuejs-tips/tip-15-delay-execution-with-debounce-6a93b759bb06)
1102 | * [Handling API calls in Vue](https://medium.com/@imanhodjaev/handling-api-calls-in-vue-cf39747656ba)
1103 | * [Slide - Vue & REST API Patterns](https://speakerdeck.com/imanhodjaev/vue-and-rest-api-patterns)
1104 |
1105 | ### 路由
1106 |
1107 | * [Navigation Guards - Official](https://router.vuejs.org/guide/advanced/navigation-guards.html#global-guards)
1108 | * [Vue Router Navigation Guards with Vuex](https://serversideup.net/vue-router-navigation-guards-vuex/)
1109 |
1110 | ### Anti Patterns
1111 |
1112 | * [Chris Fritz - Vue.js Anti-Patterns (and How to Avoid Them)](http://www.fullstackradio.com/87)
1113 | * [Common mistakes to avoid while working with Vue.js](https://medium.freecodecamp.org/common-mistakes-to-avoid-while-working-with-vue-js-10e0b130925b)
1114 | * [Avoid This Common Anti-Pattern In Full-Stack Vue/Laravel Apps](https://vuejsdevelopers.com/2017/08/06/vue-js-laravel-full-stack-ajax/)
1115 | * [[Video] - VueNYC - Three Vue code smells, and what you can do about them - Matt Rothenberg (@mattrothenberg)](https://www.youtube.com/watch?v=z5UWVOeIsUQ)
1116 |
1117 | ### 视频 / 音频
1118 |
1119 | * [81: Evan You - Advanced Vue Component Design](https://player.fm/series/series-1401837/81-evan-you-advanced-vue-component-design)
1120 | * [7 Secret Patterns Vue Consultants Don’t Want You to Know](https://www.youtube.com/watch?v=7YZ5DwlLSt8)
1121 |
1122 | ### 仓库
1123 |
1124 | * [vue-enterprise-boilerplate](https://github.com/chrisvfritz/vue-enterprise-boilerplate)
1125 | * [7-secret-patterns](https://github.com/chrisvfritz/7-secret-patterns)
1126 | * [Vue.js-2-Design-Patterns-and-Best-Practices](https://github.com/PacktPublishing/Vue.js-2-Design-Patterns-and-Best-Practices)
1127 |
1128 | ### 付费
1129 |
1130 | * [Advanced Vue Component Design](https://adamwathan.me/advanced-vue-component-design/)
1131 | * [Advanced Vue.js Features from the Ground Up](https://frontendmasters.com/courses/advanced-vue/)
1132 |
1133 |
1134 | ### Typescript
1135 |
1136 | * [Vue + TypeScript: A Match Made in Your Code Editor](https://css-tricks.com/vue-typescript-a-match-made-in-your-code-editor/)
1137 | * [Writing Class-Based Components with Vue.js and TypeScript](https://alligator.io/vuejs/typescript-class-components/)
1138 |
1139 | ### Flowtype
1140 |
1141 | ### GraphQL
1142 |
1143 | * [Basics of GraphQL with Vue.js](https://medium.com/@lachlanmiller_52885/graphql-basics-and-practical-examples-with-vue-6b649b9685e0)
1144 |
1145 | ---
1146 |
1147 | ### Misc
1148 |
1149 | * [Creating an Interpose Vue component from a React implementation](https://itnext.io/creating-an-interpose-vue-component-from-a-react-implementation-80d367a695c6)
1150 | * [Composing computed properties in Vue.js](https://medium.com/@kevin_peters/composing-computed-properties-in-vue-js-87b4507af079)
1151 | * [4 AJAX Patterns For Vue.js Apps](https://medium.com/js-dojo/4-ajax-patterns-for-vue-js-apps-add915fc9168)
1152 | * [3 Code Splitting Patterns For VueJS and Webpack](https://medium.com/js-dojo/3-code-splitting-patterns-for-vuejs-and-webpack-b8fff1ea0ba4)
1153 | * [The easiest way to improve your Vue.js application. Part 1](https://codeburst.io/the-easiest-way-to-improve-your-vue-js-application-part-1-51f068652872)
1154 | * [Using JSX with Vue and Why You Should Care](https://scotch.io/tutorials/using-jsx-with-vue-and-why-you-should-care?utm_campaign=Revue%20newsletter&utm_medium=Newsletter&utm_source=Vue.js%20News)
1155 | * [Compound components](https://forum.vuejs.org/t/compound-components/30139)
1156 | * [Creating Multi-root Vue.js Components](https://zendev.com/2018/05/07/multi-root-vue-components.html)
1157 | * [Understanding Vue.js Reactivity in Depth with Object.defineProperty()](https://www.timo-ernst.net/blog/2017/07/26/understanding-vue-js-reactivity-depth-object-defineproperty/)
1158 | * [Templating in Vue: Separation of Concerns or Separation of Technology or something else?](https://medium.com/@s.molinari/templating-separation-of-concerns-or-separation-of-technology-or-something-else-123a3d41f0b4)
1159 | * [Stashing Vue components data](https://medium.com/@kelin2025/components-stash-f2e14603a874)
1160 | * [Creating Reusable Transitions in Vue](https://vuejsdevelopers.com/2018/02/26/vue-js-reusable-transitions/)
1161 | * [vue-advanced-workshop](https://github.com/d-levin/vue-advanced-workshop)
1162 | * [Do it with Elegance: How to Create Data-Driven User Interfaces in Vue](https://blog.rangle.io/how-to-create-data-driven-user-interfaces-in-vue/)
1163 | * [Creating Vue.js Component Instances Programmatically](https://css-tricks.com/creating-vue-js-component-instances-programmatically/)
1164 | * [Managing User Permissions in a Vue.js App](https://dzone.com/articles/managing-user-permissions-in-a-vuejs-app)
1165 | * [Render Functional Components in Vue.js](https://alligator.io/vuejs/render-functional-components/)
1166 | * [Looping through Object Properties](https://codingexplained.com/coding/front-end/vue-js/looping-object-properties)
1167 | * [Cancelling async operations in Vue.js](https://codeburst.io/cancelling-async-operations-in-vue-js-3d0f3c2de598)
1168 | * [Scoped styles with v-html](https://medium.com/@brockreece/scoped-styles-with-v-html-c0f6d2dc5d8e)
1169 | * [Pagination With Vuejs](https://medium.com/@obapelumi/pagination-with-vuejs-1f505ce8d15b)
1170 | * [What does the ‘h’ stand for in Vue’s render method?](https://css-tricks.com/what-does-the-h-stand-for-in-vues-render-method/)
1171 | * [How To Build Vue Components That Play Nice](https://vuejsdevelopers.com/2018/06/18/vue-components-play-nicely/)
1172 | * [Making responsive Vue components with ResizeObserver](https://itnext.io/making-adaptive-vue-components-with-resizeobserver-123b5ebb20ae)
1173 | * [An imperative guide to forms in Vue.js](https://blog.logrocket.com/an-imperative-guide-to-forms-in-vue-js-7536bfa374e0)
1174 | * [Vue.js: the good, the meh, and the ugly](https://medium.com/@Pier/vue-js-the-good-the-meh-and-the-ugly-82800bbe6684)
1175 | * [Dynamic Vue.js Layout Components](https://markus.oberlehner.net/blog/dynamic-vue-layout-components/)
1176 | * [Advanced Vue.js concepts: mixins, custom directives, filters, transitions, and state management](https://blog.logrocket.com/advanced-vue-js-concepts-mixins-custom-directives-filters-transitions-and-state-management-ca6955905156)
1177 | * [Introducing the Single Element Pattern](https://medium.freecodecamp.org/introducing-the-single-element-pattern-dfbd2c295c5d)
1178 | * [Control DOM Outside Your Vue.js App with portal-vue](https://alligator.io/vuejs/portal-vue/)
1179 | * [Add i18n and manage translations of a Vue.js powered website](https://medium.com/hypefactors/add-i18n-and-manage-translations-of-a-vue-js-powered-website-73b4511ca69c)
1180 | * [Managing Complex Waiting Experiences on Web UIs](https://medium.com/@fkadev/managing-complex-waiting-experiences-on-web-uis-29534d2d92a8)
1181 | * [Vue.js — Forms, components and considerations](https://blog.webf.zone/vue-js-forms-components-and-considerations-d81b3ffe9efb)
1182 |
1183 | ## 全栈 Vue 图书
1184 |
1185 | [](https://gumroad.com/a/462206067)
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # 确保脚本抛出遇到的错误
4 | set -e
5 |
6 | # 生成静态文件
7 | npm run docs:build
8 |
9 | # 进入生成的文件夹
10 | cd docs/.vuepress/dist
11 |
12 | # 如果是发布到自定义域名
13 | # echo 'www.example.com' > CNAME
14 |
15 | git init
16 | git add -A
17 | git commit -m 'deploy'
18 |
19 | # 如果发布到 https://.github.io
20 | # git push -f git@github.com:/.github.io.git master
21 |
22 | # 如果发布到 https://.github.io/
23 | git push -f git@github.com:ZYSzys/vue-patterns-cn.git master:gh-pages
24 |
25 | cd -
--------------------------------------------------------------------------------
/docs/.vuepress/components/GitHubStarButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | base: '/vue-patterns-cn/',
3 | title: 'Vue Patterns CN',
4 | description: '有用的Vue模式,技巧,提示和技巧以及有帮助的精选链接。',
5 | serviceWorker: true,
6 | themeConfig: {
7 | displayAllHeaders: true,
8 | lastUpdated: 'Last Updated',
9 | repo: 'ZYSzys/vue-patterns-cn',
10 | editLinks: true,
11 | locales: {
12 | '/': {
13 | lastUpdated: 'Last Updated',
14 | nav: [
15 | { text: '首页', link: '/' },
16 | { text: '文档', link: '/patterns/' },
17 | {
18 | text: '翻译',
19 | items: [{
20 | text: 'English',
21 | link: 'https://learn-vuejs.github.io/vue-patterns/',
22 | },
23 | {
24 | text: '繁體中文',
25 | link: 'https://github.com/yoyoys/vue-patterns-cht',
26 | },
27 | ],
28 | },
29 | ],
30 | sidebar: [
31 | ['/patterns/', '模式'],
32 | ['/useful-links/', '链接'],
33 | ['/sponsors/', '赞助商']
34 | ],
35 | },
36 | },
37 | },
38 | }
--------------------------------------------------------------------------------
/docs/.vuepress/public/learn-vue-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYSzys/vue-patterns-cn/c08fa0dd6451da40844214dbc2d352b1d6dbcd12/docs/.vuepress/public/learn-vue-logo.png
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /learn-vue-logo.png
4 | actionText: Get Started →
5 | actionLink: /patterns/
6 | ---
7 |
8 |
--------------------------------------------------------------------------------
/docs/patterns/README.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 |
3 | - [组件声明](#组件声明)
4 | - [单文件组件 (SFC) - 最常用](#单文件组件-sfc---最常用)
5 | - [字符串模板 (ES6模板字面值)](#字符串模板-es6模板字面值)
6 | - [渲染函数](#渲染函数)
7 | - [JSX](#jsx)
8 | - [vue-class-component](#vue-class-component)
9 | - [组件通信](#组件通信)
10 | - [Props 和 Events](#props和events)
11 | - [组件事件处理](#组件事件处理)
12 | - [组件条件渲染](#组件条件渲染)
13 | - [指令 (v-if / v-else / v-else-if / v-show)](#指令-v-if--v-else--v-else-if--v-show)
14 | - [JSX](#jsx-1)
15 | - [动态组件](#动态组件)
16 | - [带is属性的组件](#带is属性的组件)
17 | - [构建](#构建)
18 | - [基础构建](#基础构建)
19 | - [继承](#继承)
20 | - [混入](#混入)
21 | - [插槽 (默认)](#插槽-默认)
22 | - [具名插槽](#具名插槽)
23 | - [作用域插槽](#作用域插槽)
24 | - [渲染 Props](#渲染-props)
25 | - [传递 Props](#传递-props)
26 | - [高阶组件 (HOC)](#高阶组件-HOC)
27 | - [依赖注入](#依赖注入)
28 | - [Provide / Inject](#provide--inject)
29 | - [@Provide / @Inject Decorator](#provide--inject-decorator)
30 | - [错误处理](#错误处理)
31 | - [错误捕获钩子](#错误捕获钩子)
32 | - [高效提示](#高效提示)
33 | - [有帮助的链接](#有帮助的链接)
34 | - [风格指南](#风格指南)
35 | - [重构](#重构)
36 | - [状态管理](#状态管理)
37 | - [Vuex](#vuex)
38 | - [Mobx](#mobx)
39 | - [无渲染组件](#无渲染组件)
40 | - [文件结构](#文件结构)
41 | - [提示技巧](#提示技巧)
42 | - [路由](#路由)
43 | - [Anti Patterns](#anti-patterns)
44 | - [视频 / 音频](#视频--音频)
45 | - [仓库](#仓库)
46 | - [付费](#付费)
47 | - [Typescript](#typescript)
48 | - [Flowtype](#flowtype)
49 | - [GraphQL](#graphql)
50 | - [Misc](#misc)
51 | - [全栈Vue图书](#全栈-vue-图书)
52 |
53 | ## 组件声明
54 |
55 | ### [单文件组件 (SFC)](https://vuejs.org/v2/guide/single-file-components.html) - 最常用
56 |
57 | ```html
58 |
59 |
62 |
63 |
64 |
78 |
79 |
84 | ```
85 |
86 | ### 字符串模板 (ES6模板字面值)
87 |
88 | ```js
89 | Vue.component('my-btn', {
90 | template: `
91 |
94 | `,
95 | data() {
96 | return {
97 | text: 'Click me',
98 | };
99 | },
100 | methods: {
101 | handleClick() {
102 | console.log('clicked');
103 | },
104 | },
105 | });
106 | ```
107 |
108 | ### [渲染函数](https://vuejs.org/v2/guide/render-function.html)
109 |
110 | ```js
111 | Vue.component('my-btn', {
112 | data() {
113 | return {
114 | text: 'Click me',
115 | };
116 | },
117 | methods: {
118 | handleClick() {
119 | console.log('clicked');
120 | },
121 | },
122 | render(h) {
123 | return h('button', {
124 | attrs: {
125 | class: 'btn-primary'
126 | },
127 | on: {
128 | click: this.handleClick,
129 | },
130 | }, this.text);
131 | },
132 | });
133 | ```
134 |
135 | ### [JSX](https://vuejs.org/v2/guide/render-function.html#JSX)
136 |
137 | ```jsx
138 | Vue.component('my-btn', {
139 | data() {
140 | return {
141 | text: 'Click me',
142 | };
143 | },
144 | methods: {
145 | handleClick() {
146 | console.log('clicked');
147 | },
148 | },
149 | render() {
150 | return (
151 |
154 | );
155 | },
156 | });
157 | ```
158 |
159 | ### [vue-class-component](https://github.com/vuejs/vue-class-component)
160 |
161 | ```html
162 |
163 |
166 |
167 |
168 |
181 |
182 |
187 | ```
188 |
189 | #### 参考:
190 |
191 | * [Official - Single File Component](https://vuejs.org/v2/guide/single-file-components.html)
192 | * [Official - Render Functions & JSX](https://vuejs.org/v2/guide/render-function.html)
193 | * [7 Ways To Define A Component Template in VueJS](https://medium.com/js-dojo/7-ways-to-define-a-component-template-in-vuejs-c04e0c72900d)
194 |
195 | ## 组件通信
196 |
197 | ### Props和Events
198 |
199 | 基本上,vue组件遵循单向数据流,即props向下([参见官方指南](https://vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow) 和 event向上。
200 | props是只读数据,因此无法从子组件更改props。
201 | 当props更改时,子组件将自动重新渲染(props是响应性数据源)。
202 | 子组件只能将event事件直接发送到父组件,因此父组件可以更改`data`,映射到子组件的`props`。
203 |
204 | ```html
205 |
206 |
207 |
208 |
209 |
217 | ```
218 |
219 | ```html
220 |
221 |
222 |
223 |
224 |
240 | ```
241 |
242 | #### 参考:
243 |
244 | * [Official - Props](https://vuejs.org/v2/guide/components-props.html)
245 | * [Vue.js Component Communication Patterns](https://alligator.io/vuejs/component-communication/)
246 | * [Creating Custom Inputs With Vue.js](https://www.smashingmagazine.com/2017/08/creating-custom-inputs-vue-js/)
247 | * [Vue Sibling Component Communication](https://vegibit.com/vue-sibling-component-communication/)
248 | * [Managing State in Vue.js](https://medium.com/fullstackio/managing-state-in-vue-js-23a0352b1c87)
249 | * [Vue.js communication part 2: parent-child components](https://gambardella.info/2017/09/13/vue-js-communication-part-2-parent-child-components/)
250 |
251 | ## 组件事件处理
252 |
253 | #### 参考:
254 |
255 | * [Official - Custom Events](https://vuejs.org/v2/guide/components-custom-events.html)
256 | * [Leveraging Vue events to reduce prop declarations](https://itnext.io/leveraging-vue-events-to-reduce-prop-declarations-e38f5dce2aaf)
257 | * [Vue.js Component Hooks as Events](https://alligator.io/vuejs/component-event-hooks/)
258 | * [Creating a Global Event Bus with Vue.js](https://alligator.io/vuejs/global-event-bus/)
259 | * [Vue.js Event Bus + Promises](https://medium.com/@jesusgalvan/vue-js-event-bus-promises-f83e73a81d72)
260 |
261 | ## 组件条件渲染
262 |
263 | ### 指令 (`v-if` / `v-else` / `v-else-if` / `v-show`)
264 |
265 | `v-if`
266 |
267 | ```html
268 | Render only if v-if condition is true
269 | ```
270 |
271 | `v-if` and `v-else`
272 |
273 | ```html
274 | Render only if v-if condition is true
275 | Render only if v-if condition is false
276 | ```
277 |
278 | `v-else-if`
279 |
280 | ```html
281 | Render only if `type` is equal to `A`
282 | Render only if `type` is equal to `B`
283 | Render only if `type` is equal to `C`
284 | Render if `type` is not `A` or `B` or `C`
285 | ```
286 |
287 | `v-show`
288 |
289 | ```html
290 | Always rendered, but it should be visible only if `v-show` conditions is true
291 | ```
292 |
293 | 如果要有条件地渲染多个元素,
294 | 你可以在``元素上使用指令(`v-if` /`v-else` /`v-else-if` /`v-show`)。
295 | 请注意,``元素实际上并未渲染为DOM。 它是一个不可见的封装。
296 |
297 | ```html
298 |
299 | All the elements
300 | will be rendered into DOM
301 | except `template` element
302 |
303 | ```
304 |
305 | ### JSX
306 |
307 | 如果在vue应用程序中使用JSX,则可以应用所有技术,例如`if else`和`switch case`语句以及`ternary`和`logical`运算符。
308 |
309 | `if else` 声明
310 |
311 | ```jsx
312 | export default {
313 | data() {
314 | return {
315 | isTruthy: true,
316 | };
317 | },
318 | render(h) {
319 | if (this.isTruthy) {
320 | return Render value is true
;
321 | } else {
322 | return Render value is false
;
323 | }
324 | },
325 | };
326 | ```
327 |
328 | `switch case` 声明
329 |
330 | ```jsx
331 | import Info from './Info';
332 | import Warning from './Warning';
333 | import Error from './Error';
334 | import Success from './Success';
335 |
336 | export default {
337 | data() {
338 | return {
339 | type: 'error',
340 | };
341 | },
342 | render(h) {
343 | switch (this.type) {
344 | case 'info':
345 | return ;
346 | case 'warning':
347 | return ;
348 | case 'error':
349 | return ;
350 | default:
351 | return ;
352 | }
353 | },
354 | };
355 | ```
356 |
357 | 或者你可以使用 `object` 映射来简化 `switch case`
358 |
359 | ```jsx
360 | import Info from './Info';
361 | import Warning from './Warning';
362 | import Error from './Error';
363 | import Success from './Success';
364 |
365 | const COMPONENT_MAP = {
366 | info: Info,
367 | warning: Warning,
368 | error: Error,
369 | success: Success,
370 | };
371 |
372 | export default {
373 | data() {
374 | return {
375 | type: 'error',
376 | };
377 | },
378 | render(h) {
379 | const Comp = COMPONENT_MAP[this.type || 'success'];
380 |
381 | return ;
382 | },
383 | };
384 | ```
385 |
386 | 三元运算符
387 |
388 | ```jsx
389 | export default {
390 | data() {
391 | return {
392 | isTruthy: true,
393 | };
394 | },
395 | render(h) {
396 | return (
397 |
398 | {this.isTruthy ? (
399 |
Render value is true
400 | ) : (
401 | Render value is false
402 | )}
403 |
404 | );
405 | },
406 | };
407 | ```
408 |
409 | 逻辑运算符
410 |
411 | ```jsx
412 | export default {
413 | data() {
414 | return {
415 | isLoading: true,
416 | };
417 | },
418 | render(h) {
419 | return {this.isLoading &&
Loading ...
};
420 | },
421 | };
422 | ```
423 | #### 参考
424 |
425 | * [Official - Conditional Rendering](https://vuejs.org/v2/guide/conditional.html)
426 | * [Difference Between v-if and v-show [With Video at End]](https://dzone.com/articles/difference-between-v-if-and-v-show-with-a-video)
427 |
428 | ## 动态组件
429 |
430 | ### 带is属性的组件
431 |
432 | * [Example 1](https://jsfiddle.net/chrisvfritz/o3nycadu/)
433 | * [Example 2](https://jsfiddle.net/chrisvfritz/b2qj69o1/)
434 | * [Example 3](https://alligator.io/vuejs/dynamic-components/)
435 |
436 | ```html
437 |
438 | ```
439 |
440 | 在上面的代码示例中,如果在``中呈现不同的组件,则将销毁渲染的组件。 如果你想让组件保持它们的实例而不在``标签中被销毁,你可以将``标签包装在``标签中,如下所示:
441 |
442 | ```html
443 |
444 |
445 |
446 | ```
447 |
448 | #### 参考
449 |
450 | * [Official - Dynamic Components](https://vuejs.org/v2/guide/components.html#Dynamic-Components)
451 | * [Official - Dynamic & Async Components](https://vuejs.org/v2/guide/components-dynamic-async.html)
452 | * [Dynamic Component Templates with Vue.js](https://medium.com/scrumpy/dynamic-component-templates-with-vue-js-d9236ab183bb)
453 |
454 | ## 构建
455 |
456 | #### 库
457 |
458 | * [Proppy - Functional props composition for components](https://proppyjs.com/)
459 |
460 | ### 基础构建
461 |
462 | ```html
463 |
464 |
465 |
466 |
467 |
468 |
469 |
478 | ```
479 |
480 | #### References
481 |
482 | * [Official - Composing with Components](https://vuejs.org/v2/guide/#Composing-with-Components)
483 |
484 | ### 继承
485 |
486 | 当你想要继承单个vue组件时
487 |
488 | ```html
489 |
490 |
493 |
494 |
495 |
503 | ```
504 |
505 | #### 参考:
506 |
507 | * [Official - extends](https://vuejs.org/v2/api/#extends)
508 | * [Extending VueJS Components](https://medium.com/js-dojo/extending-vuejs-components-42fefefc688b)
509 |
510 | ### 混入
511 |
512 | ```js
513 | // closableMixin.js
514 | export default {
515 | props: {
516 | isOpen: {
517 | default: true
518 | }
519 | },
520 | data: function() {
521 | return {
522 | shown: this.isOpen
523 | }
524 | },
525 | methods: {
526 | hide: function() {
527 | this.shown = false;
528 | },
529 | show: function() {
530 | this.shown = true;
531 | },
532 | toggle: function() {
533 | this.shown = !this.shown;
534 | }
535 | }
536 | }
537 | ```
538 |
539 | ```html
540 |
541 |
542 | {{text}}
543 |
544 |
545 |
546 |
547 |
555 | ```
556 |
557 | #### 参考:
558 |
559 | * [Official - mixins](https://vuejs.org/v2/guide/mixins.html)
560 | * [Practical use of Components and Mixins in Vue JS](http://www.qcode.in/practical-use-of-components-and-mixins-in-vue-js/)
561 |
562 |
563 | ### 插槽 (默认)
564 |
565 | ```html
566 |
567 |
570 |
571 |
572 |
577 | ```
578 |
579 | ```html
580 |
581 |
582 |
583 | Login
584 |
585 |
586 |
587 |
596 | ```
597 |
598 | #### 参考:
599 |
600 | * [Official - Slot Content](https://vuejs.org/v2/guide/components-slots.html#Slot-Content)
601 | * [Understanding Component Slots with Vue.js](https://alligator.io/vuejs/component-slots/)
602 | * [Composing Custom Elements With Slots And Named Slots](https://alligator.io/web-components/composing-slots-named-slots/)
603 | * [Writing Abstract Components with Vue.js](https://alligator.io/vuejs/vue-abstract-components/)
604 |
605 | ### 具名插槽
606 |
607 | BaseLayout.vue
608 |
609 | ```html
610 |
611 |
614 |
615 |
616 |
617 |
620 |
621 | ```
622 |
623 | App.vue
624 |
625 | ```html
626 |
627 |
628 | Here might be a page title
629 |
630 |
631 | A paragraph for the main content.
632 | And another one.
633 |
634 |
635 | Here's some contact info
636 |
637 |
638 | ```
639 |
640 | #### 参考
641 |
642 | * [Official - Named Slots](https://vuejs.org/v2/guide/components-slots.html#Named-Slots)
643 |
644 | ### 作用域插槽
645 |
646 | ```html
647 |
648 |
649 | -
653 |
654 |
655 |
656 | {{ todo.text }}
657 |
658 |
659 |
660 |
661 |
662 |
673 | ```
674 |
675 | ```html
676 |
677 |
678 |
679 | ✓
680 | {{ todo.text }}
681 |
682 |
683 |
684 |
685 |
704 | ```
705 |
706 | #### 参考:
707 |
708 | * [Official - Scoped Slots](https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots)
709 | * [Getting Your Head Around Vue.js Scoped Slots](https://medium.com/js-dojo/getting-your-head-around-vue-js-scoped-slots-281bf82a1e4e)
710 | * [Understanding scoped slots in Vue.js](https://medium.com/corebuild-software/understanding-scoped-slots-in-vue-js-db5315a42391)
711 | * [Scoped Component Slots in Vue.js](https://alligator.io/vuejs/scoped-component-slots/)
712 | * [The Trick to Understanding Scoped Slots in Vue.js](https://adamwathan.me/the-trick-to-understanding-scoped-slots-in-vuejs/)
713 | * [The Power of Scoped Slots in Vue](https://pineco.de/power-scoped-slots-vue/)
714 | * [Building a list keyboard control component with Vue.js and scoped slots](https://medium.com/@tkwebdev/building-a-list-keyboard-control-component-with-vue-js-and-scoped-slots-c74db4fcf84f)
715 |
716 | ### 渲染 Props
717 |
718 | 在大多数情况下,您可以使用 `scoped` 插槽而不是渲染 `props`。 但是,在某些情况下它可能有用。
719 |
720 | 单文件组件(`SFC`)中
721 |
722 | ```html
723 |
724 |
725 |
726 |
727 |
728 |
729 |
747 |
754 | ```
755 |
756 | `JSX`中
757 |
758 | ```js
759 | const Mouse = {
760 | name: "Mouse",
761 | props: {
762 | render: {
763 | type: Function,
764 | required: true
765 | }
766 | },
767 | data() {
768 | return {
769 | x: 0,
770 | y: 0
771 | };
772 | },
773 | methods: {
774 | handleMouseMove(event) {
775 | this.x = event.clientX;
776 | this.y = event.clientY;
777 | }
778 | },
779 | render(h) {
780 | return (
781 |
782 | {this.$props.render(this)}
783 |
784 | );
785 | }
786 | };
787 |
788 | export default Mouse;
789 | ```
790 |
791 | #### 参考:
792 |
793 | * [Official - Render Functions & JSX](https://vuejs.org/v2/guide/render-function.html)
794 | * [Leveraging Render Props in Vue](https://medium.com/@dillonchanis/leveraging-render-props-in-vue-7eb9a19c262d)
795 | * [Use a Vue.js Render Prop!](https://medium.com/js-dojo/use-a-vue-js-render-prop-98880bc44e05)
796 |
797 | ## 传递 Props
798 |
799 | 有时,你可能希望将 `props`和 `listeners`传递给子组件,而无需声明所有子组件的 `props`。
800 | 您可以在子组件中绑定 `$attrs` 和 `$listeners`,并将 [`inheritAttrs` 设置为 `false`](https://vuejs.org/v2/api/#inheritAttrs)(否则div和子组件都将接收属性)
801 |
802 | 子组件中:
803 | ```html
804 |
805 |
806 |
{{title}}
807 |
808 |
809 |
810 |
811 |
823 | ```
824 |
825 | 在父组件中,你可以这样做:
826 | ```html
827 |
828 |
833 |
834 |
835 |
836 |
850 | ```
851 |
852 | #### 参考:
853 |
854 | * [Transparent Wrapper Components in Vue](https://zendev.com/2018/05/31/transparent-wrapper-components-in-vue.html)
855 |
856 | ## 高阶组件 (HOC)
857 |
858 | #### 参考:
859 |
860 | * [Higher Order Components in Vue.js](https://medium.com/bethink-pl/higher-order-components-in-vue-js-a79951ac9176)
861 | * [Do we need Higher Order Components in Vue.js?](https://medium.com/bethink-pl/do-we-need-higher-order-components-in-vue-js-87c0aa608f48)
862 | * [Higher-Order Components in Vue.js](https://medium.com/tldr-tech/higher-order-components-in-vue-js-38b500c6d49f)
863 |
864 | ## 依赖注入
865 |
866 | Vue支持依赖/注入机制,无论组件层次结构有多深,只要它们位于同一父链中,就可以将`object`提供给它的所有后代。 请注意,`provide`和`inject`绑定不是响应式的,除非你传递一个观察对象。
867 |
868 | ```html
869 |
870 |
871 |
872 |
873 |
874 | ```
875 |
876 | 在上面的示例组件层次结构中,为了从`parent-component`派生数据,您应该将数据(对象)作为`props`传递给`child-component`和`grand-child-component`。 但是,如果`parent-component``提供`数据(对象),`grand-child-component`只能从`parent-component`定义`inject`提供的对象。
877 |
878 | #### 参考:
879 |
880 | * [Official API](https://vuejs.org/v2/api/#provide-inject)
881 | * [Official Guide](https://vuejs.org/v2/guide/components-edge-cases.html#Dependency-Injection)
882 | * [Component Communication](https://alligator.io/vuejs/component-communication/#provide--inject)
883 | * [Dependency Injection in Vue.js App with TypeScript](https://blog.kloud.com.au/2017/03/22/dependency-injection-in-vuejs-app-with-typescript/)
884 |
885 | ### Provide / Inject
886 |
887 | ```js
888 | // ParentComponent.vue
889 |
890 | export default {
891 | provide: {
892 | theme: {
893 | primaryColor: 'blue',
894 | },
895 | },
896 | };
897 | ```
898 |
899 | ```html
900 | // GrandChildComponent.vue
901 |
902 |
903 |
906 |
907 |
908 |
919 | ```
920 |
921 | ### [@Provide / @Inject Decorator](https://github.com/kaorun343/vue-property-decorator)
922 |
923 | ```js
924 | // ParentComponent.vue
925 |
926 | import { Component, Vue, Provide } from 'vue-property-decorator';
927 |
928 | @Component
929 | export class ParentComponent extends Vue {
930 | @Provide
931 | theme = {
932 | primaryColor: 'blue',
933 | };
934 | }
935 | ```
936 |
937 | ```html
938 | // GrandChildComponent.vue
939 |
940 |
941 |
944 |
945 |
946 |
956 | ```
957 |
958 | ## 错误处理
959 |
960 | ### 错误捕获钩子
961 |
962 | ```js
963 | export default {
964 | name: 'ErrorBoundary',
965 | data() {
966 | return {
967 | error: false,
968 | errorMessage: '',
969 | };
970 | },
971 | errorCaptured (err, vm, info) {
972 | this.error = true;
973 | this.errorMessage = `${err.stack}\n\nfound in ${info} of component`;
974 |
975 | return false;
976 | },
977 | render (h) {
978 | if (this.error) {
979 | return h('pre', { style: { color: 'red' }}, this.errorMessage);
980 | }
981 |
982 | return this.$slots.default[0]
983 | }
984 | };
985 | ```
986 |
987 | ```
988 |
989 |
990 |
991 | ```
992 |
993 | #### Examples
994 |
995 | * [Example 1](https://jsfiddle.net/Linusborg/z84wspcg/)
996 |
997 | #### 参考
998 |
999 | * [Handling Errors in Vue with Error Boundaries](https://medium.com/@dillonchanis/handling-errors-in-vue-with-error-boundaries-91f6ead0093b)
1000 |
1001 | ## 高效提示
1002 |
1003 | watch on create
1004 |
1005 | ```js
1006 | // don't
1007 | created() {
1008 | this.fetchUserList();
1009 | },
1010 | watch: {
1011 | searchText: 'fetchUserList',
1012 | }
1013 | ```
1014 |
1015 | ```js
1016 | // do
1017 | watch: {
1018 | searchText: {
1019 | handler: 'fetchUserList',
1020 | immediate: true,
1021 | }
1022 | }
1023 | ```
1024 |
--------------------------------------------------------------------------------
/docs/sponsors/README.md:
--------------------------------------------------------------------------------
1 | [](https://gumroad.com/a/462206067)
--------------------------------------------------------------------------------
/docs/useful-links/README.md:
--------------------------------------------------------------------------------
1 | ### 风格指南
2 |
3 | * [Official - Style Guide](https://vuejs.org/v2/style-guide/)
4 | * [Vue.js Component Style Guide](https://github.com/pablohpsilva/vuejs-component-style-guide)
5 |
6 | ### 重构
7 |
8 | * [Refactoring Vue: Cleaning Up a List of Posts With Better Component Splitting and More ES6](https://mattstauffer.com/blog/refactoring-vue-cleaning-up-a-list-of-posts-with-better-component-splitting-and-more-es6/?utm_campaign=Revue%20newsletter&utm_medium=Newsletter&utm_source=Vue.js%20Feed)
9 | * [Clean up your Vue modules with ES6 Arrow Functions](https://gist.github.com/JacobBennett/7b32b4914311c0ac0f28a1fdc411b9a7)
10 | * [Examples of Vue’s Clean Code](https://webdesign.tutsplus.com/tutorials/examples-of-vues-clean-code--cms-29619)
11 | * [Optimizing Performance with Computed Properties](https://codingexplained.com/coding/front-end/vue-js/optimizing-performance-computed-properties)
12 | * [Simplify Your Components with Computed Setters](https://tahazsh.com/vuebyte-computed-setters)
13 |
14 | ### 状态管理
15 |
16 | * [Managing State in Vue.js](https://medium.com/fullstackio/managing-state-in-vue-js-23a0352b1c87)
17 |
18 | ### Vuex
19 |
20 | * [Decouple Vuex modules with the Mediator pattern](https://itnext.io/decouple-vuex-actions-with-the-mediator-pattern-58a8879de1b4)
21 | * [Vuex getters are great, but don’t overuse them](https://codeburst.io/vuex-getters-are-great-but-dont-overuse-them-9c946689b414)
22 | * [Reusable Vuex Mutation Functions](https://itnext.io/reusable-vuex-mutation-functions-9b4920aa737b)
23 | * [A pattern to handle ajax requests in Vuex](https://medium.com/@lachlanmiller_52885/a-pattern-to-handle-ajax-requests-in-vuex-2d69bc2f8984)
24 | * [[vuex Mutations] Single Changes vs. Single Responsibility](https://forum.vuejs.org/t/vuex-mutations-single-changes-vs-single-responsibility/16396)
25 | * [Components and How They Interact in Vue and Vuex](https://dzone.com/articles/how-do-components-interact-in-vue-and-what-is-vuex)
26 | * [Why VueX Is The Perfect Interface Between Frontend and API](https://codeburst.io/why-vuex-is-the-perfect-interface-between-frontend-and-api-271d92161709)
27 | * [Composing actions with Vuex](https://codeburst.io/composing-actions-with-vuex-b63466264a37)
28 | * [How to Build Complex, Large-Scale Vue.js Apps With Vuex](https://code.tutsplus.com/tutorials/how-to-build-complex-large-scale-vuejs-applications-with-vuex--cms-30952)
29 | * [Should I Store This Data in Vuex?](https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/)
30 | * [Anyway, this is how to use v-model with Vuex. Computed setter in action.](https://itnext.io/anyway-this-is-how-to-use-v-model-with-vuex-computed-setter-in-action-320eb682c976)
31 | * [5 Vuex Plugins For Your Next VueJS Project](https://medium.com/js-dojo/5-vuex-plugins-for-your-next-vuejs-project-df9902a70de2)
32 | * [Writing Vuex modules in neat Typescript classes](https://medium.com/coding-blocks/writing-vuex-modules-in-neat-typescript-classes-9bf7b505e7b5)
33 |
34 | ### Mobx
35 |
36 | * [Build A View-Framework-Free Data Layer Based on MobX — Integration With Vue (1)](https://itnext.io/build-a-view-framework-free-data-layer-based-on-mobx-integration-with-vue-1-8b524b86c7b8)
37 |
38 | ### 无渲染组件
39 |
40 | * [Renderless Components in Vue.js](https://adamwathan.me/renderless-components-in-vuejs/)
41 | * [Building Renderless Components to Handle CRUD Operations in Vue.js](https://markus.oberlehner.net/blog/building-renderless-components-to-handle-crud-operations-in-vue/)
42 |
43 | #### 示例
44 |
45 | * [Renderless Calendar component](https://codesandbox.io/s/v65lx0xvy5)
46 |
47 | ### 文件结构
48 |
49 | * [How you can improve your workflow using the JavaScript console](https://medium.freecodecamp.org/how-you-can-improve-your-workflow-using-the-javascript-console-bdd7823a9472)
50 | * [How to Structure a Vue.js Project](https://itnext.io/how-to-structure-a-vue-js-project-29e4ddc1aeeb)
51 | * [Large-scale Vuex application structures](https://medium.com/3yourmind/large-scale-vuex-application-structures-651e44863e2f)
52 | * [Vue.js Application Structure and CSS Architecture](https://markus.oberlehner.net/blog/vue-application-structure-and-css-architecture/)
53 |
54 | ### 提示技巧
55 |
56 | * [How To Build Vue Components Like A Pro 😎](https://blog.bitsrc.io/how-to-build-vue-components-like-a-pro-fd89fd4d524d)
57 | * [Four tips for working with Vue.js](https://itnext.io/four-tips-for-working-with-vue-js-b362d97de852)
58 | * [Tips from a Lowly VueJS Developer](https://medium.com/@denny.headrick/tips-from-a-lowly-vuejs-developer-381b6956aece)
59 | * [Throttling and Debouncing Events with Vue.js and lodash](https://alligator.io/vuejs/lodash-throttle-debounce/)
60 | * [Are partially applied functions in event handlers possible?](https://forum.vuejs.org/t/are-partially-applied-functions-in-event-handlers-possible/10187)
61 | * [Vue.js — Considerations and Tricks](https://blog.webf.zone/vue-js-considerations-and-tricks-fa7e0e4bb7bb)
62 | * [Six random issues and their solutions in VueJS.](https://medium.com/@stijlbreuk/six-random-issues-and-their-solutions-in-vuejs-b16d470a6462)
63 | * [When VueJS Can't Help You](https://vuejsdevelopers.com/2017/05/01/vue-js-cant-help-head-body/)
64 | * [Things that won’t work using Vue](https://winnercrespo.com/things-that-wont-work-using-vue/)
65 | * [Tip#15 Delay execution with \_.debounce](https://medium.com/vuejs-tips/tip-15-delay-execution-with-debounce-6a93b759bb06)
66 | * [Handling API calls in Vue](https://medium.com/@imanhodjaev/handling-api-calls-in-vue-cf39747656ba)
67 | * [Slide - Vue & REST API Patterns](https://speakerdeck.com/imanhodjaev/vue-and-rest-api-patterns)
68 |
69 | ### 路由
70 |
71 | * [Navigation Guards - Official](https://router.vuejs.org/guide/advanced/navigation-guards.html#global-guards)
72 | * [Vue Router Navigation Guards with Vuex](https://serversideup.net/vue-router-navigation-guards-vuex/)
73 |
74 | ### Anti Patterns
75 |
76 | * [Chris Fritz - Vue.js Anti-Patterns (and How to Avoid Them)](http://www.fullstackradio.com/87)
77 | * [Common mistakes to avoid while working with Vue.js](https://medium.freecodecamp.org/common-mistakes-to-avoid-while-working-with-vue-js-10e0b130925b)
78 | * [Avoid This Common Anti-Pattern In Full-Stack Vue/Laravel Apps](https://vuejsdevelopers.com/2017/08/06/vue-js-laravel-full-stack-ajax/)
79 | * [[Video] - VueNYC - Three Vue code smells, and what you can do about them - Matt Rothenberg (@mattrothenberg)](https://www.youtube.com/watch?v=z5UWVOeIsUQ)
80 |
81 | ### 视频 / 音频
82 |
83 | * [81: Evan You - Advanced Vue Component Design](https://player.fm/series/series-1401837/81-evan-you-advanced-vue-component-design)
84 | * [7 Secret Patterns Vue Consultants Don’t Want You to Know](https://www.youtube.com/watch?v=7YZ5DwlLSt8)
85 |
86 | ### 仓库
87 |
88 | * [vue-enterprise-boilerplate](https://github.com/chrisvfritz/vue-enterprise-boilerplate)
89 | * [7-secret-patterns](https://github.com/chrisvfritz/7-secret-patterns)
90 | * [Vue.js-2-Design-Patterns-and-Best-Practices](https://github.com/PacktPublishing/Vue.js-2-Design-Patterns-and-Best-Practices)
91 |
92 | ### 付费
93 |
94 | * [Advanced Vue Component Design](https://adamwathan.me/advanced-vue-component-design/)
95 | * [Advanced Vue.js Features from the Ground Up](https://frontendmasters.com/courses/advanced-vue/)
96 |
97 |
98 | ### Typescript
99 |
100 | * [Vue + TypeScript: A Match Made in Your Code Editor](https://css-tricks.com/vue-typescript-a-match-made-in-your-code-editor/)
101 | * [Writing Class-Based Components with Vue.js and TypeScript](https://alligator.io/vuejs/typescript-class-components/)
102 |
103 | ### Flowtype
104 |
105 | ### GraphQL
106 |
107 | * [Basics of GraphQL with Vue.js](https://medium.com/@lachlanmiller_52885/graphql-basics-and-practical-examples-with-vue-6b649b9685e0)
108 |
109 | ---
110 |
111 | ### Misc
112 |
113 | * [Creating an Interpose Vue component from a React implementation](https://itnext.io/creating-an-interpose-vue-component-from-a-react-implementation-80d367a695c6)
114 | * [Composing computed properties in Vue.js](https://medium.com/@kevin_peters/composing-computed-properties-in-vue-js-87b4507af079)
115 | * [4 AJAX Patterns For Vue.js Apps](https://medium.com/js-dojo/4-ajax-patterns-for-vue-js-apps-add915fc9168)
116 | * [3 Code Splitting Patterns For VueJS and Webpack](https://medium.com/js-dojo/3-code-splitting-patterns-for-vuejs-and-webpack-b8fff1ea0ba4)
117 | * [The easiest way to improve your Vue.js application. Part 1](https://codeburst.io/the-easiest-way-to-improve-your-vue-js-application-part-1-51f068652872)
118 | * [Using JSX with Vue and Why You Should Care](https://scotch.io/tutorials/using-jsx-with-vue-and-why-you-should-care?utm_campaign=Revue%20newsletter&utm_medium=Newsletter&utm_source=Vue.js%20News)
119 | * [Compound components](https://forum.vuejs.org/t/compound-components/30139)
120 | * [Creating Multi-root Vue.js Components](https://zendev.com/2018/05/07/multi-root-vue-components.html)
121 | * [Understanding Vue.js Reactivity in Depth with Object.defineProperty()](https://www.timo-ernst.net/blog/2017/07/26/understanding-vue-js-reactivity-depth-object-defineproperty/)
122 | * [Templating in Vue: Separation of Concerns or Separation of Technology or something else?](https://medium.com/@s.molinari/templating-separation-of-concerns-or-separation-of-technology-or-something-else-123a3d41f0b4)
123 | * [Stashing Vue components data](https://medium.com/@kelin2025/components-stash-f2e14603a874)
124 | * [Creating Reusable Transitions in Vue](https://vuejsdevelopers.com/2018/02/26/vue-js-reusable-transitions/)
125 | * [vue-advanced-workshop](https://github.com/d-levin/vue-advanced-workshop)
126 | * [Do it with Elegance: How to Create Data-Driven User Interfaces in Vue](https://blog.rangle.io/how-to-create-data-driven-user-interfaces-in-vue/)
127 | * [Creating Vue.js Component Instances Programmatically](https://css-tricks.com/creating-vue-js-component-instances-programmatically/)
128 | * [Managing User Permissions in a Vue.js App](https://dzone.com/articles/managing-user-permissions-in-a-vuejs-app)
129 | * [Render Functional Components in Vue.js](https://alligator.io/vuejs/render-functional-components/)
130 | * [Looping through Object Properties](https://codingexplained.com/coding/front-end/vue-js/looping-object-properties)
131 | * [Cancelling async operations in Vue.js](https://codeburst.io/cancelling-async-operations-in-vue-js-3d0f3c2de598)
132 | * [Scoped styles with v-html](https://medium.com/@brockreece/scoped-styles-with-v-html-c0f6d2dc5d8e)
133 | * [Pagination With Vuejs](https://medium.com/@obapelumi/pagination-with-vuejs-1f505ce8d15b)
134 | * [What does the ‘h’ stand for in Vue’s render method?](https://css-tricks.com/what-does-the-h-stand-for-in-vues-render-method/)
135 | * [How To Build Vue Components That Play Nice](https://vuejsdevelopers.com/2018/06/18/vue-components-play-nicely/)
136 | * [Making responsive Vue components with ResizeObserver](https://itnext.io/making-adaptive-vue-components-with-resizeobserver-123b5ebb20ae)
137 | * [An imperative guide to forms in Vue.js](https://blog.logrocket.com/an-imperative-guide-to-forms-in-vue-js-7536bfa374e0)
138 | * [Vue.js: the good, the meh, and the ugly](https://medium.com/@Pier/vue-js-the-good-the-meh-and-the-ugly-82800bbe6684)
139 | * [Dynamic Vue.js Layout Components](https://markus.oberlehner.net/blog/dynamic-vue-layout-components/)
140 | * [Advanced Vue.js concepts: mixins, custom directives, filters, transitions, and state management](https://blog.logrocket.com/advanced-vue-js-concepts-mixins-custom-directives-filters-transitions-and-state-management-ca6955905156)
141 | * [Introducing the Single Element Pattern](https://medium.freecodecamp.org/introducing-the-single-element-pattern-dfbd2c295c5d)
142 | * [Control DOM Outside Your Vue.js App with portal-vue](https://alligator.io/vuejs/portal-vue/)
143 | * [Add i18n and manage translations of a Vue.js powered website](https://medium.com/hypefactors/add-i18n-and-manage-translations-of-a-vue-js-powered-website-73b4511ca69c)
144 | * [Managing Complex Waiting Experiences on Web UIs](https://medium.com/@fkadev/managing-complex-waiting-experiences-on-web-uis-29534d2d92a8)
145 | * [Vue.js — Forms, components and considerations](https://blog.webf.zone/vue-js-forms-components-and-considerations-d81b3ffe9efb)
146 |
--------------------------------------------------------------------------------
/generate-toc.md:
--------------------------------------------------------------------------------
1 | # To generate table of contents
2 |
3 | ```js
4 | var toc = '';
5 |
6 | readme.querySelectorAll('h2, h3')
7 | .forEach((elem) => {
8 | const { tagName, innerText } = elem;
9 | const anchor = elem.querySelector('a').getAttribute('href');
10 |
11 | if (tagName === 'H2') {
12 | toc += `- [${innerText}](${anchor})\n`;
13 | }
14 |
15 | if (tagName === 'H3') {
16 | toc += ` - [${innerText}](${anchor})\n`;
17 | }
18 | });
19 |
20 | console.log(toc);
21 | ```
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-patterns-cn",
3 | "version": "1.0.0",
4 | "description": "vue-patterns-cn",
5 | "main": "",
6 | "repository": "https://github.com/ZYSzys/vue-patterns-cn",
7 | "author": "ZYSzys ",
8 | "license": "MIT",
9 | "private": false,
10 | "scripts": {
11 | "docs:dev": "vuepress dev docs",
12 | "docs:build": "vuepress build docs"
13 | },
14 | "devDependencies": {
15 | "vuepress": "0.14.2"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------