feat(vue): support to merge styles on root element of child component

This commit is contained in:
zoomchan-cxj
2022-11-07 10:56:31 +08:00
parent 020fd1e9ce
commit efea081cf9
13 changed files with 63 additions and 35 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ At present, the basic `Universal`, `Type`, `ID`, `Class`, `Grouping` selectors h
## Scoped & Attribute
> `2.15.0` support Vue `scoped` style.
> `2.15.0` support Vue `scoped` style, `2.15.2` support to merge styles on root element of child component.
> `2.15.1` support `Attribute` selector and Vue `deep` selector.
+1 -1
View File
@@ -25,7 +25,7 @@ HippyVue 提供了 `beforeLoadStyle` 的 Vue options 勾子函数,供开发者
## Scoped & Attribute
> `2.15.0` 版本增加支持 Vue `scoped` 样式能力
> `2.15.0` 版本增加支持 Vue `scoped` 样式能力, `2.15.2` 支持子组件根元素样式合并
> `2.15.1` 版本增加支持 `Attribute` 选择器和 Vue `deep` 深度选择器
@@ -10,7 +10,7 @@
v-if="loaded"
class="async-com-wrapper"
>
<AsyncComponentFromLocal />
<AsyncComponentFromLocal class="async-component-outer-local" />
<AsyncComponentFromHttp />
</div>
</div>
@@ -55,7 +55,11 @@ export default {
};
</script>
<style>
<style scoped>
.async-component-outer-local {
height: 200px;
width: 300px;
}
#demo-dynamicimport {
flex: 1;
display: flex;
@@ -1,5 +1,5 @@
<template>
<div id="asynccomponent">
<div class="async-component-local">
<text class="async-txt">
我是本地异步组件
</text>
@@ -15,18 +15,16 @@ export default {
};
</script>
<style>
#asynccomponent {
<style scoped>
.async-component-local {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
height: 200px;
width: 300px;
background-color: #50ca92;
border-radius: 10px;
margin-bottom: 10px;
background-color: #50ca92;
}
.async-txt{
color: black;
@@ -10,7 +10,7 @@
v-if="loaded"
class="async-com-wrapper"
>
<AsyncComponentFromLocal />
<AsyncComponentFromLocal class="async-component-outer-local"/>
<AsyncComponentFromHttp />
</div>
</div>
@@ -67,7 +67,11 @@ export default defineComponent({
});
</script>
<style>
<style scoped>
.async-component-outer-local {
height: 200px;
width: 300px;
}
#demo-dynamicimport {
flex: 1;
display: flex;
@@ -92,6 +96,6 @@ export default defineComponent({
line-height: 40px;
}
.async-com-wrapper {
marginTop: 20px
margin-top: 20px
}
</style>
@@ -1,7 +1,6 @@
<template>
<div
id="async-component-local"
class="local-local"
class="async-component-local"
>
<p class="async-txt">
我是本地异步组件
@@ -17,15 +16,13 @@ export default defineComponent({
});
</script>
<style>
#async-component-local {
<style scoped>
.async-component-local {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
height: 200px;
width: 300px;
background-color: #50ca92;
border-radius: 10px;
margin-bottom: 10px;
@@ -240,10 +240,10 @@ describe('node-ops.ts', () => {
it('setScopeId method should work correct', () => {
const element = nodeOps.createElement('div');
element.setStyleScope('style-scoped-id-1');
expect(element.styleScopeId).toEqual('style-scoped-id-1');
expect(element.styleScopeId).toEqual(['style-scoped-id-1']);
element.setStyleScope({});
expect(element.styleScopeId).toEqual('[object Object]');
expect(element.styleScopeId).toEqual(['style-scoped-id-1', '[object Object]']);
element.setStyleScope(123456);
expect(element.styleScopeId).toEqual('123456');
expect(element.styleScopeId).toEqual(['style-scoped-id-1', '[object Object]', '123456']);
});
});
@@ -579,10 +579,10 @@ describe('runtime/element/hippy-element', () => {
it('setStyleScopedId method should work correct', () => {
const element = new HippyElement('div');
element.setStyleScope('style-scoped-id');
expect(element.styleScopeId).toEqual('style-scoped-id');
expect(element.styleScopeId).toEqual(['style-scoped-id']);
element.setStyleScope({});
expect(element.styleScopeId).toEqual('[object Object]');
expect(element.styleScopeId).toEqual(['style-scoped-id', '[object Object]']);
element.setStyleScope(12345);
expect(element.styleScopeId).toEqual('12345');
expect(element.styleScopeId).toEqual(['style-scoped-id', '[object Object]', '12345']);
});
});
@@ -205,7 +205,7 @@ export class HippyElement extends HippyNode {
protected polyFillNativeEvents?: (type: string) => string;
// style scoped id for element
private scopedId?: string | undefined = undefined;
private scopedIdList: NeedToTyped[] = [];
constructor(tagName: string) {
super(NodeType.ElementNode);
@@ -789,14 +789,17 @@ export class HippyElement extends HippyNode {
* @param scopeStyleId - scoped style id
*/
public setStyleScope(scopeStyleId: NeedToTyped): void {
this.scopedId = typeof scopeStyleId !== 'string' ? scopeStyleId.toString() : scopeStyleId;
const scopedId = typeof scopeStyleId !== 'string' ? scopeStyleId.toString() : scopeStyleId;
if (scopedId && !this.scopedIdList.includes(scopedId)) {
this.scopedIdList.push(scopedId);
}
}
/**
* get style scoped id
*/
public get styleScopeId() {
return this.scopedId;
return this.scopedIdList;
}
/**
@@ -360,7 +360,7 @@ const getNodeAttrVal = (node, attribute) => {
if (typeof attr !== 'undefined') {
return attr;
}
if (!isNullOrUndefined(node.styleScopeId) && node.styleScopeId === attribute) {
if (Array.isArray(node.styleScopeId) && node.styleScopeId.includes(attribute)) {
return attribute;
}
};
@@ -199,8 +199,8 @@ class ElementNode extends ViewNode {
this.id = '';
// style attribute in template.
this.style = {};
// Vue style scope id.
this._styleScopeId = undefined;
// Vue style scope id list.
this.scopeIdList = [];
// Class attribute in template.
this.classList = new Set(); // Fake DOMTokenLis
// Other attributes in template.
@@ -441,11 +441,13 @@ class ElementNode extends ViewNode {
if (typeof styleScopeId !== 'string') {
styleScopeId = styleScopeId.toString();
}
this._styleScopeId = styleScopeId;
if (styleScopeId && !this.scopeIdList.includes(styleScopeId)) {
this.scopeIdList.push(styleScopeId);
}
}
get styleScopeId() {
return this._styleScopeId;
return this.scopeIdList;
}
appendChild(childNode) {
@@ -252,7 +252,7 @@ const getNodeAttrVal = (node, attribute) => {
if (typeof attr !== 'undefined') {
return attr;
}
if (!isNullOrUndefined(node.styleScopeId) && node.styleScopeId === attribute) {
if (Array.isArray(node.styleScopeId) && node.styleScopeId.includes(attribute)) {
return attribute;
}
};
@@ -1,3 +1,23 @@
/*
* Tencent is pleased to support the open source community by making
* Hippy available.
*
* Copyright (C) 2017-2022 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable no-underscore-dangle */
import test, { before } from 'ava';
@@ -266,5 +286,5 @@ test('setStyleScope test', (t) => {
const node = createElement('div');
const styleScopeId = 123;
t.is(nodeOps.setStyleScope(node, styleScopeId), undefined);
t.is(node._styleScopeId, styleScopeId.toString());
t.is(node.scopeIdList[0], styleScopeId.toString());
});