This is the fifth day of my participation in the August Wen Challenge.More challenges in August

preface

Recently, I encountered a need to modify the original Modal to support rich text content when writing Vue. The original Modal component is roughly:

<template>
    <div>
        <div>{title}</div>
        <div>{desc}</div>
        <button>confirm</button>
    </div>
</template>
<script>
export default {
    props: ['title'.'desc'],}</script>
Copy the code

Use this Modal component:

<template>
    <Modal title="Windows" desc="Are you sure you want to close?" />
</template>
Copy the code

The current requirement requires that the part of desc be dynamic rich text, such as:

this.desc = Are you sure you want to close it? 
Copy the code

Also, clicking < SPAN > User Protocol takes you to the User protocol page.

Plan a

Because of the need to render rich text, the first solution that comes to mind is to render rich text via V-HTML. For click events, you need to define a unique ID or class name, and then add native click events, code like this:

<! - Modal component - > < template > < div > < div > {title} < / div >- 
      
{desc}
+
</button> </button> </div> </template> <script> export default {props: ['title', 'desc'],} </script>Copy the code

After modification, Modal now supports rendering rich text elements, but does not yet handle click events. Now add the click event logic.

this.desc = Are you sure you want to close it? 
this.$nextTick(() = > {
    document.querySelector('#user-rule').addEventListener('click'.() = > {
        // do something})})Copy the code

As you can see above, the implementation does address this requirement, but there are some problems:

  • How to ensure that the selector does not repeat
  • Click events are wrapped in $nextTick, but sometimes completion of this.desc is not guaranteedspan id="user-rule"Must be added to the DOM. (For example, when you use Modal components, instead of parent-child relationships, there are n layers nested and some delayed processing in each layer)

For the first problem, it’s easier to fix. Check to see if a unique selector exists before setting it, and then create a new one. But the second problem is more difficult to solve.

Now let’s see if there are other alternatives.

Scheme 2

Since Vue is used, can we use Vue to solve this problem?

Here we write a piece of pseudo code to see the specific idea:

  • First modify the part of the Modal component that renders Desc:
<! - Modal component - > < template > < div > < div > {title} < / div >- 
      
{desc}
+ </button> </button> </div> </template> <script> export default {props: ['title', 'desc'],} </script>Copy the code

As you can see, the Modal component now supports DESC and can pass in component types.

  • Then use the Vue component for rendering the rich text.

this.desc = {
    methods: {
        onUserRuleClick() {
            // do something}},render: () = > <div>Are you sure you want to close it? Click here to read<span onClick={this.onUserRuleClick} style="color: blue;">User agreement</span>~
    </div>,}Copy the code

As you can see, we have created a Vue component and assigned it to desc, and the click event related handling is also written as a Vue component.

We don’t have to deal with:

  • Uniqueness of span tag selectors
  • Desc-related click events

Tips

Option 2 code may not run in all environments because the render part of the function uses JSX syntax directly. There are two solutions to this problem:

  • Modify render JSX notation
render(h) {
    return h(
        'div', {},'Are you sure you want to close it? Click to read ',
            h('span', {
                style: 'color: blue; '.on: {
                    click: this.onUserRuleClick,
                }
            }, User Agreement)
            '~',])}Copy the code
  • Install the @vue/ babel-PRESET – JSX plugin

conclusion

It can be seen that scheme 2 uses the component rendering capability of Vue. Compared with Scheme 1, click events have been added after DOM rendering, so there is no need for developers to consider when to bind events. In addition, when the rich text rendered has many events to bind or it is not known when the rich text is added to the DOM, Option one does not meet the requirements.

Welcome to share!