问题

对于那些使用 .Net 的人来说,使用 Razor 在服务器端呈现他们的页面是很常见的。而且,很长一段时间以来,当需要进行一些 AJAX 调用或操作一些 DOM 时,我们都将 jQuery 作为盟友。这是默认堆栈。

随着 VueJS 的采用,我们的生活有了很大的改善。但是,每当我们想在Vue项目中表示Razor渲染的对象时,都需要使用Js语法重写整个对象。

在这篇文章中,我打算展示一些如何使从控制器发送到视图的对象也自动在 Vue 代码中可用。

假设我们有以下结构:

Person.cs

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

PersonController.cs

public class PersonController : Controller
{
    public IActionResult Form()
        {
            var person = new Person();
            return View(person);
        }
}

表单输入已经与我们稍后将创建的 Vue 对象的属性绑定。

Form.cshtml

@model Person

<form asp-route="Save" method="post">
    <input asp-for="Id" v-model="Model.Id"  />
    <input asp-for="Name" v-model="Model.Name"  />
    <input asp-for="Age" v-model="Model.Age"  />
</form>

为了让我们在 Vue 项目中使用Person类,也为了上面的绑定工作,有必要在 Vue 内部重写整个类:

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  data() {
    return {
      Model: {
        Id: 0,
        Name: '',
        Age: 0
      }
    }
  },
  render: h => h(App),
}).$mount('#app')

显然这是一种非常简单的方法,但仍然有必要以某种方式重写整个Person类,以便能够访问,如下例所示:

//...
methods: {
  changeName () {
    this.Model.Name = 'New Name'
  }
}
//...

准备工作

我们需要进行 3 次更改才能使事情自动运行。首先,我们将创建一个将要呈现的对象传输为 JSON 格式的方法。在这里,我假设您将创建一个类BaseController,以便您可以在所有控制器中使用此方法。

BaseController.cs

public class BaseController : Controller
{
    protected JsonSerializerSettings jsonSettings;

    public BaseController()
    {
        this.jsonSettings = new JsonSerializerSettings
        {
            Culture = new CultureInfo("pt-BR"),
            DateFormatString = "dd/MM/yyyy",
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            Formatting = Formatting.Indented
        };
    }

    public ViewResult ViewJson(object model, string view = "")
    {
        // Transformamos o objeto em Json e enviamos para a view usando ViewBags
        ViewBag.Model = JsonConvert.SerializeObject(model, this.jsonSettings);

        // Depois a view é renderizada normalmente
        if (string.IsNullOrWhiteSpace(view))
            return View(model);
        else
            return View(view, model);
    }
}

现在对象序列化了,让我们将它添加到一个名为model的全局 JavaScript 变量中。这个变量稍后将在我们的 Vue 项目中使用。

我们将在布局文件中执行此操作,因为整个系统都将使用此解决方案。

_Layout.cshtml

<html>
    <head>
        <script>
            @if (string.IsNullOrWhiteSpace(ViewBag.Model))
            {
                <text>const model = null;</text>
            }
            else
            {
                <text>const model = @Html.Raw(ViewBag.Model);</text>
            }
        </script>
    </head>
    ...
</html>

最后,我们需要让全局变量model可以从 Vue 的根目录访问。

Main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  data() {
    return {
      Model: model
    }
  },
  render: h => h(App),
}).$mount('#app')

// Sempre adiciono esta linha para deixar o Vue acessível pelo console do navegador
window.vue = vue;

应用更改

现在,只需更改控制器,将方法调用View()更改为ViewJson()

PersonController.cs

public class PersonController : Controller
{
    public IActionResult Form()
        {
            var person = new Person();
            //Única alteração necessária nos controllers
            return ViewJson(person);
        }
}

结论

现在,除了在服务器端呈现的 Razor 页面之外,每个操作都将返回,您还将拥有一个表示在@model中分配的类的 Vue 对象。

Logo

前往低代码交流专区

更多推荐