Vue study notes seven (boundary issues, transitions and animations)

1. Boundary issues

Documented here are all functions related to handling edge cases, i.e. some special cases that require some small tweaks to Vue's rules. However, note that these functions are all disadvantageous or dangerous scenarios. We will note it in each case, so please be careful when you use each function.

1. Access elements & components

1) Access the root instance

In the child component of each new Vueinstance , its root instance can be accessed through the $rootproperty. For example, in this root instance:

// Vue 根实例
new Vue({
  data: {
    foo: 1
  },
  computed: {
    bar: function () { /* ... */ }
  }
  methods: {
    baz: function () { /* ... */ }
  }
})

 

All child components can access or use this instance as a global store.

 

// 获取根组件的数据
this.$root.foo

// 写入根组件的数据
this.$root.foo = 2

// 访问根组件的计算属性
this.$root.bar

// 调用根组件的方法
this.$root.baz()

This is handy for demos or very small applications with few components. However, this model is not the case when it is extended to medium and large applications. Therefore, in the vast majority of cases, we strongly recommend using Vuex to manage the state of the application.

2) Access the parent component instance

$rootSimilarly , $parentproperties can be used to access instances of the parent component from a child component. It provides an opportunity to reach the parent component at any time later, instead of passing data to the child component as a prop.

Also in some cases where it might be appropriate, you need to share some component libraries specifically. For example, within an abstract component that interacts with a JavaScript API without rendering HTML, like these hypothetical Google Maps components:

<google-map>
  <google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map>

This <google-map>component can define a mapproperty that all child components need to access . In this case you <google-map-markers>might want to this.$parent.getMapaccess that map in a similar way to add a set of markers to it. You can check out this pattern here .

Note, however, that the internals of the component built with this pattern are still prone to problems. For example, imagine we add a new <google-map-region>component that, when <google-map-markers>present inside it, only renders the markup in that area:

<google-map>
  <google-map-region v-bind:shape="cityBoundaries">
    <google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
  </google-map-region>
</google-map>

Then <google-map-markers>internally you may find yourself needing some hacks like this:

var map = this.$parent.map || this.$parent.$parent.map

Soon it will get out of hand. That's why we recommend dependency injection when you need to provide contextual information to any deeper component .

3) Access child component instance or child element

Despite the existence of props and events, there may be times when you need to access a child component directly in JavaScript. For this purpose, you can assign an ID reference to the child component via the refattribute . E.g:

 

<base-input ref="usernameInput"></base-input>

Now in refyour you can use:

<strong>this.$refs.usernameInput</strong>

to access this <base-input>instance for emergencies. Such as programmatically focusing the input from a parent component. In the previous example, the <base-input>component could also use a similar to refprovide access to the specified element inside, for example:

This allows the parent component to <base-input>focus the input field in :

this.$refs.usernameInput.focus()

refWhen v-forused with and , the reference you get will be an array containing these subcomponents for the corresponding data source.

$refsOnly take effect after the component has been rendered, and they are not reactive. It just means an "escape hatch" encapsulated by a direct child component - you should avoid accessing it in templates or computed properties $refs.

4) Dependency Injection

In the above example of Google Maps when accessing the parent instance:

<google-map>
  <google-map-region v-bind:shape="cityBoundaries">
    <google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
  </google-map-region>
</google-map>

In this component, <google-map>all descendants of , need to access a getMapmethod in order to know which map to interact with. Unfortunately, using the $parentprop doesn't scale well to deeper nested components. This is also where dependency injection comes in, using two new instance options: provideand inject.

provideOptions allow us to specify the data/methods we want to provide to descendant components. In this case, it's the <google-map>inner getMapmethod:

provide: function () {
  return {
    getMap: this.getMap
  }
}

Then in any descendant component, we can use options to receive specific properties we want to add to this instance: inject

inject: ['getMap']

2. Programmatic event listeners

Now that you know $emitthe usage of , it can be v-onlistened to, but the Vue instance also provides other methods in its event interface. We can:

  • by $on(eventName, eventHandler)listening to an event
  • $once(eventName, eventHandler)By listening to an event at a time
  • $off(eventName, eventHandler)Stop listening to an event by

You won't normally use these, but they are useful when you need to manually listen for events on a component instance. They can also be used in code organization tools. For example, you may often see this pattern of integrating a third-party library: the following code is a bit confusing:

https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E9%80%92%E5%BD%92%E7%BB%84%E4%BB%B6

above this

3. Circular references

1) Recursive components

Components can call themselves from their own templates. But they can only do this with nameoptions :

name: 'unique-name-of-my-component'

When you register a component with Vue.componentglobal , the global ID is automatically set as the component's nameoption.

Vue.component('unique-name-of-my-component', {
  // ...
})

With little care, recursive components can lead to infinite loops:

name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'

Components like the above will result in "max stack size exceeded" errors, so make sure the recursive call is conditional (eg using one falsethat v-if).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324359684&siteId=291194637