> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Criando aplicativos ASP.NET Core que utilizam o Vue.js
- URL: https://www.azurebrasil.cloud/blog/criando-aplicativos-asp-net-core-que-utilizam-o-vue-js/
- Published: 2024-10-07T17:46:10.000Z
- Updated: 2024-10-07T17:46:10.000Z
- Author: Talles Valiatti

[Vue.js](https://vuejs.org/?ref=azurebrasil.cloud) é um framework JavaScript voltado para a criação de interfaces de usuário dinâmicas. Ele é leve, flexível e pode ser integrado de maneira gradual em projetos já existentes, sem precisar reestruturar completamente o código. Sua simplicidade, aliada à sua capacidade de gerenciar o estado de componentes, torna-o uma escolha popular para desenvolvedores que buscam uma abordagem moderna para a criação de interfaces.

Neste exemplo, estamos criando aplicativos[ ASP.NET Core MVC](https://learn.microsoft.com/pt-br/aspnet/core/mvc/overview?view=aspnetcore-8.0&ref=azurebrasil.cloud) que renderizam páginas HTML, e utilizaremos o Vue.js para a manipulação dos elementos dinâmicos nessas páginas. Ao fazer isso, estamos optando por uma alternativa mais moderna ao tradicional [jQuery](https://jquery.com/?ref=azurebrasil.cloud), aproveitando os recursos avançados de frameworks como Vue.js para lidar com interatividade e reatividade.

Esse post pretende ser educacional e não apresenta um código pronto para produção, mas sim um guia para ajudar no entendimento de como integrar o Vue.js com o ASP.NET Core MVC.

Vamos começar criando a pasta raiz para nosso projeto e uma *solution*:

```csharp
mkdir AspNetCoreMvcVueJs
dotnet new sln
```

Agora, vamos criar um projeto MVC e adicioná-lo à nossa *solution*:

```csharp
dotnet new mvc -n MyApp
dotnet sln add MyApp/MyApp.csproj
```

Vamos adicionar a importação do Vue.js usando `importmap`, uma maneira moderna de importar bibliotecas JavaScript diretamente do CDN, sem a necessidade de um gerenciador de pacotes. Isso facilita a integração do Vue.js com o ASP.NET Core MVC.

Abra o arquivo `_Layout.cshtml` na pasta `Views/Shared` e insira o seguinte código para importar o Vue.js:

```csharp
    @* Add Vue *@
    <script type="importmap">
        {
          "imports": {
            "vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.21/vue.esm-browser.prod.min.js"
          }
        }
    </script>
```

[*Mixins*](https://br.vuejs.org/v2/guide/mixins.html?ref=azurebrasil.cloud) no Vue.js são uma poderosa ferramenta que permite reutilizar lógica entre diferentes componentes de uma aplicação. Eles contêm opções reutilizáveis, como métodos, variáveis reativas, ou *hooks* do ciclo de vida, que podem ser incluídos em múltiplos componentes Vue. Isso facilita a manutenção e a organização do código, especialmente quando temos funcionalidades comuns que precisam ser implementadas em várias partes da aplicação.

Quando um [*mixin*](https://br.vuejs.org/v2/guide/mixins.html?ref=azurebrasil.cloud) é aplicado a um componente, todas as suas propriedades e métodos são mesclados ao componente. Isso significa que o componente poderá acessar qualquer função ou dado definido no *mixin* como se tivesse sido declarado diretamente no próprio componente. É uma excelente solução para evitar repetição de código, tornando o desenvolvimento de aplicações mais dinâmico e eficiente.

No arquivo `_Layout.cshtml`, criamos um componente Vue principal e utilizamos *mixins* para tornar a lógica mais modular e reutilizável:

```csharp
@* Vue app *@
<script type="module">
    import { createApp } from 'vue';
    
    const app = createApp({
        mixins: [pageMixin]
    });

    app.mount('#app');
</script>
```

Com isso, podemos criar nossa primeira página. No arquivo `Views/Home/Index.cshtml`, substitua o conteúdo pelo seguinte código:

```cshtml
@{
    ViewData["Title"] = "Counter";
}

<div class="text-center">
    <h1>Simple Counter</h1>
    <div id="app">
        <h2>{{ count }}</h2>
        <div class="d-flex justify-content-center gap-2">
            <button v-on:click="increment" class="btn btn-primary">Increment</button>
            <button v-on:click="decrement" class="btn btn-danger">Decrement</button>
        </div>
    </div>
</div>

@section Scripts {
    <script>
        const pageMixin = {
            data() {
                return {
                    count: 0
                };
            },
            methods: {
                increment() {
                    this.count++;
                },
                decrement() {
                    this.count--;
                }
            }
        };
    </script>
}

```

- O Vue.js é utilizado para criar uma instância reativa de dados, controlando o comportamento do contador na interface.
- A propriedade `data()` do Vue.js retorna um objeto que contém o estado inicial, no caso, a variável `count`, que começa com o valor `0`.
- O Vue.js faz a vinculação reativa de dados (data binding) entre a variável `count` e o conteúdo do elemento `<h2>`. Isso significa que sempre que o valor de `count` for alterado, a interface será automaticamente atualizada para refletir essa mudança.
- Os métodos `increment()` e `decrement()` são definidos dentro da propriedade `methods` do Vue.js. Esses métodos alteram o valor da variável `count` ao serem chamados.

O uso da [diretiva](https://vuejs.org/api/built-in-directives.html?ref=azurebrasil.cloud) `v-on:click` no Vue.js permite a vinculação dos eventos de clique dos botões aos métodos `increment()` e `decrement()`, atualizando o valor de `count` dinamicamente quando o usuário interage com os botões.

Vamos executar a aplicação e verificar o comportamento da página:

```bash
dotnet run
```

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-12.22.36.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-12.22.41.png)

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-12.22.46.png)

Tudo correu com esperado!

Agora, vamos criar uma nova página em nossa aplicação ASP.NET Core MVC chamada `Components.cshtml`, onde utilizaremos [componentes](https://vuejs.org/guide/essentials/component-basics.html?ref=azurebrasil.cloud) do Vue.js. Isso permitirá que você veja como trabalhar com componentes reutilizáveis em uma página da aplicação.

Para começar, precisamos criar um componente Vue.js que será utilizado em nossa nova página. Vamos criar uma pasta chamada `components` dentro de `wwwroot/js` e, dentro dessa pasta, criaremos um arquivo chamado `countComponent.js` com o seguinte código:

```js
export default {
    data() {
        return {
            count: 0
        };
    },
    template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`
}

```

Este componente utiliza JavaScript nativo para manipular o contador e renderiza um botão que exibe o número de vezes clicado. Ao clicar no botão, o valor de `count` é incrementado. O componente foi escrito em JavaScript nativo, sem o uso de ferramentas de compilação como Babel ou Webpack, que são frequentemente utilizados em projetos mais complexos.

Existem dois tipos de componentes Vue.js: os compilados e os não compilados.

1. **Componentes Não Compilados**: esses componentes são escritos diretamente em JavaScript, como no exemplo acima. Eles podem ser usados sem a necessidade de um ambiente de build ou ferramentas de compilação. Esta abordagem é simples, mas limitada quando o projeto cresce e a complexidade aumenta.
2. **Componentes Compilados**: esses componentes são escritos em arquivos `.vue` e passam normalmente por uma etapa de compilação usando ferramentas como Vue CLI, Vite, ou Webpack. Essa abordagem permite dividir o *template*, *script*, e estilos em uma única estrutura modular, oferecendo mais organização e flexibilidade.

Para projetos mais complexos, os componentes compilados são geralmente preferidos devido à escalabilidade e manutenção que eles oferecem. No entanto, para pequenos exemplos como este, o uso de componentes não compilados funciona bem e é fácil de configurar.

Com o componente criado, agora podemos adicionar o conteúdo à nova página `Components.cshtml`. Substitua o conteúdo dessa página pelo seguinte código:

```cshtml
@{
ViewData["Title"] = "Counter";
}

<div class="text-center">
    <h1>Components</h1>
    <div class="d-flex justify-content-center gap-2">
        <count-component></count-component>
        <count-component></count-component>
        <count-component></count-component>
    </div>
</div>

@* Create mixin *@
@section Scripts {
    <script>
        const pageMixin = {};
    </script>
}

```

- **Três Instâncias do Componente**: Cada `count-component` tem seu próprio estado isolado, permitindo que os contadores operem independentemente.
- **Uso de Vue.js com Componentes**: Demonstramos como usar componentes Vue.js não compilados diretamente em uma página ASP.NET Core MVC.

Finalmente, na controladora do seu projeto ASP.NET Core, adicione uma nova ação chamada `Components` para renderizar a nova página:

```CSHARP
public IActionResult Components()
{
    return View();
}

```

Para garantir que o componente Vue.js esteja disponível em todas as páginas que utilizam o layout principal, precisaremos modificar o arquivo `_Layout.cshtml` para importar e registrar o componente.

Primeiro, vamos adicionar o *script* que importa o componente `countComponent.js` no layout principal. Isso garante que o componente estará disponível para uso em qualquer página que herde deste layout.

```html
@* Components *@
<script src="~/js/components/countComponent.js" asp-append-version="true" type="module"></script>

```

Essa linha importa o *script* do componente diretamente da pasta `wwwroot/js/components` e garante que ele seja carregado corretamente com a versão mais recente, graças à tag `asp-append-version`.

Agora, vamos modificar o código de criação do aplicativo Vue.js dentro do `_Layout.cshtml`, passando o componente criado para que ele possa ser utilizado em qualquer página que utilize o layout.

Substitua ou adicione o seguinte código para criar o aplicativo Vue.js e registrar o componente `CountComponent`:

```html
@* Vue app *@
<script type="module">
    import { createApp } from 'vue';
    import CountComponent from '@Url.Content("/js/components/countComponent.js")';
    
    const app = createApp({
        mixins: [pageMixin],
        components: {
            // Registrar o componente aqui
            'count-component': CountComponent
        }
    });

    app.mount('#app');
</script>

```

Nesse código, importamos o `CountComponent` e o registramos localmente dentro do aplicativo Vue.js. Agora, sempre que a tag `<count-component>` for usada em uma página que herda do `_Layout.cshtml`, o componente será renderizado corretamente.

Vamos executar novamente a aplicação e verificar a nova página criada:

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-13.09.25.png)

Podemos clicar em cada componente e verificar que cada um possui seu próprio estado e seus próprios *event handlers.*

Agora vamos criar uma nova página chamada `Forms.cshtml`, onde manipularemos dois tipos de formulários: um gerenciado pelo Vue.js no *frontend* e outro gerenciado pelo ASP.NET Core mediante uma requisição POST. Isso nos permite interagir com dados no *frontend*, enquanto os submetemos ao *backend* para processamento e persistência.

Estrutura da Página `Forms.cshtml`:

```html
@model MyApp.ViewModels.ItemsViewModel

@{
    ViewData["Title"] = "Forms";
}

<div class="text-center">
    <h1>Forms</h1>
</div>

<!-- Formulário Vue.js -->
<form v-on:submit.prevent="addItem">
    <div class="form-group">
        <p>Item name: <input class="form-control" type="text" required v-model="itemName"></p>

        <div v-show="items.length > 0">
            <p>Items:</p>
            <ul>
                <li v-for="item in items">{{ item }}</li>
            </ul>
        </div>

        <button class="btn btn-secondary" type="submit">Add item</button>
    </div>
</form>

<!-- Formulário ASP.NET Core -->
<form asp-action="Forms" method="post">
    <input type="hidden" asp-for="Items" :value="concatenatedItems" />
    <button class="btn btn-primary mt-2">Save</button>
</form>

@section Scripts {
    <script>
        const pageMixin = {
            data() {
                return {
                    itemName: null,
                    items: []
                };
            },
            computed: {
                concatenatedItems() {
                    return this.items.join(';');
                }
            },
            methods: {
                addItem() {
                    this.items.push(this.itemName);
                    this.itemName = null;
                }
            }
        };

        const app = Vue.createApp({
            mixins: [pageMixin]
        });

        app.mount('body');
    </script>
}

```

- **Vue.js Form**:O formulário gerenciado pelo Vue.js permite adicionar itens a uma lista de forma dinâmica, sem fazer uma requisição ao servidor.Cada item inserido no campo de texto é adicionado à lista de itens exibida abaixo do formulário.O botão "*Add item*" utiliza o método `addItem` para atualizar a lista `items`.O campo de texto é limpo após cada submissão, e a lista é exibida apenas quando há itens adicionados.
- **ASP.NET Core Form**:O segundo formulário utiliza a estrutura padrão do ASP.NET Core, enviando os dados para a ação `Forms` via uma requisição POST.O campo oculto (`<input type="hidden">`) envia a lista de itens concatenada como uma string, separada por `;`, ao *backend*.Ao clicar no botão "*Save*", o formulário é submetido para o servidor, permitindo o processamento ou salvamento dos dados.

Criamos um *ViewModel* simples para transportar a lista de itens concatenada como uma única string para o servidor:

```csharp
namespace MyApp.ViewModels
{
    public class ItemsViewModel
    {
        public string? Items { get; init; }
    }
}

```

A controladora `FormsController` gerencia a exibição da página e o processamento do formulário enviado via POST. Aqui está como a controladora deve ser estruturada:

```csharp
public class FormsController : Controller
{
    // Exibe a página do formulário
    public IActionResult Forms()
    {
        return View();
    }

    // Processa os dados enviados via POST
    [HttpPost]
    public IActionResult Forms(ItemsViewModel viewModel)
    {
        if (ModelState.IsValid)
        {
            // Redireciona para outra ação, como a página inicial, após o processamento bem-sucedido
            return RedirectToAction(nameof(Index));
        }

        // Se houver falha na validação, retorna à mesma view com os dados atuais
        return View(viewModel);
    }
}

```

Com isso, podemos testar a página:

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-13.15.47.png)

a

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-13.15.59.png)

a

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-13.16.06.png)

Clicando em "Save", podemos analisar o *view model* enviado a controladora:

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2024/10/Screenshot-2024-10-07-at-13.16.48.png)

E é isso pessoal!

Esse foi um simples exemplo de como podemos integrar o ASP.NET Core MVC ao Vue.js.

Você já pode baixar o projeto por esse [link](https://github.com/TallesValiatti/AspNetCoreMvcVueJs?ref=azurebrasil.cloud), e não esquece de me seguir no [LinkedIn](https://www.linkedin.com/in/tallesvaliatti/?ref=azurebrasil.cloud)!

Até a próxima, abraços!