Close read Vue official documentation series 🎉

Access elements & components

$root

Access the root component instance

$parent

Gets a parent component instance that supports multiple calls to get instances of successive layers of parents.

ref & $refs

Gets an instance of the child component

<children ref="child" />
Copy the code

Gets an object reference to a DOM element.

<input type="text" ref="input" />
Copy the code

Finally, we can access the corresponding references to these Refs in the component’s $refs property.

mountd(){
    this.$refs.child.input.foucs();
}
Copy the code

When ref and V-for are used together, the ref you get will be an array containing the subcomponents of the corresponding data source.

Dependency injection

Provide dependencies with provide and inject dependencies with Inject.

Provider

provide: function(){
    return {
        getMapData: this.getData
    }
}
Copy the code

Consumer

inject:['getMapData']
Copy the code

This pair of component options must be used together. To allow an ancestor component to inject a dependency into all its descendants, no matter how deep the component hierarchy is.

The value of provide is an object or a function that returns an object. The key of the object is the dependency injected into the descendant component. The value of Inject is an array of strings, or an object option. These array elements or object keys correspond to provide injected dependencies.

In its most basic form:

Vue.extend({
  name: "Parent".provide: {
    foo: "bar",}}); Vue.extend({name: "Son".inject: ["foo"].created() {
    console.log(this.foo); }});Copy the code

While provide is a function, inject is an object option:

Vue.extend({
  name: "Parent".provide() {
    return {
      foo: "bar"}; }}); Vue.extend({name: "Son".inject: {
    bar: {
      from: "foo".default: "new bar",}}});Copy the code

If the value of inject is an object, then from specifies the source and default is used to set the default value of the dependency. But when your dependency default is not a primitive type, you must use a factory method to return that value.

{
  inject: {
    foo: {
      from: 'bar'.default: () = > [1.2.3]}}}Copy the code

Finally, since provide/inject initialization takes precedence over props,data, we can initialize their defaults with dependency injection.

Vue.extend({
  inject: ["foo"].props: {
    bar: {
      type: String.default: () = > this.foo,
    },
  },
  data() {
    return {
      copy_bar: this.foo, }; }});Copy the code

What problem does dependency injection solve?

  1. To solve the$parentDoes not scale well to deeper nested components.
  2. Providing data or methods to arbitrary descendants eliminates the need for multiple layers of Prop passing.
  3. Any descendant does not need to care where the property was injected from.

Application scenarios of dependency injection:

  1. Write a fixed set of components, with a root component and multiple layers of child components, with a fixed structure.
  2. A local data centralization.

Negative effects of dependency injection:

  1. Injected data or methods are not responsive based on design considerations.
  2. Injected data is not processed as responsive data, but that does not prevent dependency injection of responsive data.
  3. Because of the nature of dependency injection, it tightly couples related components in the application (those that use dependency injection), making refactoring difficult.

Vuex, the silver bullet of dependency injection, provides a third party independent data center with responsive update capabilities.

Programmatic event listeners

The programmatic event listener is built on top of the Vue system, which is distinct from the browser’s EventTarget API. Normally we use V-ON to listen for events on components and $emit() to fire events within components, and the “programmatic Event Listener” provides a feature to listen for events on component instances.

  • $on('eventName', eventHandler)Bind/listen for an event.
  • $off('eventName, eventHandler')Unbind/stop listening for an event.
  • $once(eventName, eventHandler)Bind/listen on one event at a time.

Making good use of $once can improve our ability to solve component event cleanup problems.

Bad

// Attach the date picker to an input box once
// It will be mounted to the DOM.
mounted: function () {
  // Pikaday is a library of third-party date pickers
  this.picker = new Pikaday({
    field: this.$refs.input,
    format: 'YYYY-MM-DD'})},// Before the component is destroyed,
// Also destroy the date picker.
beforeDestroy: function () {
  this.picker.destroy()
}
Copy the code

Good

mounted: function () {
  var picker = new Pikaday({
    field: this.$refs.input,
    format: 'YYYY-MM-DD'
  })

  this.$once('hook:beforeDestroy'.function () {
    picker.destroy()
  })
}
Copy the code

We can also encapsulate these operations into methods that make it easier to perform the same operation multiple times.

Recursive components

In the same way that “recursion” is calling itself, component recursion is a component calling itself over and over again.

Recursive component entry:

<x-menu :menus="menus"></x-menu>
Copy the code

Recursive component definition:

Vue.component('x-menu', {
    props: {menus: {requried:true.type:Array}},template:` <ul> <li v-for="menu in menus" :key="menu.key"> <div>{{ menu.name }}</div> <! - heart - > < x - menus v - if = "menu. Children" > < / x - menus > < / li > < / ul > `
});
Copy the code

A circular reference

Unlike recursive components, recursion implements the desired functionality by constantly calling itself. A circular reference exists only between two components, A that uses B, and B that uses A.

This is not the case if you are registered as a global component through Vue.com Ponent.

Typically this problem occurs only when modular systems are used to introduce components that reference each other.

There are two solutions:

1. Manually register one of the components

beforeCreate: function(){
    this.$options.components.ComponetB = import('./components/componentB').default;
}
Copy the code

2. Use asynchronous components

{
    components: {'component-b': () = >import('./components/componentB')}}Copy the code

Alternatives to template definitions

We recommend defining templates using single-file component SFC or writing string templates in the template property rather than separating component templates from logic.

Inline template

When the special attribute inline-template appears on a child component, the component will use its content as the template, rather than as the content to be distributed (regardless of the nature of the slot). This makes writing templates more flexible.

Inline templates need to be defined within the DOM element that the Vue belongs to.

<my-component inline-template>
  <div>
    <p>These are compiled as the component's own template.</p>
    <p>Not parent's transclusion content.</p>
  </div>
</my-component>
Copy the code

The contents of the start and end tags of a custom component will be used as templates for that custom component and therefore will not be passed to the

element. This will separate the template from the logic of the component and is generally not recommended.

X-Template

The contrast with inline templates is to use

The X-template needs to be defined outside the DOM element that the Vue belongs to.

<script type="text/x-template" id="hello-world-template">
  <p>Hello hello hello</p>
</script>
Copy the code

The ID is the credential that connects the template content to the template logic.

Vue.component('hello-world', {
  template: '#hello-world-template'
})
Copy the code

The X-template approach also causes the component Template to be separated from the logic, so it is not recommended.

Forced to update

A call to this.$forceUpdate() forces the component to update.

throughv-onceCreate low overhead static components

When a component contains a lot of static content. We can add v-once attributes to the root element to ensure that the content is evaluated only once and then cached to provide the rendering speed of the component.

Vue.component('terms-of-service', {
  template: `
    <div v-once>
      <h1>Terms of Service</h1>. a lot of static content ...</div>`})Copy the code