Author: Milos Protic

Translator: Front-end wisdom

Source: medium

The more you know, the more you don’t know

Like it and see. Make it a habit


GitHub: github.com/qq449245884… Has included more categories of previous articles, as well as a lot of my documentation and tutorial material. Welcome Star and Perfect, you can refer to the examination points for review in the interview, I hope we can have something together.

What is application state and why do we need it?

State management is usually not needed in smaller projects, but when it comes to larger scale, such as enterprise applications, it is mostly needed. Simply put, a state is an object that contains the most recent value used by the application. However, if we look at it from a structural, more abstract point of view, it becomes clear that state is an important piece of complexity that enables clean architecture and a strong separation of concerns.

Often, inexperienced developers cannot predict the need for state management and how to implement it, making it difficult to understand the importance of state management. If state-based components pile up, managing and sharing data between them becomes a nightmare. The more state-based components you have, the more problems you have in the long run.

If external packages are not used for state management, it is best to use state-based components as little as possible, while presentation components use the state built around them.

Vue and stateless (function) components

Stateless components in Vue are function components. But what about function components? To answer this question, we must first understand what functional programming is.

Unlike the object-oriented approach of breaking up programs into objects, functional programming encourages breaking up programs into small functions that are used to form higher-level programs. We create functions that do not depend on or can change any external state, which leads to another observation that they always return the same output for a given input.

Therefore, a function component is a stateless component and can be changed. The function component output is always based on the given input. On the Vue side, such components give different output depending on the given props.

grammar

Vue provides an easy way to define function components. All we need is a functional keyword. In version 2.5.0 and above, if single-file components are used, template-based functional components can be declared as follows:

<template functional> <div> function/stateless component </div> </template>Copy the code

or

export default { functional: true, props: { // ... }, render(createElement, context) {return createElement('div', 'function/stateless component')}}Copy the code

Note: Prior to 2.3.0, if a functional component wanted to receive a prop, the props option was required. In versions 2.3.0 and above, you can omit the props option, and features on all components are automatically resolved implicitly to prop.

When using functional components, the reference will be htmlElements because they are stateless and instance-free.

Note that the only data passed to the function component is props. These components are completely stateless (no response data), they ignore any state passed to them, and do not fire any lifecycle methods (created, Mounted, and so on).

Also, we cannot access instances by using the this keyword, because these components are not instantiated either. Instead, everything a component needs is provided through the context. In the Render function, it is passed as the second argument to the createElement method.

Everything a component needs is passed through the context parameter, which is an object containing the following fields:

  • Props: Objects that provide all prop

  • Children: array of VNode children

  • Slots: a function that returns an object containing all slots

  • ScopedSlots: (2.6.0+) An object that exposes the incoming scope slots. Normal slots are also exposed as functions.

  • Data: The entire data object passed to the component as the second parameter to createElement

  • Parent: reference to the parent component

  • An object containing all event listeners registered by the parent component for the current component. This is an alias for data.on.

  • Injections: (2.3.0+) If the Inject option is used, then the object contains attributes that should be injected.

Why do we need stateless components

So far, we have seen that function components are stateless; in their core, they are simply executable functions that take some input and provide an output based on it.

In terms of their usage, functional components are much less expensive to render because they are just functions, which means they are very efficient and don’t take much time to render. Meanwhile, consider higher-order components, which do not require any state; all they need to do is wrap a given child component with additional logic or style.

Next, the general example shows when to use function components, which are perfect for this type of task.

The instance

In this example, we create a Panel component that acts as a wrapper and provides the required styles. The child components will be rendered in the panel body:

export default { name: 'panel', functional: true, props: { title: String }, render(createElement, context) { const slots = context.slots(); const header = createElement('header', { attrs: { class: 'panel-header'} }, context.props.title); const body = createElement('main', { attrs: { class: 'panel-body'} }, slots.default); return createElement('section', { attrs: { class: 'panel' } }, [header, body]); }}Copy the code

As mentioned above, the sole purpose of this component is to provide a panel-like (card) style with header and main elements that hold the panel title and HTML content, respectively. The whole process is done using the createElement parameter in the Render function. CreateElement is part of the virtual Dom system implemented in the Vue core.

Virtual DOM

Vue tracks how it changes the real DOM by creating a virtual DOM. Take a closer look at this line of code:

return createElement('h1', this.blogTitle)
Copy the code

What exactly does createElement return? It’s not an actual DOM element. It might be more accurately called createNodeDescription, because it contains information that tells the Vue what nodes need to be rendered on the page, including descriptions of their children. We describe such a node as a “virtual node”, often abbreviated to “VNode”. “Virtual DOM” is the name we use for the entire VNode tree built from the Vue component tree.

CreateElement method parameter

The next thing you need to be familiar with is how to use those functions in the template in the createElement function. Here are the parameters accepted by createElement:

/ / @ returns {VNode} createElement method (/ / {String | Object | Function} / / an HTML tag name, component options Object, Or // resolve an async function of any of the above. Required fields. 'div', // {Object} // a data Object corresponding to the attributes in the template. Optional. {/ / (see the next section)}, / / {String | Array} / / child (VNodes), virtual node by ` createElement method () is constructed from the `, / / you can also use the String to generate the "text" virtual node. Optional. [' write some text ', createElement('h1', 'headline '), createElement(MyComponent, {props: {someProp: 'foobar'}})]Copy the code

The CSS style of the panel is as follows:

.panel {
  margin-bottom: .5rem
}

.panel, .panel-header {
    border: 1px solid #d3d3d3;
    border-radius: 4px;
}

.panel-header, .panel-body, .panel {
  padding: .5rem;
}

.panel-header {
  background-color:#efefef;
  color: #eeeee
}
Copy the code

This is a straightforward CSS that provides some padding and color.

Child components

Now, to bring the example to life, let’s create two more add-ons, one that displays a list of cars, and one that is just a simple lorem- Ipsum text component that has the same panel style and look.

List components:

export default {
  name: 'cars',
  props: {
    data: Array
  }
}
Copy the code

The template:

<template>
  <ul>
    <li v-for="car in data" :key="car">{{car}}</li>
  </ul>
</template>
Copy the code

Text component:

export default {
  name: 'lorem-ipsum'
}
Copy the code

template:

<template> <p> Lifelong learner, lifelong learner, lifelong learner, lifelong learner </p> </template>Copy the code

Now that we have the child components available, all we need to do is wrap them in the application using the Panel component, as shown below:

<div class="vue-app">
  <panel :title="'Car Manufacturers'">
    <cars :data="['Mazda', 'Ford', 'Mercedes']"></cars>
  </panel>
  <panel :title="'Lorem Ipsum'">
    <lorem-ipsum></lorem-ipsum>
  </panel>
</div>
Copy the code

Note that these components are used because the example is simple. In practice, it can be any type of component.

The complete code

hmtl

<div class="vue-app"> <panel :title="'Car Manufacturers'"> <cars :data="['Mazda', 'Ford', 'Mercedes']"></cars> </panel> <panel :title="'Lorem Ipsum'"> <lorem-ipsum></lorem-ipsum> </panel> </div> <script type="text/x-template" id="cars"> <template> <ul> <li v-for="car in data" :key="car">{{car}}</li> </ul> </template> </script> <script type="text/x-template" id="lorem-ipsum"> <template> <p> Lifelong learner </p> </template> </script>Copy the code

css

body {
  padding: .5rem
}

* {
  padding: 0;
  margin:0;
  box-sizing: border-box;
}

.panel {
  margin-bottom: .5rem
}

.panel, .panel-header {
    border: 1px solid #d3d3d3;
    border-radius: 4px;
}

.panel-header, .panel-body, .panel {
  padding: .5rem;
}

.panel-header {
  background-color:#efefef;
  color: #eeeee
}

ul {
  list-style: none;
}

ul > li {
  padding: .5rem .2rem
}
Copy the code

js

// the wrapper panel
const panel = {
  functional: true,
  name: "panel",
  props: {
    title: String
  },
  render(createElement, context) {
    const slots = context.slots();

    const header = createElement('header', {
      attrs: { class: 'panel-header'}
    }, context.props.title);
    
    const body = createElement('main', {
      attrs: { class: 'panel-body'}
    }, slots.default);

    return createElement('section', {
      attrs: { class: 'panel' }
    }, [header, body]);
  }
}

// sample components

const cars = {
  name: 'cars',
  template: '#cars',
  props: {
    data: Array
  }
}

const loremIpsum = {
  name: 'lorem-ipsum',
  template: '#lorem-ipsum'
}

new Vue({
  el: '.vue-app',
  components: {
    panel,
    cars,
    'lorem-ipsum': loremIpsum
  }
});
Copy the code

Operation effect:


The bugs that may exist after code deployment cannot be known in real time. In order to solve these bugs, I spent a lot of time on log debugging. Incidentally, I recommend a good BUG monitoring tool for youFundebug.

Original text: itnext. Before they go out the IO / – the – d…


communication

communication

This article is updated every week, you can search wechat “big move the world” for the first time to read and urge more (one or two earlier than the blog hey), this article GitHub github.com/qq449245884… It has been included and sorted out a lot of my documents. Welcome Star and perfect. You can refer to the examination points for review in the interview.