element-plus: [bug report] loading component. In the development environment, the command usage posture is abnormal

Element Plus version

1.0.2-beta.32

OS/Browsers version

Microsoft Edge 版本 88.0.705.56 (官方内部版本) (64 位)

Vue version

3.0.5

Reproduction Link

https://jsfiddle.net/n4az9x2s/2/

Steps to reproduce

  1. 这个 https://jsfiddle.net/n4az9x2s/2/ 网址代码运行结果正常

2.问题出现在开发环境(我本地fork了一份element-plus)

3.在fork的项目element-plus/website/play/index.vue写上 https://jsfiddle.net/n4az9x2s/2/ 这个网址的demo代码

4.运行 npm run website-dev:play

5.就会发现改变loading的值,无任何效果

What is Expected?

1.希望为true的时候出现loading ui,为false的时候 ui消失

What is actually happening?

1.实际上没有任何反应,也没有执行element-plus/packages/loading/src/directive.ts中的钩子函数(一开始我以为是element的bug,后来确信是Vue的bug,但是我作为使用者,确实是使用了v-loading的造成的,所以就提了这个bug)

2.下面我说下这个bug造成的原因(希望能看下,或许我说的不对)

a.造成bug的根本原因,我觉得是模板编译或者vue-loader出了问题, 相同的模板只是使用了不同方式(ref,reactive)创建的响应式数据,最后模板编译的结果却不同。

b.withDirectives(vNode, [ [dir, value, argument, modifiers] ])函数接受2个参数,这里我们关心下第二个参数数组里面的成员,成员数组的第一个dir值我觉得必须为一个对象(虽然可以是函数,但是内部实现中,还是会转成对象){ beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted },值为钩子函数。对于我提的这个bug的代码,模板解析完,dir的值却是一个boolean值(内部没有特殊处理),所以当调用钩子时, 解析不到对应的钩子,所以就没执行element-plus/packages/loading/src/directive.ts中的钩子函数。

c.看下模板编译的结果 使用 Vue.compile 编译后的render函数,这是正常的,所以生产环境没毛病。_directive_loading拿到了element-plus/packages/loading/src/directive.ts中的钩子函数

function render(_ctx, _cache) {

    with(_ctx) {
        const {
            toDisplayString: _toDisplayString,
            resolveDirective: _resolveDirective,
            createVNode: _createVNode,
            withDirectives: _withDirectives,
            openBlock: _openBlock,
            createBlock: _createBlock
        } = _Vue

        const _directive_loading = _resolveDirective("loading")

        return (_openBlock(), _createBlock("div", _hoisted_1, [
            _withDirectives(_createVNode("div", {
                class: "element-plus-loading__box1"
            }, " 注意看我: " + _toDisplayString(loading), 513 /* TEXT, NEED_PATCH */ ), [
                [_directive_loading, loading]
            ])
        ]))
    }

}

使用ref 创建响应式数据时, 模板编译有问题, withDirectives(vNode, [[dir, value, argument, modifiers]])方法,dir是个对象,里面是不同的钩子,下面编译后的代码dir却是boolean值, $setup[“loading”]这句话应该是问题所在,应该是element-plus/packages/loading/src/directive.ts中的钩子函数,现在却是布尔值。

function render(_ctx, _cache, $props, $setup, $data, $options) {

    return Object(vue__WEBPACK_IMPORTED_MODULE_0__["openBlock"])(), Object(vue__WEBPACK_IMPORTED_MODULE_0__["createBlock"])("div", _hoisted_1, [Object(vue__WEBPACK_IMPORTED_MODULE_0__["withDirectives"])(Object(vue__WEBPACK_IMPORTED_MODULE_0__["createVNode"])("div", {
            class: "element-plus-loading__box1"
        }, " 注意看我: " + Object(vue__WEBPACK_IMPORTED_MODULE_0__["toDisplayString"])($setup.loading), 513
        /* TEXT, NEED_PATCH */
    ), [
        [$setup["loading"], $setup.loading]
    ])]);

}

使用reactive 创建的响应式数据, 和预期一样, 这个和Vue.compile 编译后的差不多,所以正常

function render(_ctx, _cache, $props, $setup, $data, $options) {

    var _directive_loading = Object(vue__WEBPACK_IMPORTED_MODULE_0__["resolveDirective"])("loading");

    return Object(vue__WEBPACK_IMPORTED_MODULE_0__["openBlock"])(), Object(vue__WEBPACK_IMPORTED_MODULE_0__["createBlock"])("div", _hoisted_1, [Object(vue__WEBPACK_IMPORTED_MODULE_0__["withDirectives"])(Object(vue__WEBPACK_IMPORTED_MODULE_0__["createVNode"])("div", {
            class: "element-plus-loading__box1"
        }, " 注意看我: " + Object(vue__WEBPACK_IMPORTED_MODULE_0__["toDisplayString"])(_ctx.loading), 513
        /* TEXT, NEED_PATCH */
    ), [
        [_directive_loading, _ctx.loading]
    ])]);

}

3.希望我的解释是对的,感谢阅读

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 35 (23 by maintainers)

Most upvoted comments

我明白了,还真是同名的问题。

这样是可以的

<script setup></script>

<template>
  <el-table v-loading="true"></el-table>
</template>

出现任何的loading 变量就不行,不管这个loading是什么类型的数据(ref,还是普通值)

<script setup>
const loading = "any string"
</script>

<template>
  <!-- 上下文有 loading 变量,则不生效 -->
  <el-table v-loading="true"></el-table>
</template>

只要不出现loading变量就行了

<script setup>
const loading123 = "any string"
</script>

<template>
  <!-- ok 没毛病 -->
  <el-table v-loading="true"></el-table>
</template>