Categories
Angular JavaScript

Complex Angular Component Interaction Examples

Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.

In this article, we’ll look at some complex examples of Angular component interaction.

Parent Interacts with Child Via Local Variable

We can create template reference variable for the child element and then reference that variable within the template to access a child component’s variable in the parent.

For example, we can write the following code:

app.module.ts :

import { BrowserModule } from '@angular/platform-browser';  
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';  
import { AppComponent } from './app.component';  
import { PersonComponent } from './person/person.component';

@NgModule({  
  declarations: [  
    AppComponent,  
    PersonComponent  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule  
  ],  
  providers: [],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }

app.component.ts :

import { Component } from '@angular/core';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']  
})  
export class AppComponent {  
  person = {};  
}

app.component.html :

<app-person #appPerson></app-person>  
<button (click)='appPerson.setPerson()'>Set Person</button>  
<p>{{appPerson.person.name}}</p>

person.component.ts :

import { Component, Output, EventEmitter } from '@angular/core';

@Component({  
  selector: 'app-person',  
  templateUrl: './person.component.html',  
  styleUrls: ['./person.component.css']  
})  
export class PersonComponent {  
  person = {}; 

  setPerson() {  
    this.person = { name: 'Jane' };  
  }  
}

We left person.component.html blank.

In the code above, we have the PersonComponent , which is the child of AppComponent .

In PeronComponent , we have the person variable and the setPerson method.

Then in app.component.html , we added a #appPerson template variable so that we can access its variable.

Then we used it to call PersonComponent ‘s setPerson method on the Set Person button.

We also displayed appPerson.person.name from PersonComponent in the p element.

When we click the Set Person button, the p tag automatically updates to show the value of appPerson.person.name set by setPerson .

Parent calls an @ViewChild()

In the previous example, we access a child component’s local variables. It’s simple and easy, but it’s limited because the parent-child wiring is all done in the parent.

The parent component has no access to the child.

To access the child component in the parent component’s code, we can use a ViewChild .

To do use ViewChild , we can write the following code:

app.module.ts :

import { BrowserModule } from '@angular/platform-browser';  
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';  
import { AppComponent } from './app.component';  
import { PersonComponent } from './person/person.component';

@NgModule({  
  declarations: [  
    AppComponent,  
    PersonComponent  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule  
  ],  
  providers: [],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }

app.component.ts :

import { Component, ViewChild } from '@angular/core';  
import { PersonComponent } from './person/person.component';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']  
})  
export class AppComponent {  
  @ViewChild(PersonComponent, {static: false})  
  private personComponent: PersonComponent;

  setPerson(){  
    this.personComponent.setPerson();  
  }  
}

app.component.html :

<button (click)='setPerson()'>Set Person</button>  
<p>{{personComponent && personComponent.person.name}}</p>  
<app-person></app-person>

person.component.ts :

import { Component } from '@angular/core';

@Component({  
  selector: 'app-person',  
  templateUrl: './person.component.html',  
  styleUrls: ['./person.component.css']  
})  
export class PersonComponent {  
  person = {}; 

  setPerson() {  
    this.person = { name: 'Jane' };  
  }  
}

We left person.component.html blank again.

In the code above, we have the same person and setPerson members in PersonComponent .

Then in in AppComponent , we added the ViewChild as follows:

@ViewChild(PersonComponent, {static: false})  
private personComponent: PersonComponent;

to access the PersonComponent directly from within AppComponent . We need the app-person component in our PersonComponent template even though we don’t show anything in it so that AppComponent can access PersonComponent .

Then we just call the methods directly in AppComponent‘s setPerson method.

Also, we accessed the app-person component within the template with:

<p>{{personComponent && personComponent.person.name}}</p>

to show the person.name property from PersonComponent .

Parent and Children Communicate via a Service

Parent and child components can also communicate via a shared service.

We can create a service and then send the data to an Observable in the service from the child component which the parent component listens to so that it can get the latest data.

To do this, we can write the following:

app.module.ts :

import { BrowserModule } from '@angular/platform-browser';  
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';  
import { AppComponent } from './app.component';  
import { PersonComponent } from './person/person.component';  
import { PersonService } from './person.service';

@NgModule({  
  declarations: [  
    AppComponent,  
    PersonComponent  
  ],  
  imports: [  
    BrowserModule,  
    AppRoutingModule  
  ],  
  providers: [PersonService],  
  bootstrap: [AppComponent]  
})  
export class AppModule { }

person.service.ts :

import { Injectable } from '@angular/core';  
import { Subject } from 'rxjs';

@Injectable({  
  providedIn: 'root'  
})  
export class PersonService {  
  private personSource = new Subject();  
  personSource$ = this.personSource.asObservable(); 

  announcePerson(person) {  
    this.personSource.next(person);  
  }}

app.component.ts :

import { Component } from '@angular/core';  
import { PersonService } from './person.service';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']  
})  
export class AppComponent {  
  person = {}; constructor(private personService: PersonService) {  
    personService.personSource$.subscribe(  
      person => {  
        this.person = person;  
      });  
  }  
}

app.component.html :

<app-person></app-person>  
<p>{{person.name}}</p>

person.component.ts :

import { Component } from '@angular/core';  
import { PersonService } from '../person.service';

@Component({  
  selector: 'app-person',  
  templateUrl: './person.component.html',  
  styleUrls: ['./person.component.css']  
})  
export class PersonComponent {  
  constructor(private personService: PersonService) { } 

  setPerson() {  
    this.personService.announcePerson({ name: 'Jane' });  
  }  
}

person.component.html :

<button (click)='setPerson()'>Set Person</button>

In the code above, we have the PersonService , whre we created a new Subject and converted it to an Observable.

In the annoucePerson method, we take in a person object and call next on personSource to broadcast the person object via the personSource$ Observable.

Then in AppComponent , we subscribe to the personSource$ Observable by writing:

personService.personSource$.subscribe(  
      person => {  
        this.person = person;  
      });

to get the latest value of person from the Observable.

In person.component.html , we added a button as follows:

<button (click)='setPerson()'>Set Person</button>

When we click it, we call the setPerson method, which calls the annoucePerson method from the PersonService we have above with the object that we wanted to pass in.

Since AppComponent subscribed to the personSource$ Observable, we should get the latest value of person.name .

Therefore, when we click Set Person, we should get ‘Jane’ displayed on the screen.

Conclusion

We can communicate between parent and child components in many ways.

We can add a template variable on the child component in the parent template and then access its public members on the parent template.

To access a child component’s members in the parent component, we can do it via the ViewChild which references the child component in the parent component.

Lastly, we can create a service that’s shared between the parent and child component, and then called the Subject ‘s next method to broadcast the message via the Observable.

Then the parent subscribes to the Observable and gets the latest value broadcasted from there.

Categories
JavaScript React

Using Uncontrolled Components in React Apps

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at how to use uncontrolled components in React code.

Uncontrolled Components

Uncontrolled components are where we use the DOM properties to manipulate form inputs.

We can use a ref to get form values directly from the DOM.

For example, we can write the following:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.input = React.createRef();  
  } 

  handleSubmit(event) {  
    alert(`Name submitted: ${this.input.current.value}`);  
    event.preventDefault();  
  } 

  render() {  
    return (  
      <form onSubmit={this.handleSubmit.bind(this)}>  
        <label>  
          Name:  
          <input type="text" ref={this.input} />  
        </label>  
        <input type="submit" value="Submit" />  
      </form>  
    );  
  }  
}

In the code above we created the this.input ref in the constructor and attached it to the input element.

Then when we type in something and click Submit, we get whatever we typed into the input box displayed in the alert box since we accessed it with this.input.current.value .

This makes integrating React and non-React code easier since we’re using the DOM to get the value.

Default Values

The value attribute on form elements will override the value in the DOM.

With an uncontrolled component, we often want to specify the initial value and leave subsequent updates uncontrolled.

We can set the defaultValue attribute to do this:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.input = React.createRef();  
  } 

  handleSubmit(event) {  
    alert(`Name submitted: ${this.input.current.value}`);  
    event.preventDefault();  
  } 

  render() {  
    return (  
      <form onSubmit={this.handleSubmit.bind(this)}>  
        <label>  
          Name:  
          <input type="text" defaultValue="Foo" ref={this.input} />  
        </label>  
        <input type="submit" value="Submit" />  
      </form>  
    );  
  }  
}

In the code above, we set the defaultValue attribute to Foo , which is the value of this.input.current.value if we don’t change the input value.

The file input Tag

File inputs are always uncontrolled components because its value can only be set by a user and not programmatically.

Therefore, we have to use a ref to access its value.

For example, we can write the following:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.fileRef = React.createRef();  
  } 

  handleSubmit(event) {  
    alert(`Filename: ${this.fileRef.current.files[0].name}`);  
    event.preventDefault();  
  } 

  render() {  
    return (  
      <form onSubmit={this.handleSubmit.bind(this)}>  
        <input type="file" ref={this.fileRef} />  
        <input type="submit" value="Submit" />  
      </form>  
    );  
  }  
}

In the code above, we created a ref called fileRef and attached it to the file input. Then we get the files[0].name property that has the name of the selected file.

We can use the File API to do things with the selected file.

Conclusion

We can use uncontrolled components to get input values directly from the DOM.

This is useful for integrating React and non-React code. It’s also useful for quick and dirty apps.

We can set the default value of an uncontrolled input by setting the defaultValue attribute with a value.

Also, file inputs are always uncontrolled. We use the File API to manipulate selected files from file inputs.

Categories
JavaScript React

Creating Accessible React Apps — Mouse Events and Other Things

React is a library for creating front end views. It has a big ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

In this article, we’ll look at how to create accessible React apps.

Mouse and Pointer Events

Any functionality that’s exposed through a mouse or pointer event should also be accessible using the keyboard alone.

We should use onBlur and onFocus on buttons, if we’re using them to toggle something on or off.

For example, we should write:

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = { open: false };  
  } 

  handleClick() {  
    this.setState({ open: true });  
  } 

  handleFocus() {  
    this.setState({ open: true });  
  } 

  handleBlur() {  
    setTimeout(() => {  
      this.setState({ open: false });  
    });  
  } 

  render() {  
    return (  
      <div  
        onFocus={this.handleFocus.bind(this)}  
        onBlur={this.handleBlur.bind(this)}  
        aria-expanded={this.state.open}  
      >  
        <button onClick={this.handleClick.bind(this)}>Menu</button>  
        {this.state.open && (  
          <ul>  
            <li>Apple</li>  
            <li>Orange</li>  
            <li>Mengo</li>  
          </ul>  
        )}  
      </div>  
    );  
  }  
}

In the code above, we have the handlers for blur and focus events handlers attached to the wrapper div.

Also, we have the aria-expanded attribute to indicate whether the div has an expanded menu.

When we press the tab button to focus on the button, we can toggle the menu without the mouse. This is what we want since not everyone can use a mouse or another pointing device.

More Complex Widgets

We should put in HTML aria attributes so that our components are accessible to React components.

This is even more important for complex components since they have many parts.

Setting the Language

We should set the language of the page so that screen reader software can use it to set the right voice settings.

Setting the Document Title

The title text should correctly describe the current page so that users are aware of the page’s content.

Color Contrast

Elements should have enough contrast so that they can be readable by viewers with low vision.

We can calculate color combinations with enough contrast by using the Colorable package.

Testing The Keyboard

We should test if everything can navigate to with only the keyboard.

To do this, we can press Tab and Shift+Tab to navigate forward and backward respectively.

Also, we should be able to use the Enter key to activate elements.

Arrow keys should work with menus and dropdowns.

eslint-plugin-jsx-a11y

ESLint has a plugin to check for accessibility issues in JSX code. Many IDE integrate with this directly.

It an NPM package so that we can install it by running:

npm install eslint --save-dev

We can install the package and put in the following to the .eslintrc file of our project as follows:

{  
  "extends": ["react-app", "plugin:jsx-a11y/recommended"],  
  "plugins": ["jsx-a11y"]  
}

Testing Accessibility in the Browser

We can test for accessibility by using the aXe-core package for automated testing of accessibility.

Screen Readers

Screen readers should be able to read the page correctly. Common screen readers include NVDA, VoiceOver, and JAWS.

There’s also a ChromeVox extension for Google Chrome.

Conclusion

There’re many aspects to consider to make React apps accessible. We should set the language, title, and aria attributes correctly.

Also, elements on a page should be accessible via the keyboard.

We can use ESLint plugins and automated testing tools to test accessibility.

Categories
JavaScript Vue

Handling Form Input with Vue.js — Input Bindings

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to bind data in various ways and automatically modify inputs.

Value Bindings

v-model bind values usually as static strings, or booleans for a checkbox.

For example, for checkbox, we can bind it to a string as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    selected: undefined  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      foo  
      <input type="radio" v-model="selected" value="foo" />  
      <br />  
      bar  
      <input type="radio" v-model="selected" value="bar" />  
      <br />  
      <span>Selected: {{ selected }}</span>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

Checkboxes are bound to a boolean value:

<input type="checkbox" v-model="toggle">

Select are bound to the selected string set in the value attribute:

<select v-model="selected">     
  <option value="foo">Foo</option>   
</select>

Checkbox

We can change the true and false value of a checkbox with the true-value and false-value attributes as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    selected: undefined  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      Toggle  
      <input  
        type="checkbox"  
        v-model="selected"  
        true-value="yes"  
        false-value="no"  
      />  
      <br />  
      <span>Selected: {{ selected }}</span>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

Then we get yes when we checked the checkbox and no otherwise.

true-value and false-value don’t affect the input’s value attribute because browsers don’t include unchecked boxes in form submissions.

We should use radio inputs to guarantee at least one item is selected.

Radio Buttons

We can bind the value attribute to the selected value with v-bind:value .

For example, we can write the following:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    pick: "",  
    foo: "foo",  
    bar: "bar"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      Foo  
      <input type="radio" v-model="pick" v-bind:value="foo" />  
      <br />  
      Bar  
      <input type="radio" v-model="pick" v-bind:value="bar" />  
      <br />  
      <p>Selected: {{ pick }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

Then v-bind:value=”foo” renders as value='foo' and v-bind:value=”bar” is rendered as value='bar' .

When we pick a value, we get foo or bar depending on which radio button is clicked.

Select Options

We can bind a value to an object as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    selected: undefined  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <select v-model="selected">  
        <option v-bind:value="{ number: 123 }">123</option>  
        <option v-bind:value="{ number: 456 }">456</option>  
      </select>  
      <br />  
      <p>Selected: {{ selected }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

Then we get either { number: 123 } or { number: 456 } displayed depending on what’s selected.

If we want to display the value of the number property, then we have to write the following:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    selected: {}  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <select v-model="selected">  
        <option v-bind:value="{ number: 123 }">123</option>  
        <option v-bind:value="{ number: 456 }">456</option>  
      </select>  
      <br />  
      <p>Selected: {{ selected.number }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

Since setting the initial value to undefined will give us an error and the app won’t run.

Modifiers

Vue comes with a few modifiers for v-model .

.lazy

We can use v-model.lazy to sync data on change events rather than input events. This means that changes are only synced when the input it out of focus.

For example, we can use it as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    msg: ""  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input v-model.lazy="msg" />  
      <br />  
      <p>Value: {{ msg }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

When we move out cursor out of the input, then we get the input value displayed.

.number

The number modifier will convert whatever’s entered into a number. This is useful because input with type='number' still returns a string.

For example, we can use it as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    age: 0  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input v-model.number="age" type="number" />  
      <br />  
      <p>Age: {{ age }}</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

.trim

We can trim whitespace automatically with the .trim modifier. To use it, we can write the following:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    msg: ""  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input v-model.trim="msg" type="text" />  
      <br />  
      <p>Value: "{{ msg }}"</p>  
    </div> <script src="src/index.js"></script>  
  </body>  
</html>

Then when we type in something with starting and ending whitespaces, they won’t show up.

So:

" a b c "

will become "a b c" .

Conclusion

We can bind dynamically to values with the v-bind:value attribute. It lets us bind value attributes to primitive values and objects.

Also, we can use various modifiers on v-model to automatically change the input value in various ways like trimming input and converting them to numbers.

Categories
JavaScript Vue

Making Code Reusable with Vue.js Mixins

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to define and use mixins to make code reusable.

Basics

We can define a mixin by writing some simple code that consists of an object with some properties of components as follows:

src/index.js :

const appMixin = {  
  created() {  
    this.hello();  
  },  
  methods: {  
    hello() {  
      this.message = "hi";  
    }  
  }  
};
new Vue({  
  el: "#app",  
  mixins: [appMixin],  
  data: {  
    message: ""  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      {{message}}  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we defined the mixin appMixin by assigning it to an object with the structure that are the same as the Vue instance.

Therefore, hello gets called when the Vue instance is created since we have the created hook in appMixin .

Then in the template, we display the message , so we get hi on the screen.

Other properties we can put include methods , components , and directives . They’ll all be merged into the object we pass into new Vue or the component options object.

If there’s anything that’s the same, the component’s options will take priority over the items in the mixin.

For example, if we have the following:

src/index.js :

const appMixin = {  
  created() {  
    this.hello();  
  },  
  methods: {  
    hello() {  
      this.message = "hi";  
    }  
  }  
};
new Vue({  
  el: "#app",  
  mixins: [appMixin],  
  data: {  
    message: ""  
  },  
  created() {  
    this.hello();  
  },  
  methods: {  
    hello() {  
      this.message = "foo";  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      {{message}}  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then foo is displayed since the methods in the Vue instance takes precedence over the methods in the mixin.

We can also use the Vue.extend method to create a new component as follows:

src/index.js :

const appMixin = {  
  created() {  
    this.hello();  
  },  
  methods: {  
    hello() {  
      this.message = "hi";  
    }  
  }  
};
const Component = Vue.extend({  
  mixins: [appMixin],  
  el: "#app"  
});

new Component();

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      {{message}}  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Vue.extend works the same way as new Vue that we have above.

The same merging mechanism is used with Vue.extend() .

Option Merging

We can adjust how items are merged by selecting the appropriate strategy for merging.

For example, data objects are merged recursively, with component’s data taking priority in case of conflicts.

src/index.js :

const mixin = {  
  data() {  
    return {  
      message: "hi",  
      foo: "abc"  
    };  
  }  
};

new Vue({  
  el: "#app",  
  mixins: [mixin],  
  data() {  
    return {  
      message: "bye",  
      bar: "def"  
    };  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      {{message}} {{foo}} {{bar}}  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

We see bye abc def displayed since message is in both the component and the mixin, and the component takes precedence.

foo and bar are only in the mixin and component respectively, so they’re both merged into the same data object.

Hooks with the same name are merged into an array so that they all will be called. Mixin hooks will be called the component’s own hooks.

So if we have:

src/index.js :

const mixin = {  
  mounted() {  
    console.log("mixin hook called");  
  }  
};

new Vue({  
  el: "#app",  
  mixins: [mixin],  
  mounted() {  
    console.log("component hook called");  
  }  
});

We see:

mixin hook called  
component hook called

in the console.log output.

Options that expect object values like methods , components , and directives are merged into the same object. The component’s options will take priority when there’re conflicts in the objects.

For example, if we have:

src/index.js :

const mixin = {  
  methods: {  
    foo() {  
      console.log("foo");  
    }  
  }  
};

const vm = new Vue({  
  el: "#app",  
  mixins: [mixin],  
  methods: {  
    foo() {  
      console.log("bar");  
    }  
  }  
});  
vm.foo();

We’ll see bar logged since the component’s foo method takes precedence over the mixin ‘s foo method.

The same merging strategies are used in Vue.extend().

Conclusion

Mixins allow us to create code that can be included in multiple components.

They’re merged by taking component’s methods , components , and directives taking precedence over the mixin’s items in these properties.

Data are merged together as well, with component’s data taking precedence if the same key exists in both places.

Hooks are merged into an array, with the mixin’s hook being called before the component’s hook if they have the same name.