Explain in detail the three core concepts of vue components

  Front end, javascript, node.js, Programmer, vue.js

Preface

This article mainly introduces the three basic concepts of vue, attribute, event and slot, their usage and some important details that are easy to be ignored. If you read the components written by others, you can also expand from these three parts. They can help you quickly understand all the functions of a component.

image.png

Please stamp the code of this articleGithub blog, the paper finally feel shallow, everyone began to knock more code!

I. Attributes

1. custom properties props

Prop defines which configurable attributes this component has, and its core functions are also determined by it. When writing general-purpose components, props is best written in the form of an object, so that the type, default value or value of a custom check attribute can be set for each attribute. This is very important in component development. However, many people neglect to directly use the array usage of props. Such components are often not rigorous.

//parent component
 < propesname =' attribute'
 :type='type'
 :is-visible="false"
 :on-change="handlePropChange"
 :list=[22,33,44]
 Title= "attribute Demo"
 class="test1"
 :class="['test2']"
 : style="{ marginTop: '20px' }" // note: style takes precedence over style
 style="margin-top: 10px">
 </props>
//subcomponent
 props: {
 name: String,
 type: {
 //type passed in from the parent, its value must be one of the specified' success', 'warning', 'danger'. If values other than these three are passed in, a warning will be thrown
 validator: (value) => {
 return ['success', 'warning', 'danger'].includes(value)
 }
 },
 onChange: {
 //For the received data, it can be of various data types and can also pass a function.
 type: Function,
 default: () => { }
 },
 isVisible: {
 type: Boolean,
 default: false
 },
 list: {
 type: Array,
 //The default value of an object or array must be obtained from a factory function
 default: () => []
 }
 }

From the above example, it can be concluded that props can display and define one or more data. For the received data, it can be of various data types.You can also pass a function.

2.inheritAttrs

This is a new API added in 2.4.0. By default, the attribute binding of the parent scope that is not considered props will be “rolled back” and applied to the root element of the child component as a normal HTML attribute. These default behaviors will be removed by setting inheritAttrs to false. Note:This option does not affect class and style binding..
In the previous example, the title attribute is not declared in props in the subcomponent, and will be hung on the root element of the subcomponent by default, as shown in the following figure:

3. difference between data and props

  • Same point

All kinds of data can be stored in both options. When the behavior operation changes, the data used in all the behavior operations and rendered by the template will change synchronously at the same time.

  • Difference

Data is called dynamic data. In each instance, we can change it at will under any circumstances.Data type and data structure, will not be affected by any environment.

Props is called static data. In each instance, once the defined type is initialized, based on Vue being a one-way data stream, its data type cannot be changed during data transfer. Moreover, it is not allowed to directly operate the transferred props data in the sub-components, but the data in the transfer source needs to be changed by other means. As for how to change, we will go on to introduce in detail:

4. One-way data flow

This concept appears in component communication. Props data is passed through parent component or higher level component data or literal methods. Direct operation is not allowed to change props data in respective instances, but data in the transmission source needs to be changed through other means. If we sometimes want to modify the prop passed, what are the methods?

  • Method 1: Transition to data Option

Copy a copy of prop in the data of the subcomponent, and the data can be modified.

export default {
 props: {
 type: String
 },
 data () {
 return {
 currentType: this.type
 }
 }
 }

In the data option, receiving type data in props through currentType is equivalent to performing an assignment operation on currentType= type, not only obtaining currentType data, but also changing currentType data.

  • Method 2: Using Calculation Attributes
export default {
 props: {
 type: String
 },
 computed: {
 normalizedType: function () {
 return this.type.toUpperCase();
 }
 }
 }

Although the above two methods can indirectly modify the value of props in the subcomponent, it is of no help if the subcomponent wants to modify the data and synchronously update to the parent component. In some cases, we may need to “double bind” a prop. At this time, the following two methods are recommended:

  • Method 3: Use. sync
//parent component
 <template>
 <div class="hello">
 <div>
 < p > parent component msg: {{msg}} </p >
 < p > parent component array: {{ arr }}</p >
 </div>
 < button @click="show = true "> open the model box < /button >
 <br />
 <demo :show.sync="show" :msg.sync="msg" :arr="arr"></demo>
 </div>
 </template>
 
 <script>
 import Demo from "./demo.vue";
 export default {
 name: "Hello",
 components: {
 Demo
 },
 data() {
 return {
 show: false,
 Msg: "Simulate a model Box",
 arr: [1, 2, 3]
 };
 }
 };
 </script>
//subcomponent
 <template>
 <div v-if="show" class="border">
 < div > subcomponent msg: {{msg}} </div >
 < div > subcomponent array: {{ arr }}</div >
 < button @click="closeModel "> close model box < /button >
 < button @ click = "$ emit ('update: msg',' sailing on the waves')" >
 Change text
 </button>
 < button @ click = "arrow. push ('front-end craftsman')" > change array < /button >
 </div>
 </template>
 <script>
 export default {
 props: {
 msg: {
 type: String
 },
 show: {
 type: Boolean
 },
 arr: {
 Type: Array // changing the passed array in the child component will affect the state of the parent component
 }
 },
 methods: {
 closeModel() {
 this.$emit("update:show", false);
 }
 }
 };

props.gif

The parent component passed msg and show values to the child component props, both using the. sync modifier for bidirectional binding.
However. sync is good, but there are also restrictions, such as:

1)Cannot be used with expressions(e.g.v-bind:title.sync="doc.title + '!' "Is invalid);
2)Cannot be used on literal objects(e.g.v-bind.sync="{ title: doc.title }"Is unable to work normally).

  • Method 4: Wrap the data in the parent component as an object and pass it to the child component

This is because objects and arrays are passed in by reference in JavaScript, so for prop of an array or object type, changing the object or array itself in a subcomponent will affect the state of the parent component. For example, in the example above, the array arr passed by the parent component is modified in the child component to change the state of the parent component.

5. Add or not add v-bind when transferring data to sub-components?

For literal grammar and dynamic grammar, beginners may feel confused whether to add or not v-bind when passing data to child components in the parent component template.

v-bind:msg = ‘msg’

This is to pass data through v-bind and the data passed is not a literal quantity, the parsing in double quotation marks is an expression, and it can also be the data and methods defined on the instance (in fact, it refers to a variable).

Msg=’ Sailing in the Waves’

In this mode without v-bind, only one literal can be passed, and this literal is limited to String class quantity and string type. If you want to transfer data by literal quantity,If you want to pass a non-String type, you must precede the props name with v-bind, internal through the instance to find, if the instance side does not have this attribute and method, the default is the corresponding data type.

:msg='11111' //Number
 :msg='true' //Bootlean
 :msg='()=>{console.log(1)}' //Function
 :msg='{a:1}' //Object

II. Events

1. Event-driven and Data-driven

Using native JavaScript events to drive a process is usually like this:

  • First find the node to be operated through a specific selector-> add corresponding event monitoring to the node
  • Then the user executes an event (click, enter, back, etc)-> calls JavaScript to modify the node

This mode has no problem for the business, but it is not ideal in terms of development cost and efficiency, especially when the business system is getting larger and larger. On the other hand, the efficiency of finding and modifying nodes is itself very low, so a data-driven mode appears.

One of Vue’s core ideas is data-driven. The so-called data drive means that the view is generated by the data drive. When we modify the view, we do not directly operate DOM, but modify the data. The process is as follows:

The user performs an operation-> feedback to VM processing (which can cause Model changes) -> VM layer changes, and directly updates the data at the corresponding position of the page through binding relationships

It can be simply understood that the data driver does not operate the node, but directly updates the page through the virtual abstract data layer. It is mainly because of this that the data-driven framework can run faster (because there is no need to disturb nodes) and can be applied to large-scale projects.

2. Modifier event

Vue events are divided into ordinary events and modifier events, here we mainly introduce modifier events.

Vue provides a large number of modifiers to encapsulate these filters and judgments, allowing developers to write less code and devote all their time to business and logic, and only need to call through one modifier. Let’s think about this question first: how to bind a native click event to this custom-component?

< custom-component > component content < /custom-component >

If your answer is yes<custom-component @click="xxx">, that is wrong. The @click here is a custom event click, not a native event click. The binding native click looks like this:

< custom-component @ click.native = "XXX" > component content < /custom-component >

Event modifiers are indispensable in the actual development process. Common event modifiers include the following:

  • Form modifier

    1).lazy

By default,v-modelEvery timeinputAfter the event is triggered, the value of the input box is synchronized with the data. You can addlazyModifier to convert to using thechangeEvents are synchronized. This is applicable to scenes where the view is updated only after the cursor leaves after all the contents have been entered.

2).trim

If you want to automatically filter the leading and trailing white space characters entered by the user, you can add trim modifier to v-model:

<input v-model.trim="msg">

This modifier can be used to filter out the scenes where the password is typed and the space is accidentally tapped. It should be noted that,It can only filter the leading and trailing spaces! First and last, the middle will not be filtered.

3).number

If you want to automatically convert the user’s input value to a numeric type, you can add a number modifier to v-model:

<input v-model.number="value" type="text" />

number.gif

From the above example, we can get that if you enter a number first, it will restrict you to enter only numbers. If you enter a string first, it is equivalent to not adding. number.

  • Event modifier
<!  -prevent click events from continuing to propagate->
 <a v-on:click.stop="doThis"></a>
 
 <!  -submit events no longer reload pages->
 <form v-on:submit.prevent="onSubmit"></form>
 
 <!  -modifiers can be concatenated->
 <a v-on:click.stop.prevent="doThat"></a>

III. Slots

Slots are divided into normal slots and scope slots, which are very similar, except that scope slots can accept parameters passed by subcomponents.

1. Scope Slot

We might as well learn about the scope slot through a todolist example. If the text turns yellow when item is selected (as shown in the figure below), how will this be achieved?
slot.gif

//parent component
 <template>
 <div class="toList">
 < input v-model = "info" type = "text"/> < button @ click = "additem" > add < /button >
 <ul>
 <TodoItem v-for="(item, index) in listData" :key="index">
 < template v-slot: item = "itemprops" >//this is a named slot
 //where the value of itemProps is the object passed by the subcomponent.
 <span
 :style="{
 fontSize: '20px',
 color: itemProps.checked ?  'yellow' : 'blue'
 }"
 >{{ item }}</span
 >
 </template>
 </TodoItem>
 </ul>
 </div>
 </template>
 <script>
 import TodoItem from "./TodoItem";
 export default {
 components: {
 TodoItem
 },
 data() {
 return {
 info: "",
 listData: []
 };
 },
 methods: {
 addItem() {
 this.listData.push(this.info);
 this.info = "";
 }
 }
 };
 </script>
//subcomponent
 <template>
 <div>
 <li class="item">
 <input v-model="checked" type="checkbox" />
 < slot name = "item": checked = "checked" > </slot >//pass checked value to parent component
 </li>
 </div>
 </template>
 <script>
 export default {
 data() {
 return {
 checked: false
 };
 }
 };
 </script>

It is worth noting that the object syntax of v-bind:style is very intuitive-it looks very like CSS, but it is actually a JavaScript object. CSS attribute names can be named by camelCase or dash-case (remember to use quotation marks).

2. new 2.v-slot grammar

In 2.6.0, we introduced a new unified syntax (i.e.v-slotInstructions). It replacedslotAndslot-scope.
We introduce the new syntax for the default slot, named slot, and scope slot through an example:

//parent component
 <template>
 <div class="helloSlot">
 < h2>2.6 new syntax < /h2 >
 <SlotDemo>
 < p > default slot: default slot</p >
 <template v-slot:title>
 < p > named slot: title slot1</p >
 < p > named slot: title slot2</p >
 </template>
 <template v-slot:item="props">
 < p > scope slot: item slot-scope {{ props }}</p >
 </template>
 </SlotDemo>
 </div>
 </template>
 <script>
 import Slot from "./slot";
 export default {
 components: {
 SlotDemo: Slot
 }
 };
 </script>
//subcomponent
 <template>
 <div>
 <slot />
 <slot name="title" />
 <slot name="item" :propData="propData" />
 </div>
 </template>
 <script>
 export default {
 data() {
 return {
 propData: {
 Value: "Sailing in the Waves"
 }
 };
 }
 };
 </script>

slot

Welcome to pay attention to the public number:Front end craftsmanWe witness your growth together!
image

Reference article