英文原版:learn-vuejs

中文翻譯:yoyoys

此頁面集結了許多有用的 Vue 實作模式、技術、技巧、以及有幫助的參考連結。

  • Vue 實作模式 (learn-vuejs) 中文版

    • 元件宣告

      • 單文件組件(Single File Component, SFC) - 最為常見
      • 字串樣板 (String Template) (或是 es6 樣板字面值 (Template Literal)))
      • 渲染函式 (Render Function)
      • JSX
      • vue-class-component (使用 es6 classes)
        • 參考連結
    • 元件條件渲染 (Component Conditional Rendering)
      • 指令 (Directives) (v-if / v-else / v-else-if / v-show)
      • JSX
    • 動態元件
    • 元件組合
      • 基本組合 (Basic Composition)
      • 繼承 (Extends)
      • 混入 (Mixins)
      • 預設插槽 (Slots (Default))
      • 具名插槽(Named Slots)
      • 作用域插槽 (Scoped Slots)
      • 渲染屬性 (Render Props)
    • 參數傳遞 (Passing Props)
    • 高優先元件 (Higher Order Component, HOC)
    • 相依注入 (Dependency injection)
      • 提供 與 注入 (Provide / Inject)
      • 注入裝飾器模式 (@Provide / @Inject Decorator)
    • 錯誤處理 (Handling Errors)
      • errorCaptured 事件
    • 生產力小技巧
    • 有用的連結
      • 組建間的溝通
      • 重構技巧
      • Vuex
      • Mobx
      • 不須渲染的元件 (Renderless Component)
      • 目錄結構
      • 小技巧
      • 專案範例
      • 不良示範 (反模式)
      • 影片與音訊課程
      • 付費課程
      • 其他資訊

元件宣告

單文件組件(Single File Component, SFC) - 最為常見

<template><button class="btn-primary" @click.prevent="handleClick">{{text}}</button>
</template><script>
export default {data() {return {text: 'Click me',};},methods: {handleClick() {console.log('clicked');},},
}
</script><style scoped>
.btn-primary {background-color: blue;
}
</style>

字串樣板 (String Template) (或是 es6 樣板字面值 (Template Literal))

Vue.component('my-btn', {template: `<button class="btn-primary" @click.prevent="handleClick">{{text}}</button>`,data() {return {text: 'Click me',};},methods: {handleClick() {console.log('clicked');},},
});

渲染函式 (Render Function)

Vue.component('my-btn', {data() {return {text: 'Click me',};},methods: {handleClick() {console.log('clicked');},},render(h) {return h('button', {attrs: {class: 'btn-primary'},on: {click: this.handleClick,},});},
});

JSX

Vue.component('my-btn', {data() {return {text: 'Click me',};},methods: {handleClick() {console.log('clicked');},},render() {return (<button class="btn-primary" onClick={this.handleClick}>{{this.text}}</button>);},
});

vue-class-component (使用 es6 classes)

<template><button class="btn-primary" @click.prevent="handleClick">{{text}}</button>
</template><script>
import Vue from 'vue';
import Component from 'vue-class-component';@Component
export default MyBtn extends Vue {text = 'Click me';handleClick() {console.log('clicked');}
}
</script><style scoped>
.btn-primary {background-color: blue;
}
</style>

參考連結

  • 7 Ways To Define A Component Template in VueJS

元件條件渲染 (Component Conditional Rendering)

指令 (Directives) (v-if / v-else / v-else-if / v-show)

v-if<h1 v-if="true">只在 v-if 值為 true 時渲染</h1>
v-if 與 v-else<h1 v-if="true">只在 v-if 值為 true 時渲染</h1>
<h1 v-else>只在 v-if 值為 false 時渲染</h1>
v-else-if<div v-if="type === 'A'">只在 `type` 等於 `A` 時渲染</div>
<div v-else-if="type === 'B'">只在 `type` 等於 `B` 時渲染</div>
<div v-else-if="type === 'C'">只在 `type` 等於 `C` 時渲染</div>
<div v-else>只在 `type` 不等於>fmf `A` 或 `B` 或 `C` 時渲染</div>
v-show<h1 v-show="true">永遠都會渲染,但是只在 `v-show` 值為 true 時顯示</h1>
如果你需要同時在多個元素上面做條件式渲染,你可以在 <template> 元素上使用這些指令 (v-if / v-else / v-else-if /v-show)。 注意:<template> 元素不會實際渲染一個 DOM。<template v-if="true"><h1>所有元素</h1><p>都會被渲染成為 DOM</p><p>除了 `template` 元素</p>
</template>

JSX

如果你在你的 Vue 應用程式中使用 JSX,你可以使用所有 javascript 語句,例如 if else 、 switch case 、三元運算 (ternary) 與 邏輯運算式 (logical operator)

if else 語句

export default {data() {return {isTruthy: true,};},render(h) {if (this.isTruthy) {return <h1>值為真時渲染</h1>;} else {return <h1>值為假時渲染</h1>;}},
};

switch case 語句

import Info from './Info';
import Warning from './Warning';
import Error from './Error';
import Success from './Success';export default {data() {return {type: 'error',};},render(h) {switch (this.type) {case 'info':return <Info text={text} />;case 'warning':return <Warning text={text} />;case 'error':return <Error text={text} />;default:return <Success text={text} />;},}
};

你也可以透過物件的對應來簡化 switch case 


import Info from './Info';
import Warning from './Warning';
import Error from './Error';
import Success from './Success';const COMPONENT_MAP = {info: Info,warning: Warning,error: Error,success: Success,
};export default {data() {return {type: 'error',};},render(h) {const Comp = COMPONENT_MAP[this.type || 'success'];return <Comp />;},
};


三元運算子 (ternary operator)


export default {data() {return {isTruthy: true,};},render(h) {return (<div>{this.isTruthy ? (<h1>值為真時渲染</h1>) : (<h1>值為假時渲染</h1>)}</div>);},
};


邏輯運算子 (logical operator)


export default {data() {return {isLoading: true,};},render(h) {return <div>{this.isLoading && <h1>Loading ...</h1>}</div>;},
};


參考連結

Difference Between v-if and v-show [With Video at End]

動態元件

使用 is 屬性在 <component> 元素上

範例 1 範例 2 範例 3



<component :is="currentTabComponent"></component>


上面的範例,原有 
<component> 中的元件,在切換元件的同時將會被消滅。 如果你需要切換後仍保留 <component> 中元件的實體,而不被消滅的話,可以包裹一個 <keep-alive> 標籤,如下:


<keep-alive><component :is="currentTabComponent"></component>
</keep-alive>


元件組合

基本組合 (Basic Composition)



<template><div class="component-b"><component-a></component-a></div>
</template><script>
import ComponentA from './ComponentA';export default {components: {ComponentA,},
};
</script>


繼承 (Extends)

當你需要繼承一個單文件組件 (SFC) 時可以使用。


<template><button class="button-primary" @click.prevent="handleClick">{{buttonText}}</button>
</template><script>
import BaseButton from './BaseButton';export default {extends: BaseButton,props: ['buttonText'],
};
</script>


參考連結

Extending VueJS Components

混入 (Mixins)


// closableMixin.js
export default {props: {isOpen: {default: true}},data: function() {return {shown: this.isOpen}},methods: {hide: function() {this.shown = false;},show: function() {this.shown = true;},toggle: function() {this.shown = !this.shown;}}
}
<template><div v-if="shown" class="alert alert-success" :class="'alert-' + type" role="alert">{{text}}<i class="pull-right glyphicon glyphicon-remove" @click="hide"></i></div>
</template><script>
import closableMixin from './mixins/closableMixin';export deafult {mixins: [closableMixin],props: ['text']
};
</script>


參考連結

Practical use of Components and Mixins in Vue JS

預設插槽 (Slots (Default))


<template><button class="btn btn-primary"><slot></slot></button>
</template><script>
export default {name: 'VBtn',
};
</script>
<template><v-btn><span class="fa fa-user"></span>Login</v-btn>
</template><script>
import VBtn from './VBtn';export default {components: {VBtn,}
};
</script>


參考連結

Understanding Component Slots with Vue.js Composing Custom Elements With Slots And Named Slots

具名插槽(Named Slots)

BaseLayout.vue


<div class="container"><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer>
</div>


App.vue


<base-layout><template slot="header"><h1>這裡是頁面標題</h1></template><p>一段文件主體內的文字</p><p>另外一段文字</p><template slot="footer"><p>一些聯絡資訊</p></template>
</base-layout>


作用域插槽 (Scoped Slots)


<template><ul><liv-for="todo in todos"v-bind:key="todo.id"><!-- 保留一個插槽供每一個 todo 使用,--><!-- 並將 將 `todo` 物件作為插槽參數傳遞給它,供外部元件使用。--><slot v-bind:todo="todo">{{ todo.text }}</slot></li></ul>
</template><script>
export default {name: 'TodoList',props: {todos: {type: Array,default: () => ([]),}},
};
</script>
<template><todo-list v-bind:todos="todos"><template slot-scope="{ todo }"><span v-if="todo.isComplete"></span>{{ todo.text }}</template></todo-list>
</template><script>
import TodoList from './TodoList';export default {components: {TodoList,},data() {return {todos: [{ todo: 'todo 1', isComplete: true },{ todo: 'todo 2', isComplete: false },{ todo: 'todo 3', isComplete: false },{ todo: 'todo 4', isComplete: true },];};},
};
</script>


參考資料

Getting Your Head Around Vue.js Scoped Slots Understanding scoped slots in Vue.js Scoped Component Slots in Vue.js The Trick to Understanding Scoped Slots in Vue.js The Power of Scoped Slots in Vue

渲染屬性 (Render Props)

大多數狀況下,你可以優先使用作用域插槽 (Scoped Slots) 之於渲染屬性 (Render Props),但是,在某些狀況下渲染屬性還是很有用的。

於單文件組件:

<template><div id="app"><Mouse :render="__render"/></div>
</template><script>
import Mouse from "./Mouse.js";
export default {name: "app",components: {Mouse},methods: {__render({ x, y }) {return (<h1>The mouse position is ({x}, {y})</h1>);}}
};
</script>
<style>
* {margin: 0;height: 100%;width: 100%;
}
</style>

於 JSX

const Mouse = {name: "Mouse",props: {render: {type: Function,required: true}},data() {return {x: 0,y: 0};},methods: {handleMouseMove(event) {this.x = event.clientX;this.y = event.clientY;}},render(h) {return (<div style={{ height: "100%" }} onMousemove={this.handleMouseMove}>{this.$props.render(this)}</div>);}
};export default Mouse;

參考連結

  • Leveraging Render Props in Vue
  • Use a Vue.js Render Prop!

參數傳遞 (Passing Props)

有時候你想要傳遞所有參數 (props) 與事件 (listeners) 到子元件,但又不想要宣告所有子元件的參數。 你可以直接將 $attrs 與 $listeners 綁定在子元件上。

<template><div><h1>{{title}}</h1><child-component v-bind="$attrs" v-on="$listeners"></child-component></div>
</template><script>
export default {name: 'PassingPropsSample'props: {title: {type: String,default: 'Hello, Vue!'}}
};
</script>

在父元件上,你可以這樣做:

<template><passing-props-sampletitle="Hello, Passing Props"childPropA="This props will properly mapped to <child-component />"@click="handleChildComponentClick"></passing-props-sample>
</template><script>
import PassingPropsSample from './PassingPropsSample';export default {components: {PassingPropsSample},methods: {handleChildComponentClick() {console.log('child component clicked');}}
};
</script>

參考資料

  • Transparent Wrapper Components in Vue

高優先元件 (Higher Order Component, HOC)

參考連結

  • Higher Order Components in Vue.js
  • Do we need Higher Order Components in Vue.js?
  • Higher-Order Components in Vue.js

相依注入 (Dependency injection)

Vue 支援 提供 與 注入 (Provide / inject) 機制來傳遞一個物件到所有子代元件中,不管結構有多深,只要都基於同一個父代即可。 注意: provide 和 inject 並沒有響應能力 (reactive) ,除非你傳遞的物件本身就帶有響應能力。

<parent-component>  // 父元件<child-component>  // 子元件<grand-child-component></grand-child-component>  // 孫元件</child-component>
</ancestor-component>

上述的元件結構,若要從 父元件 取得資料,你必須要透過 參數(props) 傳遞資料到 子元件 與 孫元件 之中。 但如果 父元件 提供 (provide) 資料(或物件), 孫元件 可以透過宣告直接 注入(inject父元件 中所定義的資料(或物件)。

參考連結

  • Official API
  • Official Guide
  • Component Communication
  • Dependency Injection in Vue.js App with TypeScript

提供 與 注入 (Provide / Inject)

// ParentComponent.vueexport default {provide: {theme: {primaryColor: 'blue',},},
};
// GrandChildComponent.vue<template><button :style="{ backgroundColor: primary && theme.primaryColor }"><slot></slot></button>
</template><script>
export default {inject: ['theme'],props: {primary: {type: Boolean,default: true,},},
};
</script>

注入裝飾器模式 (@Provide / @Inject Decorator)

// ParentComponent.vueimport { Component, Vue, Provide } from 'vue-property-decorator';@Component
export class ParentComponent extends Vue {@Providetheme = {primaryColor: 'blue',};
}
// GrandChildComponent.vue<template><button :style="{ backgroundColor: primary && theme.primaryColor }"><slot></slot></button>
</template><script>
import { Component, Vue, Inject, Prop } from 'vue-property-decorator';export class GrandChildComponent extends Vue {@Inject() theme;@Prop({ default: true })primary: boolean;
};
</script>

錯誤處理 (Handling Errors)

errorCaptured 事件

export default {name: 'ErrorBoundary',data() {return {error: false,errorMessage: '',};},errorCaptured (err, vm, info) {this.error = true;this.errorMessage = `${err.stack}\n\nfound in ${info} of component`;return false;},render (h) {if (this.error) {return h('pre', { style: { color: 'red' }}, this.errorMessage);}return this.$slots.default[0]}
};
<error-boundary><another-component/>
</error-boundary>

範例

  • Example 1

參考連結

  • Handling Errors in Vue with Error Boundaries

生產力小技巧

讓監聽器在 created 事件時就有效

// 不要這樣做
created() {this.fetchUserList();
},
watch: {searchText: 'fetchUserList',
}
// 這樣做
watch: {searchText: {handler: 'fetchUserList',immediate: true,}
}

有用的連結

組建間的溝通

  • Vue.js Event Bus + Promises
  • Vue.js Component Communication Patterns
  • Leveraging Vue events to reduce prop declarations
  • Control DOM Outside Your Vue.js App with portal-vue
  • Creating Custom Inputs With Vue.js
  • Creating a Global Event Bus with Vue.js

重構技巧

  • Refactoring Vue: Cleaning Up a List of Posts With Better Component Splitting and More ES6
  • Clean up your Vue modules with ES6 Arrow Functions
  • Examples of Vue’s Clean Code
  • Optimizing Performance with Computed Properties

Vuex

  • Decouple Vuex modules with the Mediator pattern
  • Vuex getters are great, but don’t overuse them
  • Reusable Vuex Mutation Functions
  • A pattern to handle ajax requests in Vuex
  • [vuex Mutations] Single Changes vs. Single Responsibility
  • Components and How They Interact in Vue and Vuex
  • Why VueX Is The Perfect Interface Between Frontend and API
  • Composing actions with Vuex
  • How to Build Complex, Large-Scale Vue.js Apps With Vuex

Mobx

  • Build A View-Framework-Free Data Layer Based on MobX — Integration With Vue (1)

不須渲染的元件 (Renderless Component)

  • Renderless Components in Vue.js
  • Building Renderless Components to Handle CRUD Operations in Vue.js

範例

  • Renderless Calendar component

目錄結構

  • How you can improve your workflow using the JavaScript console
  • How to Structure a Vue.js Project

小技巧

  • How To Build Vue Components Like A Pro
  • Four tips for working with Vue.js
  • Tips from a Lowly VueJS Developer
  • Throttling and Debouncing Events with Vue.js and lodash
  • Are partially applied functions in event handlers possible?
  • Vue.js — Considerations and Tricks
  • Six random issues and their solutions in VueJS.
  • When VueJS Can't Help You

專案範例

  • vue-enterprise-boilerplate
  • 7-secret-patterns
  • Vue.js-2-Design-Patterns-and-Best-Practices

不良示範 (反模式)

  • Chris Fritz - Vue.js Anti-Patterns (and How to Avoid Them)
  • Common mistakes to avoid while working with Vue.js

影片與音訊課程

  • 81: Evan You - Advanced Vue Component Design
  • 7 Secret Patterns Vue Consultants Don’t Want You to Know

付費課程

  • Advanced Vue Component Design

其他資訊

  • Creating an Interpose Vue component from a React implementation
  • Composing computed properties in Vue.js
  • 4 AJAX Patterns For Vue.js Apps
  • 3 Code Splitting Patterns For VueJS and Webpack
  • The easiest way to improve your Vue.js application. Part 1
  • Using JSX with Vue and Why You Should Care
  • Compound components
  • Creating Multi-root Vue.js Components
  • Understanding Vue.js Reactivity in Depth with Object.defineProperty()
  • Templating in Vue: Separation of Concerns or Separation of Technology or something else?
  • Stashing Vue components data
  • Creating Reusable Transitions in Vue
  • vue-advanced-workshop
  • Do it with Elegance: How to Create Data-Driven User Interfaces in Vue
  • Creating Vue.js Component Instances Programmatically
  • Managing User Permissions in a Vue.js App
  • Render Functional Components in Vue.js
  • Templating in Vue: Separation of Concerns or Separation of Technology or something else?
  • Looping through Object Properties
  • Cancelling async operations in Vue.js
  • Scoped styles with v-html
  • Pagination With Vuejs
  • What does the ‘h’ stand for in Vue’s render method?
  • How To Build Vue Components That Play Nice
  • Making responsive Vue components with ResizeObserver
  • An imperative guide to forms in Vue.js
  • Vue.js: the good, the meh, and the ugly
原文发布时间为:2018年07月02日
原文作者:掘金
本文来源: 掘金 如需转载请联系原作者

【译】Vue Patterns相关推荐

  1. [译]Vue官方成员:Vite生态发展的怎么样了

    前言 之前 Vite2 刚出来的时候,恰好我要负责一个新项目,所以我打算用最新的 Vite + Vue3 + TS 来构建这个项目. 不幸的是,那时候 Vite 有坑,热更新做的也不如传统 webpa ...

  2. [译] Vue.js 优雅地集成第三方 JavaScript

    原文地址:Sliding In And Out Of Vue.js 原文作者:Kevin Ball 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:Luca ...

  3. [译] Vue: scoped 样式与 CSS Module 对比

    原文:Vue.js - Scoped Styles vs CSS Modules 作者:Michał Sajnóg 发表时间:Aug 28, 2018 译者:西楼听雨 发表时间: 2018/9/10 ...

  4. Emitted value instead of an instance of Error-编译vue文件时出现的错误解决

    造成这样的原因很有可能是写重了view标签,像下面这样 只需要把下面一对view标签删去即可

  5. 【笔记-vue】《imooc-vue.js高仿饿了么》、《imooc-vue 音乐app》、《imooc-vue.js源码全方位解析》

    20170709 - 20171128:<imooc-vue.js高仿饿了么> 一.第一章 课程简介 1-1课程简介 1.需求分析-脚手架工具-数据mock-架构设计-代码编写-自测-编译 ...

  6. 来自 Vue 官方团队的 57 个技术分享

    最近在看 Vue 团队成员的技术演讲,从中能了解到他们的设计思考以及最佳实践,看完一场收获颇多. 经过我一番整理,今天给大家介绍一下这些核心团队成员以及他们的技术分享. 他们分别是: Evan You ...

  7. 如何学习配置webpack(一)

    项目小白如何从0开始配置webpack 自己配置过webpack的人应该都知道,webpack真的好复杂,一开始做项目都是拿别人现成的做做小修改,但是别人的终究没有自己配的舒服.所以我打算写这篇文章, ...

  8. 透视前端工程化之 Webpack 基本介绍【文末有彩蛋~】

    1 Webpack 的特点 图片来源于网络 Webpack 是一款强大的打包工具.在 Webpack 中一切皆模块.Webpack 官网的 Banner 图完美地诠释了这一理念.Webpack 从一个 ...

  9. before css 旋转_单标签!纯CSS实现动态晴阴雨雪

    引言 本期分享一下如何仅用CSS3,实现单标签的动态晴阴雨雪.技术关键点就是"单标签"和"纯CSS".先看下最终效果: 再看看HTML代码: <div c ...

  10. Web前端技术 Web学习资料 Web学习路线 Web入门宝典

    学习路线 第一章 核心 1.Node Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台.Node.js是一个 ...

最新文章

  1. linux下搭建redis并解决无法连接redis的问题
  2. iptraf 打不开
  3. QQ互联OAuth2.0 .NET SDK 发布以及网站QQ登陆示例代码
  4. 记一次云服务器被入侵
  5. Java黑皮书课后题第5章:**5.25(计算π)使用下面的数列可以近似计算π:4(1-1/3+1/5-1/7+……+(Math.pow(-1, i+1)/(2*i-1))
  6. 【POJ】2387 Til the Cows Come Home
  7. [mybatis]缓存_一级缓存_一级缓存失效的四种情况
  8. 玩转算法第七章-二叉树与递归
  9. ListView列表刷新方法的区别
  10. VSCode自定义代码片段3——url大全
  11. php上传文件 报的错误 $_FILES[‘file’]['error']
  12. 墨菲定律与 IndexOutOfBoundsException(数组越界异常)
  13. 学弟拿到了大厂推荐算法岗offer,分享一波他的经验
  14. Android_撕衣服小案例
  15. 计算机网路实验四 IP协议分析
  16. java 刽子手图像代码,刽子手游戏代码
  17. 疫情中的云与教育:“停课不停学”背后的百度技术密码
  18. 室内定位系列(一)——WiFi位置指纹(译)
  19. python 相关性分析原理及代码详细介绍
  20. 微信小程序之电子商场的设计以及实现

热门文章

  1. js 操作数组函数-自定义
  2. 理想的低通滤波器、巴特沃斯滤波器、高斯滤波器
  3. 【OpenCV学习笔记】【函数学习】十六(Rect参数介绍)
  4. 智能优化算法:龙格-库塔优化算法 - 附代码
  5. 基于FVC_MSAVI_EVI的荒漠化等级分类方法
  6. 实习踩坑之路:一个ElasticSearchJava客户端的批量处理操作bulkIndexAsync引发的内存泄漏的血案
  7. Java设计模式------工厂模式-------工厂方法模式
  8. sql 查出表转换为html,如何执行表中的sql语句并将其转换为html
  9. Flink CDC 系列 - 同步 MySQL 分库分表,构建 Iceberg 实时数据湖
  10. 在钢筋混泥土的城市,打铁还需身体硬