From 5fee8623d41ece84c29cc0be505f1e6288387f97 Mon Sep 17 00:00:00 2001 From: DCloud_Heavensoft Date: Thu, 12 Dec 2024 22:46:51 +0800 Subject: [PATCH] Update README.md --- docs/mp/README.md | 48 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/docs/mp/README.md b/docs/mp/README.md index ab58fb69..678586fa 100644 --- a/docs/mp/README.md +++ b/docs/mp/README.md @@ -10,25 +10,49 @@ uni-app x 项目在编译到小程序平台时,将部分特性对齐了web与a ## vue -### 组件启用virtualHost +### 自定义组件启用virtualHost带来的影响@virtualHost -uni-app x 项目在编译到小程序端时,为了避免自定义组件多一层dom嵌套影响flex等样式而默认启用了virtualHost,同时默认启用了[mergeVirtualHostAttributes特性](https://uniapp.dcloud.net.cn/collocation/manifest.html#mp-weixin)。 +标准的小程序下的自定义组件会多套一层DOM,这会影响flex等样式。而uni-app x默认都是flex的。 -启用virtualHost会让组件在实际渲染时不会额外包裹一层dom节点。这会对组件外使用选择器选择组件产生影响。 +所以为了拉齐样式表现,uni-app x 项目在编译到小程序时,默认启用了virtualHost,该配置是小程序平台提供的一种策略,可以取消多套的一层。\n +同时默认启用了[mergeVirtualHostAttributes特性](https://uniapp.dcloud.net.cn/collocation/manifest.html#mp-weixin),在取消多套的一层后,将原本父层的属性设置,合并到子层。 -* 无法在组件外层通过 getElementById 获取到自定义组件 UniElement 对象。 -* 无法在组件外层通过 SelectorQuery 获取到自定义组件的信息。但可以通过将自定义组件的实例传入 in 参数来获取。 +`去掉一层`以及`合并父属性到子`,这2件事会对真实渲染的DOM产生影响。*尤其会影响在组件外获取组件的DOM*。 -```js -uni.createSelectorQuery().in(this.$refs.xx).select('.xx').boundingClientRect((data) => { - console.log('boundingClientRect:', data) -}).exec() +我们先看一个例子: + +有个组件c1,父级外层代码如下 +```html + +``` + +c1组件的代码如下: +```html + ``` -mergeVirtualHostAttributes合并策略 -* 会将组件外层设置的 style、class 以及 v-show 指令生成的 hidden 属性合并到组件根节点上。比如外层设置了一个 id,是不会自动合并到组件根节点上的,此时通过uni.createSelectorQuery()是无法使用id选择器获取到根节点的。但因为class会合并,所以通过class选择器可以获取到根节点。 -* 仅对组件是单个根节点才会合并,组件内多个根节点的时候不会合并。 +然后看下mergeVirtualHostAttributes属性合并策略: +1. 仅将组件外层设置的 style、class 以及 v-show 指令生成的 hidden 属性,这3个属性合并到组件根节点上,其他外层设置的属性都丢弃了。 +2. 仅对组件是单个根节点才会合并,组件内多个根节点的时候不会合并。父层全部丢弃。 + +根据策略看,上述代码在运行时合并后,父层的id丢掉了,class属性合并,所以`class1parent` 和 `classchild` 同时生效。 + +那么父层通过`uni.getElementById("c1parent")`是拿不到UniElement的。 + +同样父层通过`uni.createSelectorQuery().in(this.$page).select('#c1parent')`也拿不到NodesRef。 + +但createSelectorQuery是支持设定查找范围的,上面的代码是在页面里查找,如果在父层代码里通过in方法指定查找组件,例如:`uni.createSelectorQuery().in(this.$refs['c1ref'] as ComponentPublicInstance).select('.class1parent') `,可以拿到c1组件的NodesRef + +实际上,不管是通过`.class1parent` 还是 `.classchild`,都可以拿到。因为样式合并后,这2个class在运行时同时存在。 + +假使在c1组件内部的根节点上设置了id属性`c1child`,通过`uni.createSelectorQuery().in(this.$refs['c1ref'] as ComponentPublicInstance).select('#c1child')`也可以获取。只是很少有组件会这么做。 + +获取组件的NodesRef,主要的用途是获取boundingClientRect,受小程序限制,这个使用场景目前有点复杂。DCloud会继续寻找优化方案。 +vue组件的方法调用不受影响。 ### refs@refs -- GitLab