Skip to content

Commit

Permalink
fix s-is value update
Browse files Browse the repository at this point in the history
  • Loading branch information
varsha authored and wangshuonpu committed Dec 4, 2020
1 parent 5e732da commit b1e3985
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 15 deletions.
10 changes: 5 additions & 5 deletions src/view/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,11 @@ Component.prototype.fire = function (name, event) {
var me = this;
// #[begin] devtool
emitDevtool('comp-event', {
name: name,
event: event,
name: name,
event: event,
target: this
});
// #[end]
// #[end]

each(this.listeners[name], function (listener) {
listener.fn.call(me, event);
Expand Down Expand Up @@ -510,7 +510,7 @@ Component.prototype.dispatch = function (name, value) {
// #[begin] devtool
emitDevtool('comp-message', {
target: this,
value: value,
value: value,
name: name,
receiver: parentComponent
});
Expand All @@ -528,7 +528,7 @@ Component.prototype.dispatch = function (name, value) {

// #[begin] devtool
emitDevtool('comp-message', {target: this, value: value, name: name});
// #[end]
// #[end]
};

/**
Expand Down
117 changes: 117 additions & 0 deletions src/view/is-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* Copyright (c) Baidu Inc. All rights reserved.
*
* This source code is licensed under the MIT license.
* See LICENSE file in the project root for license information.
*
* @file is 指令节点类
*/

var guid = require('../util/guid');
var insertBefore = require('../browser/insert-before');
var evalExpr = require('../runtime/eval-expr');
var NodeType = require('./node-type');
var createNode = require('./create-node');
var createReverseNode = require('./create-reverse-node');
var nodeOwnCreateStump = require('./node-own-create-stump');
var nodeOwnSimpleDispose = require('./node-own-simple-dispose');

/**
* is 指令节点类
*
* @class
* @param {Object} aNode 抽象节点
* @param {Node} parent 父亲节点
* @param {Model} scope 所属数据环境
* @param {Component} owner 所属组件环境
* @param {DOMChildrenWalker?} reverseWalker 子元素遍历对象
*/
function IsNode(aNode, parent, scope, owner, reverseWalker) {
this.aNode = aNode;
this.owner = owner;
this.scope = scope;
this.parent = parent;
this.parentComponent = parent.nodeType === NodeType.CMPT
? parent
: parent.parentComponent;

this.id = guid++;

// #[begin] reverse
if (reverseWalker) {
var tagName = evalExpr(this.aNode.directives['is'].value, this.scope, this.owner);
if (tagName) { // eslint-disable-line dot-notation
this.child = createReverseNode(
this.aNode.isRinsed,
this,
this.scope,
this.owner,
reverseWalker
);
}

this._create();
insertBefore(this.el, reverseWalker.target, reverseWalker.current);
}
// #[end]
}

IsNode.prototype.nodeType = NodeType.IS;

IsNode.prototype._create = nodeOwnCreateStump;
IsNode.prototype.dispose = nodeOwnSimpleDispose;

/**
* attach到页面
*
* @param {HTMLElement} parentEl 要添加到的父元素
* @param {HTMLElement=} beforeEl 要添加到哪个元素之前
*/
IsNode.prototype.attach = function (parentEl, beforeEl) {
var tagName = evalExpr(this.aNode.directives['is'].value, this.scope, this.owner);// eslint-disable-line dot-notation

if (tagName) {
var child = createNode(this.aNode.isRinsed, this, this.scope, this.owner);

if (child) {
this.tagName = tagName;
this.child = child;
child.attach(parentEl, beforeEl);
}
}

this._create();
insertBefore(this.el, parentEl, beforeEl);
};

/**
* 视图更新函数
*
* @param {Array} changes 数据变化信息
*/
IsNode.prototype._update = function (changes) {
var me = this;
var childANode = this.aNode.isRinsed;
var child = this.child;
var tagName = evalExpr(this.aNode.directives['is'].value, this.scope); // eslint-disable-line dot-notation

if (tagName === this.tagName) {
child && child._update(changes);
}
else {
child._ondisposed = newChild;
child.dispose();
}

function newChild() {
me.child = createNode(childANode, me, me.scope, me.owner)
.attach(me.el.parentNode, me.el);
}
};

IsNode.prototype._getElAsRootNode = function () {
var child = this.child;
return child && child.el || this.el;
};

exports = module.exports = IsNode;
3 changes: 2 additions & 1 deletion src/view/node-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ var NodeType = {
CMPT: 5,
SLOT: 6,
TPL: 7,
LOADER: 8
LOADER: 8,
IS: 9
};

exports = module.exports = NodeType;
18 changes: 17 additions & 1 deletion src/view/preheat-a-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var TextNode = require('./text-node');
var SlotNode = require('./slot-node');
var ForNode = require('./for-node');
var IfNode = require('./if-node');
var IsNode = require('./is-node');
var TemplateNode = require('./template-node');
var Element = require('./element');

Expand Down Expand Up @@ -197,6 +198,21 @@ function preheatANode(aNode, componentInstance) {
aNode = aNode.forRinsed;
}

if (aNode.directives['is']) {
aNode.isRinsed = {
children: aNode.children,
props: aNode.props,
events: aNode.events,
tagName: aNode.tagName,
vars: aNode.vars,
hotspot: aNode.hotspot,
directives: extend({}, aNode.directives)
};
aNode.hotspot.hasRootNode = true;
aNode.Clazz = IsNode;
aNode = aNode.isRinsed;
}

switch (aNode.tagName) {
case 'slot':
aNode.Clazz = SlotNode;
Expand All @@ -210,7 +226,7 @@ function preheatANode(aNode, componentInstance) {

default:
if (hotTags[aNode.tagName]) {
if (!aNode.directives.is
if (!aNode.directives.is
&& (!componentInstance || !componentInstance.components[aNode.tagName])
) {
aNode.Clazz = Element;
Expand Down
142 changes: 134 additions & 8 deletions test/component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -711,15 +711,30 @@ describe("Component", function () {

it("components use s-is", function () {
var Label = san.defineComponent({
template: '<span title="{{text}}">{{text}}</span>'
template: `<span title="{{text}}">{{text}}</span>`,
initData() {
return {
text: 'erik'
}
}
});

var MyComponent = san.defineComponent({
components: {
'x-label': Label
'x-label': Label,
},
initData() {
return {
cmpt: 'x-label'
}
}
});

MyComponent.template = '<div><test text="erik" s-is="{{\'x-label\'}}"/></div>';
MyComponent.template = `
<div>
<test s-is="cmpt"/>
</div>`;

var myComponent = new MyComponent();

var wrap = document.createElement('div');
Expand All @@ -733,6 +748,65 @@ describe("Component", function () {
document.body.removeChild(wrap);
});

it("s-is value update", function (done) {
var Label = san.defineComponent({
template: `<span
title="{{text}}"
>{{text}}
</span>`,
initData() {
return {
text: 'erik'
}
}
});

var H2 = san.defineComponent({
template: `<h2>{{text}}.baidu</h2>`,
initData() {
return {
text: 'erik'
}
}
});

var MyComponent = san.defineComponent({
components: {
'x-label': Label,
'x-h2': H2
},
initData() {
return {
cmpt: 'x-label'
}
}
});

MyComponent.template = `
<div>
<test s-is="cmpt"/>
</div>`;

var myComponent = new MyComponent();

var wrap = document.createElement('div');
document.body.appendChild(wrap);
myComponent.attach(wrap);

var span = wrap.getElementsByTagName('span')[0];
expect(span.title).toBe('erik');

myComponent.data.set('cmpt', 'x-h2');
san.nextTick(function () {
var h2 = wrap.getElementsByTagName('h2')[0];
expect(h2.innerHTML.indexOf('erik.baidu')).toBe(0);

myComponent.dispose();
document.body.removeChild(wrap);
done();
});
});

it("components in inherits structure", function () {
var Span = san.defineComponent({});
Span.template = '<span title="span">span</span>';
Expand Down Expand Up @@ -4823,15 +4897,15 @@ describe("Component", function () {
expect(child.tagName).toBe('A');
expect(child.innerHTML).toContain('one');

child = child.nextSibling;
child = child.nextSibling.nextSibling;
expect(child.tagName).toBe('BUTTON');
expect(child.innerHTML).toContain('two');

child = child.nextSibling;
child = child.nextSibling.nextSibling;
expect(child.tagName).toBe('BUTTON');
expect(child.innerHTML).toContain('three');

child = child.nextSibling;
child = child.nextSibling.nextSibling;
expect(child.tagName).toBe('A');
expect(child.innerHTML).toContain('four');

Expand Down Expand Up @@ -5239,6 +5313,58 @@ describe("Component", function () {
});
});

it("s-is value update in component as component root by s-is", function (done) {
var ChildA = san.defineComponent({
template: '<h2>erik</h2>'
});
var ChildB = san.defineComponent({
template: '<h3>varsha</h3>'
});

var Parent = san.defineComponent({
template: '<test s-is="cmpt"></test>',
components: {
'x-child-a': ChildA,
'x-child-b': ChildB
}
});


var MyComponent = san.defineComponent({
template: `<div>
<x-parent cmpt="{{cmpt}}"/>
</div>`,
components: {
'x-parent': Parent
}
});

var myComponent = new MyComponent({
data: {
cmpt: 'x-child-a'
}
});

var wrap = document.createElement('div');
document.body.appendChild(wrap);
myComponent.attach(wrap);

var childElm = myComponent.el.firstElementChild;
expect(childElm.tagName).toBe('H2');
expect(childElm.innerHTML).toBe('erik');

myComponent.data.set('cmpt', 'x-child-b');
myComponent.nextTick(function () {
var childElm = myComponent.el.firstElementChild;
expect(childElm.tagName).toBe('H3');
expect(childElm.innerHTML).toBe('varsha');

myComponent.dispose();
document.body.removeChild(wrap);
done();
});
});

it("component as component root, use s-bind", function (done) {
var Child = san.defineComponent({
template: '<h3>see <a href="{{link}}">{{linkText || name}}</a> to start <b>{{name}}</b> framework</h3>'
Expand Down Expand Up @@ -5672,8 +5798,8 @@ describe("Component", function () {
});

var myComponent = new MyComponent({
data: {
name: 'erik',
data: {
name: 'erik',
company: 'baidu',
cmpt: 'x-label'
}
Expand Down

0 comments on commit b1e3985

Please sign in to comment.