我可以在主视图中使用 Javascript(使用 @ 语法)吗?

Can I use Javascript (with @ syntax) from partial into the main view?

抱歉,如果我使用了错误的术语,我对这项技术还很陌生。

我有一个视图,我们称之为 MainView.cshtml:

<div>
  @RenderPartial("_Partial");
</div>

<script type="text/javascript">
 $(document).ready(function() {
    someFunctionDefinedIn_Partial();
 }
</script>

_Partial 视图有 javascript 定义了一个函数(在本例中 someFunctionDefinedIn_Partial

function someFunctionDefinedIn_Partial()
{
  // This uses the "@" syntax to access C# variables, which can be done in .cshtml
  alert("Hello. This variable is from C#: @ClassInCSharp.Variable");
}

当我 运行 上面的代码时,我在 chrome 控制台中被告知函数 someFunctionDefinedIn_Partial 不存在。我猜这是因为部分 javascript 没有进入容器。

我环顾四周,发现我可以将 javascript 提取到它自己的 .js 文件中并引用它,如此 post 所示:How to render JavaScript into MasterLayout section from partial view?

但是,上面的 post 建议将 javascript 提取到它自己的单独文件 .js 中。如果我这样做,那么我正在使用 "raw" javascript,因此我不能使用 @ 表示法从我的 C# 中引用变量。

是否有可能以某种方式将 javascript 包含在我的 MainView.cshtml 中,它也可以访问 @ 语法以便我可以使用 C# methods/variables?如果没有,是否可以创建一个外部 javascript 文件,但将其设为 .cshtml 文件以便我可以使用“@”语法?

我不建议您在分部视图中包含 JS,因为它可以在给定视图中多次添加。看一眼 link

我建议你将部分 JS 移动到主视图。

更新

如果您别无选择,请考虑 Razor 不能在纯 JS 中使用:Link

您可以做的是提取您的 JS 中需要的 C# 值,并在调用 JS 时发送它们。所以你可以:

function someFunctionDefinedIn_Partial(variableValue)
{
  // This uses the "@" syntax to access C# variables, which can be done in .cshtml
  alert("Hello. This variable is from C#: " + variableValue);
}

并从局部视图中调用它:

someFunctionDefinedIn_Partial(@ClassInCSharp.Variable);

Can I use Javascript (with @ syntax) from partial into the main view?

是的,但是javascript操作的顺序很重要。严格来说,下面的 javascript 代码应该会出错:

console.log(myvariable);
var myvariable = "hello world!";

我在定义变量之前使用它。这就是你遇到的类似问题。

我会推荐直接在视图中使用 Javascript 吗?

绝对几乎完全从不。今天大多数 javascript/css/html 的写法已经足够紧耦合了。向 C# 添加耦合似乎是一个巨大的 code smell。我个人的偏好是将数据添加到 html 元素,并让 javascript 仅耦合到我的 html。所以不是:

<script>
var myIds = [@(string.Join(Model.People.Select(p => Id.ToString().ToArray(), ",")];
</script>

这非常丑陋且难以调试,我将我的值应用于代表我的对象的 html 演示文稿:

<div data-id="@model.Id" class="person">
  Person Name: @Html.DisplayFor(m => m.name)
</div>

<script>
var myIds = [];
$('.person').each((i,p) => myIds.push($(p).data("Id"));
</script>

现在我真的不会犯错,确保数组中的 ID 与页面上的相同,所有内容都封装在一起。

另一个代码异味是在逻辑视图中使用 @() 方法。比如我看到很多:

@foreach(var person in Model.persons) 
{
  if (person.Age >= 21)
  {
    <div>Adult</div>
  }
  else
  {
    <div>Child</div>
  }
}

对我来说,这是一个观点中的逻辑。我对 ViewModel 的定义是表示所有必要数据点(甚至是从逻辑派生的数据点)的模型。所以我会做类似的事情:

public class PersonVM
{
  public DateTime BornOn { get; set; }
  public bool IsAdult { get { return /*BornOnLogic*/; } ]
}

所以在我看来,我不明白为什么有人需要在 Javascript 中直接使用任何 C#。

我还建议阅读 Philip Walton's (Google Engineer) -Decoupling Your HTML, CSS, and JavaScript