preface

Vue.js is a set of progressive frameworks for building user interfaces (official description). In layman’s terms, Vue. Js is a lightweight, easy-to-use, convenient and flexible front-end MVVM framework. Concise API, good and sound Chinese documentation, so that developers can easily use the Vue framework.

This series of articles will combine some CAI experiences (KENG) and some cases in the use of Vue to export some knowledge of the Vue framework and consolidate the understanding of the Vue framework.

To know the component

Components are one of Vue’s most powerful features. Vue components are packaged and reusable, allowing you to break them down into individual modules for complex applications. Note that all Vue components are also instances of Vue and can accept the same option object.

Vue component registration

We can register a Vue component globally and locally. The difference is that globally registered components can be used anywhere. In fact, all Vue instantiations will render the global component. Local components are only registered on a Vue instantiation object and can only be rendered when the Vue is instantiated. Elsewhere they are rendered using Html tags that are treated as normal. Let’s look at global component registration first. When registering Vue components globally, you can register them using Vue.com Ponent (tagName, options). Look at a simple example.

<div id="app" class="demo">
    <! -- Vue component -->
    <simple-component></simple-component>
</div>
<script>
    Vue.component("simple-component", {
        template: " I am the simplest example of a Vue component "
    })
    new Vue({
        el: "#app"
    })
</script>
Copy the code

The Vue.component method passes in two parameters, one is the component’s custom tag name and the other is an object in which the value of the template property is the component’s template.

You may be thinking, the content of the component is too simple, only one tag, if the content of the component is more complex, do you want to use strings to concatenate the content as before? It was horrible, and even with es6’s string syntax, it was a long stretch of writing that was not elegant. Well, yes, there is a good solution to this problem in Vue that can handle complex component templates using the

<div id="app2" class="demo"> <vut-button></vut-button> </div> <script type="x-template" id="vComponent"> <div Class ="vut-button"> <span> </span> </script> <script> Vue.component("vut-button", {template: "#vComponent" }) new Vue({ el: "#app2" }) </script>Copy the code

Of course, to make the code look cleaner, you can wrap the component template with the Template tag, which is not rendered during browser rendering.

<div id="app-test" class="demo"> <vut-button></vut-button> </div> <template id="vComponent"> <div class="vut-button"> <span> Vue.component("vut-button", {template: vut-button) <span> </div> </template> <script> "#vComponent" }) new Vue({ el: "#app-test" }) </script>Copy the code

Ok, so how should local components be registered? You can register local components that are only available in their scope by using the Vue instance option Components.

<div id="app-local" class="demo">
    <! -- Vue component -->
    <simple-component></simple-component>
</div>
<script>
    new Vue({
        el: "#app-local",
        components: {
            "simple-component": {
                template: " I am the simplest example of a local Vue component "}}})</script>
Copy the code

The Vue instance option Components contains a property where the key is the name of the component and the value is an object that contains properties such as the template of the component.

Use Prop to pass data

Each Vue component instance has its own scope, which means that the parent component’s template cannot get data from the parent component. Vue can use the props parameter to pass data from the parent component to the child component.

<div id="app" class="demo"> <simple-component link="https://github.com/vuejs/vue"></simple-component> </div> <script> Vue.component(" simple-Component ", {template: "<span> </span>", props: ["link"]}) new Vue({el: "#app" }) </script>Copy the code

As you can see, we defined an array of props to receive data passed from the parent component, because the parent component can pass multiple data. Props is not necessarily an array, but can also be objects, specifying the data rules passed by the parent component, including default values, data types, and so on.

props: {
    link: {
        type: String.// Data type
        defalut: "https://www.baidu.com/" / / the default value}}Copy the code

How does the parent dynamically pass data to the child? Remember that the V-bind directive is used to dynamically bind HTML properties or props values of components, so you should use the V-bind directive to pass data dynamically.

< template id = "userComponent" > < div > < p > userName: {{userName}} < / p > < p > gender: {{sex}} < / p > < p > age: {{ age }}</p> </div> </template> <script type="text/javascript"> Vue.component("user-component", { template: "#userComponent", props: ["userName", "sex", }) </script> <div id="app2" class="demo"> <input type="text" v-model="sex" placeholder=" placeholder "> </div> <user-component :user-name="userName" :sex="sex" :age="age" > </user-component> </div> <script type="text/javascript"> new Vue({ el: "#app2", data: { userName: "", sex: "", age: "" } }) </script>Copy the code

Use custom events to implement child component communication to parent component

We know that the parent uses PROP to pass data to the child. But how do children communicate with their parents? This is where Vue’s custom event system comes in handy. Suppose we are writing a comment system, the comment section is a Vue component, and we want to display the content of the comment after it is submitted. Let’s start by writing out the comment component

<template id="comment-component">
    <div class="i-comment-area">
        <textarea rows="5" class="i-textarea" placeholder="Please enter the content" v-model="commentValue"></textarea>
        <div class="i-comment-submit" @click="handleSubmit">
            <span>submit</span>
        </div>
    </div>
</template>
Copy the code

The comment component template contains an input box and a button to submit a comment, which is as simple as that, and then registers the component globally

Vue.component("i-comment", {
    template: "#comment-component".data: function(){
        return {
            commentValue: ""}},methods: {
      handleSubmit: function(){
          if(this.commentValue.length < 1){
              alert("Comments can't be empty.");
              return;
          }
          this.$emit("content".this.commentValue);
          this.commentValue = ""; }}})Copy the code

You may notice that the data instance option in the component is not written as before. Yes, this is important when writing the component. Vue specifies that the data option in the component must be a function. The submit button is then attached with a click event called handleSubmit. When you fill in the comment content and click submit, the component will emit an event via $emit(eventName) with an argument to pass the comment content to the parent component.

The child component communicates with the parent component via $emit(eventName). How does the parent component receive data from the child component? The answer is to use $ON (eventName) to listen for events.

<div id="simple-comment" class="demo">
    <i-comment v-on:content="commentData"></i-comment>
    <label class="title">Comment on the list</label>
    <ul class="comment-list">
        <li v-for="(item,index) in commentList">
            <span>{{ item.time }}</span>
            <span>{{ item.content }}</span>
        </li>
    </ul>
</div>
Copy the code

In the parent component, listen for the event name defined in the child component and call a method called commentData. The commentData method is used to get the parameters that the child component passes to the parent, so that a child component communicates to the parent. You can see the full example.

Implement a Switch UI component

Next, implement a Switch UI component with a hands-on approach. Start by thinking about the basic apis that Switch components need.

  • Considering the usage scenario, Switch components of different sizes need to be formulated, so needsizeAPI.
  • In consideration of the possibility of disabling scenarios, the function of the component needs to be disabled and enableddisabledAPI.
  • Considering the need to customize the background color on and off, soon-coloroff-colorAPI custom background color.
  • Similarly, you may need to customize the text displayed on and off, so you need toon-textoff-textThe API defines the displayed text.
  • You might also need an event listener to get the current state and do something based on the state, so you need an event to listen for changes in the state, so you needon-changeAPI.

Now that the basic API is listed, you can start implementing the functionality step by step. Start by writing out the basic framework of the component template.

<span :class="wrapClass">
    <span :class="switchClass" @click="handleChangeFn" ref="switch">
        <input type="hidden" :value="currentValue">
    </span>
</span>
Copy the code

Then you have to register the component.

var prefixClass = "vut-switch";
Vue.component("vut-switch", {template: "#switch-component".props: {
        value: {
            type: Boolean.default: false}},data: function(){
        return {
            currentValue: this.value // Current status}},computed: {
        wrapClass: function(){
            return prefixClass + "-wrap";
        },
        switchClass: function(){
            return [
                prefixClass,
                {
                    [prefixClass + "-checked"] :this.currentValue } ]; }}})Copy the code

Basically, the shelves are set up. Then start implementing those listed apis. Let’s see how size is implemented.

Size must be passed through the parent component, so define the size object in the props option of the child component.

props: {
    value: {
        type: Boolean.default: false
    },
    size: String / / size
}
Copy the code

The idea then is to control the rendered Switch components with different styles. We add different Class values according to the different sizes of values passed in, make different styles, so switchClass calculation attribute can be like:

switchClass: function(){
    return [
        prefixClass,
        {
            [prefixClass + "-checked"] :this.currentValue,
            [prefixClass +"-"+ this.size]: this.size
        }
    ];
}
Copy the code

Then add the corresponding style.

/* Small size */
.vut-switch-small{
    width: 40px;
    height: 20px;
}
.vut-switch-small:after{
    width: 16px;
    height: 16px;
}
.vut-switch-small.vut-switch-checked:after{
    left: 22px;
}

/* Large size */
.vut-switch-large{
    width: 60px;
}
.vut-switch-large.vut-switch-checked:after{
    left: 38px;
}
Copy the code

Finally, we use the Switch component in the Vue instance initialization template.

<vut-switch size="small"></vut-switch>
<vut-switch size="large"></vut-switch>
Copy the code

Now we can control the display size of the Switch component as follows:

Then look at how to implement custom background color. Again, the data to be passed is defined in the props option of the child component.

props: {
    value: {
        type: Boolean.default: false
    },
    size: String./ / size
    onColor: String.// Custom background color when enabled
    ofColor: String // Custom background color when closed
}
Copy the code

Then we control the display of different background colors by using the current state, focusing on the currentValue value. Let’s start with a function that sets the background color based on currentValue.

setBackgroundColor: function(){
    let customColor = this.currentValue ? this.onColor : this.offColor;
    this.$refs.switch.style.backgroundColor = customColor;
}
Copy the code

This function is then called by listening for changes in currentValue.

watch: {
    currentValue: function(){
        this.setBackgroundColor(); }}Copy the code

Finally, we use the Switch component in the Vue instance initialization template.

<vut-switch on-color="#13ce66" off-color="#ff4949"></vut-switch>
Copy the code

The effect is as follows:

See the Switch component for a complete example.

Afterword.

In the spirit of learning and summarizing the attitude of the article, any mistakes and problems can be pointed out on Github. Examples are posted on Github at github.com/webproblem/… .