OSDN Git Service

Regular updates
[twpd/master.git] / vue.md
diff --git a/vue.md b/vue.md
index 5b37060..a2dab72 100644 (file)
--- a/vue.md
+++ b/vue.md
 title: Vue.js
 category: JavaScript
 layout: 2017/sheet
-updated: 2019-11-22
+updated: 2019-12-26
 weight: -10
 intro: |
   [Vue.js](https://vuejs.org/) is an open-source Model–view–viewmodel JavaScript framework for building user interfaces and single-page applications.
 ---
 
-{% raw %}
+{%raw%}
 
-### Lists
+Expressions
+----------
+{: .-three-column}
 
+### Expressions
+
+```html
+<div id="app">
+  <p>I have a {{ product }}</p>
+  <p>{{ product + 's' }}</p>
+  <p>{{ isWorking ? 'YES' : 'NO' }}</p>
+  <p>{{ product.getSalePrice() }}</p>
+</div>
+```
+
+See: [Delimiters](https://vuejs.org/v2/api/#delimiters)
+
+### Binding
+
+```html
+<a v-bind:href="url">...</a>
+```
+
+#### Shorthand syntax
+```html
+<a :href="url">...</a>
+```
+{: data-line="1"}
+
+#### True or false will add or remove attribute
+```html
+<button :disabled="isButtonDisabled">...
+```
+
+#### If isActive is truthy, the class ‘active’ will appear
+```html
+<div :class="{ active: isActive }">...
+```
+
+#### Style color set to value of activeColor
+```html
+<div :style="{ color: activeColor }">
+```
+
+See: [v-bind](https://vuejs.org/v2/api/#v-bind)
+
+### Directives
+
+#### Element inserted/removed based on truthiness
+```html
+<p v-if="inStock">{{ product }}</p>
+```
+```html
+<p v-else-if="onSale">...</p>
+<p v-else>...</p>
+```
+
+#### Toggles the display: none CSS property
+```html
+<p v-show="showProductDetails">...</p>
+```
+
+#### Two-way data binding
+```html
+<input v-model="firstName" >
+```
+
+| Method | Description |
+| --- | --- |
+| `v-model.lazy="..."` | Syncs input after change event |
+| `v-model.number="..."` | Always returns a number |
+| `v-model.trim="..."` | Strips whitespace |
+
+See: [Directives](https://vuejs.org/v2/api/#Directives)
+
+### Actions/Events
+
+#### Calls addToCart method on component
+```html
+<button v-on:click="addToCart">...
+```
+
+#### Shorthand syntax
+```html
+<button @click="addToCart">...
+```
+{: data-line="1"}
+
+#### Arguments can be passed
+```html
+<button @click="addToCart(product)">...
+```
+
+#### To prevent default behavior (e.g. page reload)
+```html
+<form @submit.prevent="addProduct">...
+```
+
+#### Only trigger once
+```html
+<img @mouseover.once="showImage">...
+```
+
+| Method | Description |
+| --- | --- |
+| `.stop` | Stop all event propagation |
+| `.self ` | Only trigger if event.target is element itself |
+
+#### Keyboard entry example
 ```html
-<li v-for="todo in todos">
-  {{ todo.text }}
-  {{ $index }}
+<input @keyup.enter="submit">
+```
+
+#### Call onCopy when control-c is pressed
+```html
+<input @keyup.ctrl.c="onCopy">
+```
+
+See: [Events](https://vuejs.org/v2/guide/events.html)
+
+### List rendering
+
+#### The `:key` is always recommended
+```html
+<li v-for="item in items"
+    :key="item.id">
+  {{ item }}
 </li>
 ```
+{: data-line="2"}
 
-### Events
+#### To access the position in the array
+```html
+<li v-for="(item, index) in items">...
+```
 
+#### To iterate through objects
 ```html
-<button v-on:click='submit'>Go</button>
+<li v-for="(value, key) in object">...
 ```
 
-### Components
+#### Using `v-for` with a component
+```html
+<cart-product v-for="item in products"
+              :product="item"
+              :key="item.id">
+```
+
+See: [List Rendering](https://vuejs.org/v2/guide/list.html)
+
+
+Component
+--------
+
+### Component anatomy
 
 ```js
-new Vue({
-  components: { app: App }
+Vue.component('my-component', {
+  components: {
+    // Components that can be used in the template
+    ProductComponent,
+    ReviewComponent
+  },
+  props: {
+    // The parameters the component accepts
+    message: String,
+    product: Object,
+    email: {
+      type: String,
+      required: true,
+      default: "none"
+      validator: function (value) {
+        // Should return true if value is valid
+      }
+    }
+  },
+  data: function() {
+    // `data` must be a function
+    return {
+      firstName: 'Vue',
+      lastName: 'Mastery'
+    }
+  },
+  computed: {
+    // Return cached values until dependencies change
+    fullName: function () {
+      return this.firstName + ' ' + this.lastName
+    }
+  },
+  watch: {
+    // Called when firstName changes value
+    firstName: function (value, oldValue) { ... }
+  },
+  methods: { ... },
+  template: '<span>{{ message }}</span>',
+  // Can also use backticks in `template` for multi-line
 })
 ```
+{: data-line="3, 8, 16, 21, 28, 34, 39"}
 
-## API
+See: [Components Basics](https://vuejs.org/v2/guide/components.html)
 
-```js
-Vue.extend({ ... })        // creating components
-Vue.nextTick(() => {...})
+### Lifecycle hooks
 
-Vue.set(object, key, val)  // reactive
-Vue.delete(object, key)
+| Method | Description |
+| --- | --- |
+| `beforeCreate` | After the instance has been initialized [#](https://vuejs.org/v2/api/#beforeCreate) |
+| `created` | After the instance is created [#](https://vuejs.org/v2/api/#created) |
+| `beforeMount` | Before the first render [#](https://vuejs.org/v2/api/#beforeMount) |
+| `mounted` | After the instance has been mounted [#](https://vuejs.org/v2/api/#mounted) |
+| `beforeUpdate` | When data changes, before the DOM is patched [#](https://vuejs.org/v2/api/#beforeUpdate) |
+| `updated` | After a data change [#](https://vuejs.org/v2/api/#updated) |
+| `beforeDestroy` | Before the instance is destroyed [#](https://vuejs.org/v2/api/#beforeDestroy) |
+| `destroyed` | After a Vue instance has been destroyed [#](https://vuejs.org/v2/api/#destroyed) |
 
-Vue.directive('my-dir', { bind, update, unbind })
-// <div v-my-dir='...'></div>
+See: [Lifecycle Hooks](https://vuejs.org/v2/api/#Options-Lifecycle-Hooks)
 
-Vue.elementDirective('my-dir', { bind, update, unbind })
-// <my-dir>...</my-dir>
+### Custom events
 
-Vue.component('my-component', Vue.extend({ .. }))
+#### Set listener on component, within its parent
+```html
+<button-counter v-on:incrementBy="incWithVal">
+```
 
-Vue.partial('my-partial', '<div>hi {{msg}}</div>')
-// <partial name='my-partial'></partial>
+#### Inside parent component
+```js
+methods: {
+  incWithVal: function (toAdd) { ... }
+}
 ```
 
+#### Inside button-counter template
 ```js
-new Vue({
-  data: { ... }
-  props: ['size'],
-  props: { size: Number },
-  computed: { fullname() { return this.name + ' ' + this.lastName } },
-  methods: { go() { ... } },
-  watch: { a (val, oldVal) { ... } },
-  el: '#foo',
-  template: '...',
-  replace: true, // replace element (default true)
-
-  // lifecycle
-  created () {},
-  beforeCompile () {},
-  compiled () {},
-  ready () {}, // $el is inserted for the first time
-  attached () {},
-  detached () {},
-  beforeDestroy () {},
-  destroyed () {},
-
-  // options
-  directives: {},
-  elementDirectives: {},
-  filters: {},
-  components: {},
-  transitions: {},
-  partials: {}
-})
+this.$emit(
+    'incrementBy', // Custom event name
+    5 // Data sent up to parent
+  )
 ```
 
-## Vue templates
-Via [vueify](https://www.npmjs.com/package/vueify)
+Use props to pass data into child components,
+custom events to pass data to parent elements.
 
-```js
-// app.vue
+See: [Custom Events](https://vuejs.org/v2/guide/components-custom-events.html)
+
+Single file components
+--------
+
+### Single file
+```html
 <template>
-  <h1 class="red">{{msg}}</h1>
+  <p>{{ greeting }} World!</p>
 </template>
+
 <script>
-  module.exports = {
-    data () {
-      return {
-        msg: 'Hello world!'
-      }
+module.exports = {
+  data: function () {
+    return {
+      greeting: 'Hello'
     }
   }
-</script> 
+}
+</script>
+
+<style scoped>
+p {
+  font-size: 2em;
+  text-align: center;
+}
+</style>
 ```
 
-Also
+See: [Single File Components](https://vuejs.org/v2/guide/single-file-components.html)
 
+### Separation
 ```html
-<template lang='jade'>
-h1(class='red') {{msg}}
+<template>
+  <div>This will be pre-compiled</div>
 </template>
+<script src="./my-component.js"></script>
+<style src="./my-component.css"></style>
+```
+
+See: [What About Separation of Concerns?](https://vuejs.org/v2/guide/single-file-components.html#What-About-Separation-of-Concerns)
+
+Slots
+--------
+
+### Using a single slot
+
+#### Component template
+```html
+<div>
+  <h2>I'm a title</h2>
+  <slot>
+    Only displayed if no slot content
+  </slot>
+</div>
+```
+{: data-line="3,4,5"}
+
+#### Use of component with data for slot
+```html
+<my-component>
+  <p>This will go in the slot</p>
+</my-component>
+```
+{: data-line="2"}
+
+See: [Slots](https://vuejs.org/v2/guide/components-slots.html)
+
+### Multiple slots
+
+#### Component template
+```html
+<div class="container">
+  <header>
+    <slot name="header"></slot>
+  </header>
+  <main>
+    <slot>Default content</slot>
+  </main>
+  <footer>
+    <slot name="footer"></slot>
+  </footer>
+</div>
 ```
+{: data-line="3,6,9"}
+
+#### Use of component with data for slots
+```html
+<app-layout>
+  <h1 slot="header">Page title</h1>
+  <p>the main content.</p>
+  <p slot="footer">Contact info</p>
+</app-layout>
+```
+{: data-line="2,3,4"}
+
+See: [Slots](https://vuejs.org/v2/guide/components-slots.html)
+
+Also see
+--------
+
+* [Vue CLI](https://cli.vuejs.org/) _(cli.vuejs.org)_
+* [Vue Router](https://router.vuejs.org/) _(router.vuejs.org)_
+* [Vue DevTools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en) _(chrome.google.com)_
+* [Nuxt.js](https://nuxtjs.org/) _(nuxtjs.org)_
+* [Vue.js v1.0.28 cheatsheet](vue@1.0.28/) _Legacy version_
 
-{% endraw %}
+{%endraw%}