Publish to my blog (weekly)

    • Because the component instance is not yet created when setup is executed, there is no this inside a setup option.
    • methods
    • lifecycle hooks
    • computed properties
    • That’s because in JavaScript, primitive types like Number or String are passed by value, not by reference:
    • Now whenever we call getUserRepositories, repositories will be mutated and the view will be updated to reflect the change.
    • we recommend using kebab-cased event listeners when you are using in-DOM templates. If you're using string templates, this limitation does not apply.
    • emits: ['inFocus', 'submit']
    • When a native event (e.g., click) is defined in the emits option, the component event will be used instead of a native event listener.
    • Similar to prop type validation, an emitted event can be validated if it is defined with the Object syntax instead of the array syntax.
    • // No validation  click: null,
    • // Validate submit event  submit: ({ email, password }) => {  if (email && password) {  return true  } else {  console.warn('Invalid submit event payload!')  return false  }  }
    • .$emit('submit', { email, password })
    • child component will expect a title prop and emits update:title event to sync:
    • props: {  title: String  },  emits: ['update:title'],
    • :value="title"
    • @input="$emit('update:title', $event.target.value)"
    • v-model:first-name="firstName"
    • v-model:last-name="lastName"
    • firstName: String,
    • lastName: String
    • 'update:firstName'
    • 'update:lastName'
    • :value="firstName"
    • @input="$emit('update:firstName', $event.target.value)"
    • :value="lastName"
    • @input="$emit('update:lastName', $event.target.value)"
    • v-model has built-in modifiers - .trim, .number and .lazy
    • v-model.capitalize="myText"
    • modelModifiers: {  default: () => ({})  }
    • console.log(this.modelModifiers) // { capitalize: true }
    • modelModifiers: {  default: () => ({})  }
    • emitValue(e) {  let value = e.target.value  if (this.modelModifiers.capitalize) {  value = value.charAt(0).toUpperCase() + value.slice(1)  }  this.$emit('update:modelValue', value)  }
    • :value="modelValue"
    • @input="emitValue"
    • For v-model bindings with arguments, the generated prop name will be arg + "Modifiers"
    • v-model:description.capitalize
    • props: ['description', 'descriptionModifiers'],
    • :value="description"
    • @input="$emit('update:description', $event.target.value)"
    • console.log(this.descriptionModifiers) // { capitalize: true }
    • Using our date-picker component example from the previous section, in the event we need to apply all non-prop attributes to the input element rather than the root div element, this can be accomplished by using the v-bind shortcut.
    • inheritAttrs: false,
    • v-bind="$attrs"
    • data-status="activated"
    • data-status="activated"
    • @click="changeValue"
    • v-bind="$attrs"
    • Vue also allows you to register your own custom directives
    • the primary form of code reuse and abstraction is components - however, there may be cases where you need some low-level DOM access on plain elements, and this is where custom directives would still be useful.
    • if you haven't clicked on anything else since visiting this page, the input above should be focused now. Also, you can click on the Rerun button and input will be focused.
    • If you want to register a directive locally instead, components also accept a directives option:
    • created
    • beforeMount
    • mounted
    • beforeUpdate
    • updated
    • beforeUnmount
    • unmounted
    • Directive arguments can be dynamic. For example, in v-mydirective:[argument]="value", the argument can be updated based on data properties in our component instance!
    • 'pin'
    • mounted(el, binding) {  el.style.position = 'fixed'  // binding.value is the value we pass to directive - in this case, it's 200  el.style.top = binding.value + 'px'  }
    • // binding.arg is an argument we pass to directive  const s = binding.arg || 'top'
    • If your directive needs multiple values, you can also pass in a JavaScript object literal.
    • "{ color: 'white', text: 'hello!' }"
    • Hook functions with the same name are merged into an array so that all of them will be called.
    • When using the Composition API, the concept of reactive refs and template refs are unified. In order to obtain a reference to an in-template element or component instance, we can declare a ref as usual and return it from setup():
    • ref="root"
    • const root = ref(null)
    • root.value
    • return {  root  }
    • Here we are exposing root on the render context and binding it to the div as its ref via ref="root"
    • if a VNode's ref key corresponds to a ref on the render context, the VNode's corresponding element or component instance will be assigned to the value of that ref. This is performed during the Virtual DOM mount / patch process, so template refs will only get assigned values after the initial render.
    • Refs used as templates refs behave just like any other refs: they are reactive and can be passed into (or returned from) composition functions.
    • const root = ref(null)
    • :ref="el => { if (el) divs[i] = el }"
    • const list = reactive([1, 2, 3])
    • const divs = ref([])
    • return {  list,  divs  }
    • // This effect runs before the DOM is updated, and consequently,   // the template ref does not hold a reference to the element yet.  console.log(root.value) // => null
    • Therefore, watchers that use template refs should be defined with the flush: 'post' option.
    • This will run the effect after the DOM has been updated and ensure that the template ref stays in sync with the DOM and references the correct element.
    • {  flush: 'post'  }
    • You'll notice that if you select a post, switch to the Archive tab, then switch back to Posts, it's no longer showing the post you selected
    • Recreating dynamic components is normally useful behavior, but in this case, we'd really like those tab component instances to be cached once they're created for the first time. To solve this problem, we can wrap our dynamic component with a <keep-alive> element:
    • <keep-alive>
    • </keep-alive>
    • In large applications, we may need to divide the app into smaller chunks and only load a component from the server when it's needed.
    • defineAsyncComponent
    • defineAsyncComponent
    • () =>  new Promise((resolve, reject) => {  resolve({  template: '<div>I am async!</div>'  })  })
    • his method accepts a factory function returning a Promise
    • Promise's resolve callback should be called when you have retrieved your component definition from the server.
    • efineAsyncComponent(() =>  import('./components/AsyncComponent.vue') )
    • AsyncComponent: defineAsyncComponent(() =>  import('./components/AsyncComponent.vue')  )
    • The async component can opt-out of Suspense control and let the component always control its own loading state by specifying suspensible: false in its options.
    • when we need to pass data from the parent to child component, we use props.
    • the structure where you have some deeply nested components and you only need something from the parent component in the deep nested child.
    • you still need to pass the prop down the whole component chain which might be annoying.
    • we can use the provide and inject pair
    • Parent components can serve as dependency provider for all its children, regardless how deep the component hierarchy is
    • parent component has a provide option to provide data and child component has an inject option to start using this data.
    • If we want to pass the length of todo-items directly to TodoListStatistics, we would pass the prop down the hierarchy: TodoList -> TodoListFooter -> TodoListStatistics. With provide/inject approach, we can do this directly:
    • provide: {  user: 'John Doe'  },
    • inject: ['user'],
    • console.log(`Injected property: ${this.user}`) // > Injected property: John Doe
    • To access component instance properties, we need to convert provide to be a function returning an object
    • return {  todoLength: this.todos.length  }
    • parent components don’t need to know which descendants use the properties it provides
    • child components don’t need to know where injected properties are coming from
    • if we change the list of todos, this change won't be reflected in the injected todoLength property. This is because provide/inject bindings are not reactive by default.
    • We can change this behavior by passing a ref property or reactive object to provide
    • return {  todoLength: Vue.computed(() => this.todos.length)  }
    • inject: ['todoLength'],
    • console.log(`Injected property: ${this.todoLength.value}`) // > Injected property: 5
    • any change to todos.length will be reflected correctly in the components, where todoLength is injected.
    • Everything in the parent template is compiled in parent scope; everything in the child template is compiled in the child scope
    • There are times when it's useful to have multiple slots.
    • the <slot> element has a special attribute, name, which can be used to assign a unique ID to different slots so you can determine where content should be rendered:
    • To provide content to named slots, we need to use the v-slot directive on a <template> element, providing the name of the slot as v-slot's argument:
    • Note that v-slot can only be added to a <template> (with one exception
    • Scoped Slots
      • child 에서 넘겨주는 값들을 parent에서 받아서 처리하는 경우에 사용.
    • it's useful for slot content to have access to data only available in the child component.
    • todo-list
    • <todo-list>  <i class="fas fa-check"></i>  <span class="green">{{ item }}</span> </todo-list>
      • parent component
    • <slot :item="item"></slot>
    • <slot :item="item" :index="index" :another-attribute="anotherAttribute"></slot>
    • Attributes bound to a <slot> element are called slot props.
    • <template v-slot:default="slotProps">
    • { slotProps.item }}
    • </template>
    • we've chosen to name the object containing all our slot props slotProps, but you can use any name you like.
    • v-slot:default
    • v-slot
    • Note that the abbreviated syntax for default slot cannot be mixed with named slots, as it would lead to scope ambiguity:
    • <!-- INVALID, will result in warning -->
    • Whenever there are multiple slots, use the full <template> based syntax for all slots:
    • { item }
    • {{ item }}
    • This can make the template much cleaner, especially when the slot provides many props. It also opens other possibilities, such as renaming props, e.g. item to todo:
    • { item: todo }
    • {{ todo }}
    • item = 'Placeholder'
      • 함수 파라미터의 기본값처럼 사용.
    • [dynamicSlotName]
    • Similar to v-on and v-bind, v-slot also has a shorthand, replacing everything before the argument (v-slot:) with the special symbol #
    • #header
    • #default
    • #footer
    • <!-- This will trigger a warning -->
    • #default="{ item }"
    • ref — Takes an inner value and returns a reactive and mutable ref object. The ref object has a single property .value that points to the inner value
    • reactive — Returns a reactive copy of the object. The reactive conversion is “deep” — it affects all nested properties.
    • computed method — Takes a getter function and returns an immutable reactive ref object for the returned value from the getter.
    • To apply and automatically re-apply a side effect based on reactive state, we can use the effect method.
    • We should just use ref() for primitives and reactive() for objects.
    • There is a toRefs() method that will convert a reactive object to a plain object, where each property on the resulting object is a ref pointing to the corresponding property in the original object.

Posted from Diigo. The rest of my favorite links are here.

댓글

이 블로그의 인기 게시물

Publish to my blog (weekly)

Publish to my blog (weekly)