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
- 这个 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.希望我的解释是对的,感谢阅读
🔨 Vue issue