【问题标题】:How do I set JavaScript's scope to partial view?如何将 JavaScript 的范围设置为部分视图?
【发布时间】:2020-08-30 06:42:09
【问题描述】:

我有一个 ASP.NET 部分视图

<div class="wrapper">
    <div class="remove-item"></div>        
    <input name="Account" class="currency" />
     ...some more html input elements removed for brevity
</div>

局部视图有自己的 JavaScript

<script type="text/javascript">
    $(function(){
       $(".remove-item").click(function(){
          var i =  $("input.currency");
          // do something
       })   


    })
</script> 

在一个页面上,这个局部视图会出现多次。每个input 元素都有唯一的名称。然而 JavaScript 使用类名选择元素。

问题是当局部视图的第二个实例呈现时,$(".remove-item") 也会从第一个局部视图中选择元素。因为它会扫描整个 DOM。

在这里设置 JavaScript 范围的最佳方法是什么,以便它只选择具有自己范围的元素?


只选择元素

【问题讨论】:

  • 仅供参考,将 JavaScript 放在每个局部视图中会减慢您的初始渲染速度。 HTML解析器必须切换到JS引擎,加载&解析&运行JS,然后每次遇到&lt;script&gt;标签时切换回HTML解析器。如果代码始终相同(即,您不会将服务器端代码写入每个脚本),只需将其放入外部文件并加载一次即可。

标签: javascript jquery asp.net-mvc asp.net-core partial-views


【解决方案1】:

当处理未知数量的重复元素时,您可以使用事件委托。与其多次输出 JS 并在每个部分上都有一个事件侦听器,不如输出一次,并且整个部分集只有一个事件。无论页面上最终有多少元素,即使动态显示更多元素,您的事件仍然会触发:

  1. 仅输出此 JavaScript 一次:
<script type="text/javascript">
    $(".containing-parent").on('click', '.remove-item', function() {
        var i = $(this).closest('.wrapper').find('input.currency');
    });
</script>
  1. 使用可以附加一个事件的 div 包装您的部分:
<div class="containing-parent">
    ...partials go here
</div>

您需要确保您的 javascript 在执行时可以找到 div.containing-parent

示例:

$(".containing-parent").on('click', '.remove-item', function() {
  var i = $(this).closest('.wrapper').find('input.currency').val();
  console.log(i);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="containing-parent">
  <div class="wrapper">
    <div class="remove-item">X</div>
    <input name="Account1" class="currency" value="1" />
  </div>
  <div class="wrapper">
    <div class="remove-item">X</div>
    <input name="Account2" class="currency" value="2" />
  </div>
  <div class="wrapper">
    <div class="remove-item">X</div>
    <input name="Account3" class="currency" value="3" />
  </div>
</div>

【讨论】:

  • 很好,我不使用 jquery,但它看起来很干净。
【解决方案2】:

最好的方法是创建一个模块。

// Module

function PartialView(root) {
  var button = root.querySelector('button');
  
  button.addEventListener('click', remove);
  
  
  function remove() {
    button.removeEventListener('click', remove);
    root.remove();
  }
  
}

// Attaching listeners

Array.from(document.querySelectorAll('.partial-view'))
  .forEach(PartialView);
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div class="partial-view">
    <button>remove</button>
    <input type="text" />
  </div>
  <div class="partial-view">
    <button>remove</button>
    <input type="text" />
  </div>
  <div class="partial-view">
    <button>remove</button>
    <input type="text" />
  </div>
  <div class="partial-view">
    <button>remove</button>
    <input type="text" />
  </div>
  <div class="partial-view">
    <button>remove</button>
    <input type="text" />
  </div>
</body>
</html>

【讨论】:

  • 那不是模块;那是一个闭包,或者一个对象。 Modules 是 JavaScript 中的特定事物。
  • root 是如何传递的,root 参数的值是多少?
  • @HereticMonkey 我明白你的意思了,我实现的是一种设计模式,称为显示模块模式
  • @LP13 forEach 使用 PartialView 作为回调,它负责注入它。
  • 实际上,RMP 会返回在外部函数中构建的对象,但可以肯定。
【解决方案3】:

你可以给包含局部视图的 div 一个唯一 ID

<div class="wrapper" id="partialViewHandler">

然后在您的 Javascript 上首先找到 ContainerDiv 并将值存储在一个参数中并在您的 JQuery 选择器中使用它。

<script type="text/javascript">
    var x = $("#partialViewHandler");
    $(function () {
        $(".remove-item", x).click(function () {
            var i = $("input.currency", x);
            // do something
        })
    })
</script>

【讨论】:

    猜你喜欢
    • 2021-08-30
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多