Translator: Tips from Dmitri Pavlutin

Have a dream, have dry goods, wechat search [big Move the world] pay attention to this in the early morning is still in the bowl washing wisdom.

In this paper, making github.com/qq449245884… Has been included, a line of large factory interview complete test sites, information and my series of articles.

Recently, I needed to update the state of a component every time its contents (slots, child components, and so on) changed. For context, it is a form component that tracks the validity status of its input.

The code snippet below is written in Options API format, but can be used in Vue2 and Vue2 except where specified.

start

Start by controlling the form state and modify a class based on the state. Fill the child content with
:

<template>
  <form :class="{ '--invalid': isInvalid }">
    <slot />
  </form>
</template>

<script>
export default {
  data: () => ({
    isInvalid: false,
  }),
};
</script>
Copy the code

To update the isInvalid property, we need to add a triggered event, which could be a sumit event, but I prefer an input event.

Form events 7: focus, blur, input, SELECT, change, reset, submit, etc.

The form does not trigger an input event, but we can use “event delegate”. We attach listeners to the parent element (

) and fire when events occur on its children (
, < SELECT >,

Any time an input event is triggered in

of this component, the form captures that event.

<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: False,}), the methods: {the validate () {/ / validation logic}}}; </script>Copy the code

The validation logic can be simple or complex. To demonstrate, this article uses the form.checkvalidity () API as a simple way to see if the form is valid based on HTML validation attributes.

To access the

element. You can use the refs or $EL attribute. For simplicity, this article uses $el.
<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), methods: { validate() { this.isInvalid = ! this.$el.checkValidity() } } }; </script>Copy the code

The problem

There’s a bit of a problem here. What happens if the content of the form changes? What happens if a is added to the DOM during form loading?

For example, we call this form component “MyForm”. In our App, it looks like this:

// App.vue <template> <MyForm> <input v-model="showInput" id="toggle-name" name="toggle-name" type="checkbox" /> <label For ="toggle-name"> <template V-if ="showInput"> <label for="name"> name :</label> <input ID ="name" Name ="name" required /> </template> <button type="submit" </button> </MyForm> </template> <script> import Form from "./components/form.vue"; export default { name: "App", components: { MyForm: Form, }, data: () => ({ showInput: false, }), }; </script>Copy the code

When app.vue hides some input through conditions, our form needs to know. In this case, we might want to track the validity of the form as its contents change, not just on input events or Mounted lifecycle hooks. Otherwise, incorrect information may be displayed.

If you’re familiar with Vue’s lifecycle hooks, you might think of using Update to track changes. In theory, that sounds good. In practice, it creates an infinite loop and the browser hangs.

The solution

After some research and testing, the best solution was to use the MutationObserver API. It is a browser-built method that provides the ability to monitor changes made to the DOM tree, and the API can be notified of node additions or deletions, attribute changes, and text content changes.

It is a native method, so it is not limited to the framework.

To do this, you first create an observer instance using the MutationObserver constructor and specify the instance’s callback function. This callback is called each time it is called after a DOM change. This callback takes two arguments, the first an array of variables and the second an observer instance, rewriting our form component as follows:

<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), mounted() { const observer = new MutationObserver(this.validate); observer.observe(this.$el, { childList: true, subtree: true, }); this.observer = observer; }, methods: { validate() { this.isInvalid = ! this.$el.checkValidity(); }, }, beforeUnmount() { this.observer.disconnect(); }}; </script> <style scoped> </style>Copy the code

There is also a need to disconnect the Observer using the beforeUnmount life cycle event, which clears any memory it has allocated.

Finally, we pass the isInvalid state to the plug-in slot for the content to access, also known as the scoped slot, which is very useful.

<template> <form :class="{ '--invalid': isInvalid }" @input="validate"> <slot v-bind="{ isInvalid }" /> </form> </template> <script> export default { data: () => ({ isInvalid: false, }), mounted() { const observer = new MutationObserver(this.validate); observer.observe(this.$el, { childList: true, subtree: true, }); this.observer = observer; }, methods: { validate() { this.isInvalid = ! this.$el.checkValidity(); }, }, beforeUnmount() { this.observer.disconnect(); }}; </script>Copy the code

With this setup, we can add any number of inputs to our form component and any conditional rendering logic it needs. As long as the input uses HTML to validate the property, the form keeps track of whether it is in a valid state.

In addition, by using a scope slot, we provide the state of the form to the parent, so the parent can react to changes in validity.

For example, in app. vue, we want to “disable” the submit button if the form is invalid

<template>
  <MyForm>
    <template slot:default="form">
      <label for="name">Name:</label>
      <input id="name" name="name" required>

      <button
        type="submit"
        :class="{ disabled: form.isInvalid }"
      >
        Submit
      </button>
    </template>
  </MyForm>
</template>
Copy the code

nice~.

I hope this article will help you in your future career.

~ over, I am small wisdom, ready to field massage, show up!


Original text: austingil.com/watching-ch…

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.

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.