为啥 D3 对输入的关注只在第一次起作用?

Posted

技术标签:

【中文标题】为啥 D3 对输入的关注只在第一次起作用?【英文标题】:Why does D3's focus on an input work only the first time?为什么 D3 对输入的关注只在第一次起作用? 【发布时间】:2017-11-07 22:43:56 【问题描述】:

使用 D3 可以focus on an input field,甚至不需要to go through setTimeout(我不知道为什么,但我没有抱怨)。

但这只适用于第一次。第二次按下Set(即:SetResetSet)后,输入字段没有获得焦点。为什么?

将回调设置为焦点 after the transition is complete 给我一个错误。

<!DOCTYPE html>
<head>
    <style>
        div  width: 300px; 
        div#outerdiv   height: 500px; background-color: #ccc; 
        div#topdiv     height: 400px; background-color: #dff; 
        div#bottomdiv  height: 0px;   background-color: #ffd; display: 'none' 
        input:focus  background-color: pink; 
    </style>
</head>
<body>
    <div id="outerdiv">
        <div id="topdiv">
            <button onclick=open_form();>Set</button>
            <button onclick=close_form();>Reset</button>
        </div>

        <div id="bottomdiv">
            <form action="javascript:close_form()">
                Name:
                <input type="text" id="myTextField" name="name">
                <input type="submit" name="submit" value="Submit">
            </form>
        </div>
    </div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

    <script>
        function open_form() 
            d3.select('#topdiv').transition().duration(500)
              .style('height', '100px');
            d3.select('#bottomdiv').transition().duration(500)
              .style('height', '300px').style('display', 'inline-block');

            d3.select("#myTextField").node().focus();
         
        function close_form() 
            d3.select('#topdiv').transition().duration(500)
              .style('height', '390px');
            d3.select('#bottomdiv').transition().duration(500)
              .style('height', '10px').style('display', 'none');
        
    </script>
</body>

【问题讨论】:

【参考方案1】:

每次你点击重置按钮,即当close_form()被调用时,你的#bottomdiv被转换为display: none

d3.select('#bottomdiv').transition().duration(500)
    .style('height', '10px').style('display', 'none');

不过,这有一些副作用。查看focus management 上的 HTML5 规范显示,未呈现的元素也不可聚焦:

7.4.2 焦点管理

如果满足以下所有条件,则元素是可聚焦的:

[…] 元素是being rendered 或[…]

因此,下次您点击 Set 时,调用 open_form() 时输入不可聚焦,因为到 inline-block 的转换尚未结束。解决此问题的最简单方法是 listen 用于转换的 end 事件,该事件在转换结束时触发。

   d3.select('#bottomdiv').transition().duration(500)
       .style('height', '300px').style('display', 'inline-block')
       .on("end", () => d3.select("#myTextField").node().focus());

查看下面的 sn-p 以获取工作演示:

function open_form() 
    d3.select('#topdiv').transition().duration(500)
      .style('height', '100px');
    d3.select('#bottomdiv').transition().duration(500)
      .style('height', '300px').style('display', 'inline-block')
      .on("end", () => d3.select("#myTextField").node().focus());

 
function close_form() 
    d3.select('#topdiv').transition().duration(500)
      .style('height', '390px');
    d3.select('#bottomdiv').transition().duration(500)
      .style('height', '10px').style('display', 'none');
div  width: 300px; 
div#outerdiv   height: 500px; background-color: #ccc; 
div#topdiv     height: 400px; background-color: #dff; 
div#bottomdiv  height: 0px;   background-color: #ffd; display: 'none' 
input:focus  background-color: pink; 
<body>
    <div id="outerdiv">
        <div id="topdiv">
            <button onclick=open_form();>Set</button>
            <button onclick=close_form();>Reset</button>
        </div>

        <div id="bottomdiv">
            <form action="javascript:close_form()">
                Name:
                <input type="text" id="myTextField" name="name">
                <input type="submit" name="submit" value="Submit">
            </form>
        </div>
    </div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

</body>

【讨论】:

家庭作业:找出此处列出的 .on('end', ..) 和 .each('end', ..) 之间的区别:***.com/questions/10692100/… @Sebastian 好吧,transition.each("end") 是在 v3 中注册处理函数的方式。从 v4 开始,它被重命名为 transition.on("end")【参考方案2】:

它无法找到#myTextField,因为它处于过渡中期。您可以通过移除 display: inline-block 的转换来解决此问题,如下所示。

function open_form() 
    d3.select('#topdiv').transition().duration(500)
      .style('height', '100px');
    d3.select('#bottomdiv').style('display', 'inline-block');
    d3.select('#bottomdiv').transition().duration(500)
      .style('height', '300px');
    d3.select("#myTextField").node().focus();
 

【讨论】:

以上是关于为啥 D3 对输入的关注只在第一次起作用?的主要内容,如果未能解决你的问题,请参考以下文章

$location 在使用 d3.js 的 AngularJS 中不起作用

ckeditor插入或更新在第一次尝试时不起作用

为啥 Spinner 中的第一项不起作用

Python 函数退出不起作用 - 为啥? [复制]

为啥 fstream 在这里不起作用(在文件中读/写)?

为啥我在 ggtext 的轴标签中使用 png 徽标的代码不起作用