Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Web组件中展平/消除属性更改回调_Javascript_Html_Web Component_Native Web Component - Fatal编程技术网

Javascript 如何在Web组件中展平/消除属性更改回调

Javascript 如何在Web组件中展平/消除属性更改回调,javascript,html,web-component,native-web-component,Javascript,Html,Web Component,Native Web Component,我有一个web组件正在使用attributeChangedCallback attributeChangedCallback(name, oldValue, newValue) { // TODO: use something like rxjs debounce time? this.expensiveRenderer() } 我正在为每个动画帧上的两个属性设置新值: 此外,这可以增加到设置4个属性 component.setAttribute("att1", r); com

我有一个web组件正在使用
attributeChangedCallback

attributeChangedCallback(name, oldValue, newValue) {
    // TODO: use something like rxjs debounce time?
    this.expensiveRenderer()
}
我正在为每个动画帧上的两个属性设置新值: 此外,这可以增加到设置4个属性

component.setAttribute("att1", r);
component.setAttribute("att2", p);
function animateSpirograph(spirograph, r, p, rIncrement, pIncrement) {
  let v = r;
  if (v + rIncrement > 100) rIncrement = -Math.abs(rIncrement);
  if (v + rIncrement <= 0) rIncrement = Math.abs(rIncrement);
  v = v + rIncrement;
  r = v;
  let w = p;
  if (w + pIncrement > 200) pIncrement = -Math.abs(pIncrement);
  if (w + pIncrement <= 0) pIncrement = Math.abs(pIncrement);
  w = w + pIncrement;
  p = w;
  spirograph.setAttribute("moving-circle-radius", r);
  spirograph.setAttribute("moving-circle-locus-length", p);
  window.requestAnimationFrame(() =>
    animateSpirograph(spirograph, r, p, rIncrement, pIncrement)
  );
}
这将触发两次
attributeChangedCallback
,并且昂贵的渲染器也会触发两次

有没有一种有效的方法将两个属性设置在一起,或者将更改的效果作为一个类似于去盎司时间的单一事件

我对使用
setTimeout
/
clearTimeout
有点怀疑,因为它在每个动画帧上调用60 fps

为了提供更好的概述,我的组件看起来有点像:

<mm-spirograph
    fixed-circle-radius="100"
    moving-circle-radius="10"
    moving-circle-locus-length="30"
    repeat-count="100"
  ></mm-spirograph>

它用webGL呈现螺旋图,并计划用于生成艺术。 我喜欢这种简单性,并且有点不愿意使用JSON属性

此外,设置spirograph的动画与组件是分开的,其想法是将spirograph用作静态渲染,或者更改属性可以轻松完成类似动画的操作。在这里,它仅为两个属性设置动画,但在不同情况下可能会有所不同

此外,还计划添加类似的组件,如果需要,可以通过设置属性来设置动画

component.setAttribute("att1", r);
component.setAttribute("att2", p);
function animateSpirograph(spirograph, r, p, rIncrement, pIncrement) {
  let v = r;
  if (v + rIncrement > 100) rIncrement = -Math.abs(rIncrement);
  if (v + rIncrement <= 0) rIncrement = Math.abs(rIncrement);
  v = v + rIncrement;
  r = v;
  let w = p;
  if (w + pIncrement > 200) pIncrement = -Math.abs(pIncrement);
  if (w + pIncrement <= 0) pIncrement = Math.abs(pIncrement);
  w = w + pIncrement;
  p = w;
  spirograph.setAttribute("moving-circle-radius", r);
  spirograph.setAttribute("moving-circle-locus-length", p);
  window.requestAnimationFrame(() =>
    animateSpirograph(spirograph, r, p, rIncrement, pIncrement)
  );
}
函数动画透视图(透视图、r、p、r增量、pIncrement){
设v=r;
如果(v+rIncrement>100)rIncrement=-Math.abs(rIncrement);
如果(v+rIncrement 200)pIncrement=-Math.abs(pIncrement);
if(w+pIncrement)
动画描记器(描记器、r、p、rIncrement、pIncrement)
);
}

Danny的建议很有趣,我可以有第三个属性,它可能是requestAnimationFrame的时间戳,并将其标记为仅用于动画的可选属性。因此,每次更改属性时,我们都需要设置此额外属性以实际触发渲染。但这听起来有点像黑客/补丁。

使用超时。这允许在执行昂贵的渲染之前执行整个代码

类MyEl扩展HtmleElement{
构造函数(){
超级();
this.renderTimeout=null;
this.renderCalled=0;
this.renderDone=0;
}
静态get ObservedAttribute(){
返回['time','direction'];
}
费用支付人(){
这个.renderCalled++;
if(this.renderTimeout){
clearTimeout(this.renderTimeout);
}
this.renderTimeout=setTimeout(
() => {
这个.renderDone++;
this.innerHTML=`时间是:${this.\u time}

方向是${this.\u direction}

渲染调用:${this.renderCalled}

渲染:${this.renderDone}

`; }, 1 ); } attributeChangedCallback(名称、旧值、新值){ 如果(旧值!==新值){ 这个[`{name}`]=newValue; 这是一个昂贵的价格; } } } 自定义元素。定义('my-el',MyEl); const component=document.querySelector('my-el'); 设置超时(()=>{ setAttribute(“时间”,“1:00”); setAttribute(“时间”,“2:00”); setAttribute(“时间”,“3:00”); setAttribute(“时间”,“4:00”); setAttribute(“方向”、“东”); setAttribute(“方向”、“西”); setAttribute(“方向”、“南”); }, 2000);
使用超时。这允许在执行昂贵的渲染之前执行整个代码

类MyEl扩展HtmleElement{
构造函数(){
超级();
this.renderTimeout=null;
this.renderCalled=0;
this.renderDone=0;
}
静态get ObservedAttribute(){
返回['time','direction'];
}
费用支付人(){
这个.renderCalled++;
if(this.renderTimeout){
clearTimeout(this.renderTimeout);
}
this.renderTimeout=setTimeout(
() => {
这个.renderDone++;
this.innerHTML=`时间是:${this.\u time}

方向是${this.\u direction}

渲染调用:${this.renderCalled}

渲染:${this.renderDone}

`; }, 1 ); } attributeChangedCallback(名称、旧值、新值){ 如果(旧值!==新值){ 这个[`{name}`]=newValue; 这是一个昂贵的价格; } } } 自定义元素。定义('my-el',MyEl); const component=document.querySelector('my-el'); 设置超时(()=>{ setAttribute(“时间”,“1:00”); setAttribute(“时间”,“2:00”); setAttribute(“时间”,“3:00”); setAttribute(“时间”,“4:00”); setAttribute(“方向”、“东”); setAttribute(“方向”、“西”); setAttribute(“方向”、“南”); }, 2000);
是否需要观察
观察到的属性中的所有属性
?它们是什么类型的属性?它们是本机HTML元素属性吗?否则,您可以简单地在一个数据属性中使用带有多个键值对的JSON字符串。或者添加第三个观察到的属性来设置其他两个,或者仅在第二个属性发生更改时触发渲染器。您需要观察
观察到的属性中的所有属性吗?它们是什么类型的属性?它们是本机HTML元素属性吗?否则,您可以简单地使用一个JSON字符串,在一个数据属性中包含多个键值对。或者添加第三个观察到的属性,设置其他两个键值对,或者仅在第二个属性发生更改时触发渲染器。这样做的效果也比我预期的好,性能非常出色。很高兴我能提供帮助!哇,这比我预期的要好得多,性能非常出色。很高兴我能帮上忙!