Dcat Admin 自定义页面 script 标签内的 HTML 闭合标签(例如 </li> )被自动删除的解决办法

问题描述

今天我尝试将 Vue 引入 Dcat Admin 的自定义页面中,因为自定义页面中使用 JQuery操作 DOM 很麻烦。本来一切都很顺利,但在我尝试将 Vue 组件引入页面的时候,看到浏览器控制台有一行警告信息,提示 Vue 组件的 template 中的 HTML 元素缺失闭合标签,警告信息如下:

Dcat Admin 自定义页面 script 标签内的 HTML 闭合标签(例如 </li> )会被自动删除

我找到了 Dcat Admin 为该自定义页面生成的代码,如下:

Dcat Admin 自定义页面 script 标签内的 HTML 闭合标签(例如 </li> )会被自动删除

template 中的 HTML 元素确实没有闭合标签,但是我的代码是写了闭合标签的:

// custom-color.blade.php:

<div id="custom-color-page">
    ...
</div>
<script init="#custom-color-page">
    ......
    window.vueApp = Vue.createApp(customColorPage);
    window.vueApp.component('todo-item',{
        props: ['todo'],
        template: '<li> @{{ todo.text }} </li>',
        data(){
            return {
                name: 'Song'
            }
        }
    })
    window.vueApp.mount('#custom-color-page');
</script>

我百思不得其解,起初以为是 Vue 与 Dcat Admin 有冲突,于是我就尝试用 JQuery 试一下:

// custom-color.blade.php:

<div id="custom-color-page">
    ...
</div>
<script init="#custom-color-page">
    console.log(jQuery('<li>item</li>'));
</script>

Dcat Admin 生成的该自定义页面对应的代码如下:

Dcat Admin 自定义页面 script 标签内的 HTML 闭合标签(例如 </li> )会被自动删除

也是同样的问题,HTML 元素的闭合标签丢失了。

于是,我使用 dd()函数一步一步调试,最后发现问题出在以下代码里:

    /**
     * @param  string  $html
     * @return DOMDocument
     *
     * @throws \Throwable
     */
    protected static function getDOMDocument(string $html)
    {
        $dom = new DOMDocument();

        libxml_use_internal_errors(true);

        $dom->loadHTML('<?xml encoding="utf-8" ?>'.$html);

        // 执行完 $dom->loadHTML 后,script 标签内 HTML 元素的闭合标签完全丢掉了

        libxml_use_internal_errors(false);

        return $dom;
    }

也就是说, DOMDocument 实例在执行完 loadHtml 方法后将 script 标签内的 HTML 元素的闭合标签移除掉了。至于原因我也没有搞清楚。

解决办法

在闭合标签的斜杠(/)前加个反斜杠(\),更改后的代码如下:

// custom-color.blade.php:

<div id="custom-color-page">
    ...
</div>
<script init="#custom-color-page">
    ......
    window.vueApp = Vue.createApp(customColorPage);
    window.vueApp.component('todo-item',{
        props: ['todo'],
        // 闭合标签处加了反斜杠
        template: '<li> @{{ todo.text }} <\/li>',
        data(){
            return {
                name: 'Song'
            }
        }
    })
    window.vueApp.mount('#custom-color-page');

现在,控制台没有标签闭合的警告了,但是目前我不清楚原因在哪里,加反斜杠(\)的解决办法也是我瞎试出来的,而且我觉得解决办法并不完美。
更好的解决办法是将 Vue 组件单独定义到一个 JavaScript 文件中,然后用admin_js方法引入。
test-component.js:

function todoItemComponent(){
    window.vueApp.component('todo-item',{
        props: ['todo'],
        template: '<li> {{ todo.text }} </li>',
        data(){
            return {
                name: 'Song'
            }
        }
    })
}

custom-color.blade.php:

<div id="custom-color-page">
    <ol>
        <todo-item v-for="todoItem in groceryList" v-bind:key="todoItem.id" v-bind:todo="todoItem"></todo-item>
    </ol>
</div>
{!! admin_js(['/js/components/test-component.js']) !!}
<script init="#custom-color-page">
    const customColorPage = {
        data(){
            return {
                counter: 0,
                groceryList: [
                    {id: 1, text: 'apple'},
                    {id: 2, text: 'xiaomi'},
                    {id:3, text: 'Cheese'}
                ]
            }
        },
        methods: {
            addCounter(){
                this.counter++;
            }
        }
    }
    window.vueApp = Vue.createApp(customColorPage);
    todoItemComponent();
    window.vueApp.mount('#custom-color-page');
</script>
顺势而为
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

这个坑我终于踩到了 :sob:

11个月前 评论
myhui0926 (楼主) 11个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!