A versão russa
Vuecket é uma estrutura da web que integra o VueJS no lado do cliente e o Apache Wicket no lado do servidor. Ele tira o melhor de ambos e torna o desenvolvimento de aplicativos full-stack ainda mais rápido e fácil. Claro, todas essas são palavras grandes, porque Vuecket tem atualmente (agosto de 2020) menos de um mês, e ainda não passou pelo batismo de servidores de produção de "fogo e sangue". Mas já incluiu tudo de melhor que desenvolvemos durante o desenvolvimento do nosso principal produto Open Source, Orienteer (uma plataforma para desenvolvimento rápido de aplicações de negócios). E é precisamente pela sua tenra idade que a Vuecket necessita da sua ajuda: por favor, partilhe o que gostou, o que não é muito bom, onde é necessário melhorar, etc.
Os princípios básicos que nos guiam ao construir o Vuecket são:
- Ser declarativo não é obrigatório. Vuecket não impõe nenhum requisito de código especial. Ele pode ser aplicado de forma bastante rápida e fácil a projetos Vue.JS ou Apache Wicket existentes.
- Siga o princípio de Pareto. O Vuecket deve fornecer 80% da funcionalidade que você deseja fora da caixa, mas deve haver pontos de extensão bons e convenientes para os 20% restantes.
É fácil ver que esses princípios também se aplicam ao Vue.JS e ao Apache Wicket.
Então, como exatamente vamos começar a usar o Vuecket? Eu sugiro fazer um chat / painel de convidados com suporte Markdown. Não vou atormentar muito: o aplicativo concluído está aqui , e o código está aqui .
Nós criamos um projeto
Vamos gerar nosso projeto via `mvn archetype: generate`. Para fazer isso, você pode usar, por exemplo, o seguinte comando:
mvn archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=8.9.0 -DgroupId=com.mycompany -DartifactId=mychat -DarchetypeRepository=https://repository.apache.org/ -DinteractiveMode=false
A Vuecket ainda não tem seu próprio modelo de projeto Maven. Talvez no futuro possamos adicionar isso também. Agora vamos conectar o próprio Vuecket. Adicione a seguinte dependência ao projeto `pom.xml`:
<dependency>
<groupId>org.orienteer.vuecket</groupId>
<artifactId>vuecket</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
Saída de texto em Markdown
O projeto Wicket já contém uma página de boas-vindas do Wicket por padrão. Vamos adicionar algum código a ele para ter certeza de que o Vuecket já está funcionando. Por exemplo, vamos exibir Hello World, mas em Markdown, e para que o próprio texto seja definido no lado do servidor no componente Apache Wicket. Usaremos a biblioteca vue-markdown para renderizar Markdown .
Em HomePage.html, em vez da saudação do Wicket, adicione:
<div wicket:id="app">
<vue-markdown wicket:id="markdown">This will be replaced</vue-markdown>
</div>
E em HomePage.java o seguinte código:
public HomePage(final PageParameters parameters) {
super(parameters);
add(new VueComponent<String>("app")
.add(new VueMarkdown("markdown", "# Hello World from Vuecket")));
}
Mas onde está a aula VueMarkdown? E vamos defini-lo da seguinte maneira:
@VueNpm(packageName = "vue-markdown", path = "dist/vue-markdown.js", enablement = "Vue.use(VueMarkdown)")
public class VueMarkdown extends Label {
public VueMarkdown(String id) {
super(id);
}
public VueMarkdown(String id, Serializable label) {
super(id, label);
}
}
Preste atenção na anotação @VueNpm. É necessário habilitar o Vuecket neste componente Wicket, que carregará tudo o que é necessário do NPM para ajudar o navegador a renderizar o componente Vue para Markdown corretamente.
Se você fez tudo corretamente, depois de iniciar o projeto por meio de `mvn jetty: run`, deverá ver algo assim em http: // localhost: 8080
Então, o que aconteceu aqui e por que funciona?
- Marcamos a página adicionando 2 componentes Vue a ela: para o aplicativo e para a saída do Markdown
- Empacotamos componentes Vue com componentes Wicket no lado do servidor (em HomePage.java)
- Dissemos ao Vuecket qual biblioteca Vue.JS ele precisa para renderizar o
- E então tudo é simples: o Wicket, ao renderizar a página para o navegador, usa a linha "# Hello World do Vuecket", que definimos ao adicionar o componente Wicket, e o Vuecket ajudou o navegador a carregar as bibliotecas VueJS necessárias, iniciar o aplicativo VueJS e renderizar a saudação já como Markdown renderizado
Github se compromete a ajudar
Inserir uma mensagem e visualizá-la
Nesta etapa, complicaremos nossa aplicação: faremos a entrada e visualização da mensagem.
Vamos adicionar uma textarea a HomePage.html para inserir uma mensagem, bem como vincular este campo e vue-markdown à variável "text" VueJS.
<div wicket:id="app">
<textarea v-model="text" style="width:100%" rows="5"></textarea>
<vue-markdown wicket:id="markdown" :source="text">Will be replaced</vue-markdown>
</div>
Já estamos usando a variável "texto", mas agora precisamos adicioná-la ao componente Vue de dados. Existem várias maneiras de fazer isso no Vuecket, mas vamos por mais tempo:
- Crie seu próprio aplicativo VueComponent for Vue
- Vamos associá-lo ao nosso arquivo * .vue
- Vamos escrever a lógica no arquivo * .vue: no momento, apenas o campo "texto"
Aqui estão algumas das mudanças que faremos:
//HomePage.java:
public HomePage(final PageParameters parameters) {
super(parameters);
add(new ChatApp("app")
.add(new VueMarkdown("markdown")));
}
//ChatApp.java:
@VueFile("ChatApp.vue")
public class ChatApp extends VueComponent<Void> {
public ChatApp(String id) {
super(id);
}
}
Bem, o próprio ChatApp.vue:
<script>
module.exports = {
data: function() {
return {
text : ""
}
}
}
</script>
Como resultado, quando você inicia `mvn jetty: run` e insere algum texto, você pode ver o seguinte
Neste capítulo, aprendemos como: criar arquivos * .vue familiares e associá-los aos componentes do Apache Wicket que o
GitHub compromete para ajudar
Mostra uma lista de mensagens e adiciona uma nova
Não haverá nada Vuecket ou Wicket específico neste capítulo: brilho VueJS puro.
Se decompormos a tarefa, precisaremos fazer o seguinte:
- Adicione uma caixa de lista ao nosso aplicativo Vue para salvar mensagens
- Adicione um método para adicionar uma nova mensagem à lista
- Mostre uma lista de mensagens e não se esqueça da marcação
Primeiro, vamos mudar nosso ChatApp.vue e adicionar a lógica necessária: um novo campo `messages` com uma lista de mensagens e o método ʻaddMessage` para adicionar uma nova mensagem. E não vamos esquecer que, ao adicionar uma mensagem à lista, é uma boa ideia limpar o campo de entrada original. Para mensagens, armazenaremos não apenas o texto, mas também a data de adição / envio. No futuro, será possível expandir com campos adicionais, por exemplo, quem enviou esta mensagem, prioridade, destaque obrigatório, etc.
<script>
module.exports = {
data: function() {
return {
text : "",
messages: []
}
},
methods: {
addMessage : function() {
this.messages.push({
message: this.text,
date: new Date()
});
this.text = "";
}
}
}
</script>
Também alteraremos HomePage.html, adicionaremos uma exibição da lista de mensagens e adicionaremos uma chamada ao nosso método addMessage ao pressionar Ctrl-Enter.
<div wicket:id="app">
<div v-for="(m, index) in messages">
<h5>{{ index }}: {{ m.date }}</h5>
<vue-markdown :source="m.message"></vue-markdown>
</div>
<textarea v-model="text"
style="width:100%"
rows="5"
@keyup.ctrl.enter="addMessage"
placeholder="Enter message and Ctrl-Enter to add the message">
</textarea>
<vue-markdown wicket:id="markdown" :source="text">Will be replaced</vue-markdown>
</div>
Ao executar `mvn jetty: run` e inserir algumas mensagens, você verá algo como isto
Neste capítulo, ensinamos apenas o aplicativo usando VueJS para adicionar uma mensagem à lista e exibi-la.
GitHub se compromete a ajudar
Ative a colaboração
Se antes o conteúdo do nosso livro de visitas era único para cada visitante da página, então neste capítulo vamos habilitar a comunicação com o servidor e permitir a sincronização com todos os visitantes. Para isso, precisamos do Vuecket Data Fibers, uma solução que permite que objetos do lado do navegador sejam sincronizados com objetos do lado do servidor. E o mais interessante é que não precisamos fazer nada para isso do lado do cliente! Parece legal? Vamos codificar! Embora ... Existem apenas duas novas linhas em nosso componente ChatApp.java:
private static final IModel<List<JsonNode>> MESSAGES = Model.ofList(new ArrayList<JsonNode>());
public ChatApp(String id) {
super(id);
addDataFiber("messages", MESSAGES, true, true, true);
}
O que aconteceu aqui:
- Criamos um modelo MESSAGES que está disponível para todos, pois foi criado como final estático.
- Adicionado fibra de dados, que vincula o objeto de mensagens no lado do cliente e o objeto dentro do modelo MESSAGES no lado do servidor.
- , data-fiber 3 : load, observe, refresh. Load — , Observe — , Refresh — .
-
GitHub commit
No capítulo anterior, trapaceei um pouco ao conceder acesso de leitura / gravação à coleção de mensagens a todos os visitantes do site de uma vez. É altamente desencorajado fazer isso, porque então, por meio da fibra de dados, qualquer remetente pode sobrescrever todas as mensagens no servidor com algo próprio ou até mesmo apagá-las. As fibras de dados devem ser usadas apenas para vincular objetos personalizados do lado do navegador a objetos de dados do lado do servidor pertencentes ao mesmo usuário. Isso significa que não há modelos ou dados estáticos!
Como podemos consertar a situação? Para isso temos que:
- Esqueça a fibra de dados, que funciona em toda a linha, e use-a apenas para carregar inicialmente a lista de mensagens.
- Use o método do lado do servidor para adicionar uma nova mensagem à lista.
Assim, todos podem apenas adicionar novas mensagens à lista geral, mas não podem excluir nem alterar as existentes. Vamos complicar um pouco o lado do servidor: salvaremos não apenas JSON recebido do cliente, mas uma classe especializada Message com os campos, métodos necessários, etc. para trabalhar com dados no lado do servidor.
Vamos começar com uma classe Message para armazenar mensagens do usuário. A propósito, pode ser alguma classe JPA que permite salvar dados em um banco de dados.
public class Message implements IClusterable {
@JsonProperty("message")
private String text;
private Date date;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
Preste atenção em @JsonProperty. Assim, redirecionamos o campo JSON "mensagem" para nosso campo Java "texto".
A seguir, vamos alterar ChatApp.java para fazer o que está descrito acima: adicionar um método vuecket para salvar a mensagem. Também no código, você pode notar o corte da lista de mensagens para apenas 20 (os usuários do Habr são muito diligentes), mas quando você apaga uma mensagem, ela ainda é salva para sempre nos logs do servidor.
@VueFile("ChatApp.vue")
public class ChatApp extends VueComponent<Void> {
private static final Logger LOG = LoggerFactory.getLogger(ChatApp.class);
private static final int MAX_SIZE = 20;
private static final IModel<List<Message>> MESSAGES = Model.ofList(new ArrayList<Message>());
public ChatApp(String id) {
super(id);
addDataFiber("messages", MESSAGES, true, false, false);
}
@VueMethod
public synchronized void addMessage(Context ctx, Message message) {
List<Message> list = MESSAGES.getObject();
list.add(message);
trimToSize(list, MAX_SIZE);
IVuecketMethod.pushDataPatch(ctx, "messages", list);
}
private void trimToSize(List<Message> list, int size) {
//It's OK to delete one by one because in most of cases we will delete just one record
while(list.size()>size) LOG.info("Bay-bay message: {}", list.remove(0));
}
}
Veja o método de anotação @VueMethod? Nele recebemos uma nova mensagem, salvamos na lista, cortamos e enviamos a lista já atualizada para o cliente. Observe também que a fibra de dados foi reconfigurada para solicitar dados apenas quando o aplicativo Vue for inicializado.
Também precisamos alterar a lógica em ChatApp.vue para que, em vez do campo "mensagens" local, envie uma nova mensagem para o servidor em modo assíncrono (vcInvoke)
module.exports = {
data: function() {
return {
text : "",
messages: []
}
},
methods: {
addMessage : function() {
this.vcInvoke("addMessage", {
message: this.text,
date: new Date()
});
this.text = "";
}
}
}
O que aprendemos com o capítulo:
- Como criar métodos do lado do servidor para Vuecket
- Como chamar métodos no servidor a partir de um navegador
- Como enviar as alterações necessárias ao cliente
Para um visitante respeitador da lei, nada mudou, mas um hacker não pode mais alterar tão facilmente a lista geral de mensagens no servidor
GitHub se compromete a ajudar
Conclusão
Sobre isso hoje, deixe-me terminar. Existem muitas outras melhorias que podem ser feitas em nosso código, mas vou deixar isso para vocês, queridos leitores. Se precisar de ajuda, escreva, nós ajudaremos!
Você gosta da estrutura? Por favor, compartilhe sua opinião. Afinal, é sua opinião que o Open Source vive e se desenvolve.
Spoiler das próximas melhorias do Vuecket
- WebSocket' .
- , .
- data-fiber' .
- Vuecket/Wicket , VueJS , , Markdown