├── .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 | 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 | 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 | 218 | 219 | 227 | ``` 228 | 229 | ```html 230 | 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 | 你可以在`