介绍Vuecket





俄语版

Vuecket是一个Web框架,在客户端集成了VueJS,在服务器端集成Apache Wicket。它兼具了两者的优点,使开发全栈应用程序变得更快,更容易。当然,这些都是大词,因为Vuecket当前(2020年8月)还不到一个月的时间,并且它还没有通过“火与血”生产服务器的洗礼。但是它已经囊括了我们在开发关键的开源产品Orienteer(用于快速开发业务应用程序的平台)过程中开发的所有最佳产品。正是由于Vuecket的年龄很小,它需要您的帮助:请分享您喜欢的东西,不是很好的东西,需要改进的地方等等。



指导我们构建Vuecket的基本原则是:



  1. 声明式不是必须的。Vuecket并没有规定任何特殊的代码要求。它可以非常快速,轻松地应用于现有的Vue.JS或Apache Wicket项目。
  2. 遵循帕累托原则。Vuecket应该提供您想要开箱即用的功能的80%,但是对于其余20%来说应该有一个方便的扩展点。


显而易见,这些原则也适用于Vue.JS和Apache Wicket。



那么,我们到底如何开始使用Vuecket?我建议在Markdown支持下进行聊天/访客留言板。我不会过多地折磨:完成的应用程序在这里,代码在这里



我们创建一个项目



让我们通过`mvn archetype:generate`生成我们的项目。为此,您可以使用例如以下命令:



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


Vuecket尚未拥有自己的Maven项目模板。也许将来我们也会添加它。现在,让我们连接Vuecket本身。将以下依赖项添加到项目`pom.xml`中:



<dependency>
	<groupId>org.orienteer.vuecket</groupId>
	<artifactId>vuecket</artifactId>
	<version>1.0-SNAPSHOT</version>
</dependency>


在Markdown中输出文本



默认情况下,Wicket项目已经包含一个Wicket欢迎页面。让我们添加一些代码以确保Vuecket已经在运行。例如,让我们在Markdown中显示Hello World,但在Apache Wicket组件的服务器端设置文本本身。我们将使用vue-markdown库渲染Markdown



在HomePage.html中,而不是Wicket问候,添加:



<div wicket:id="app">
	<vue-markdown wicket:id="markdown">This will be replaced</vue-markdown>
</div>


在HomePage.java中,以下代码:



public HomePage(final PageParameters parameters) {
	super(parameters);
	add(new VueComponent<String>("app")
			.add(new VueMarkdown("markdown", "# Hello World from Vuecket")));
}


但是VueMarkdown类在哪里?我们将其定义如下:



@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);
	}
}


注意@VueNpm批注。需要在此Wicket组件上启用Vuecket,这将从NPM加载所需的所有内容,以帮助浏览器为Markdown正确渲染已存在的Vue组件。



如果一切正确,那么在用`mvn jetty:run`启动项目后,您应该在http:// localhost:8080上看到类似的内容




那么这里发生了什么,为什么它起作用?



  • 我们通过向页面添加2个Vue组件来标记页面:用于应用程序和Markdown输出
  • 我们在服务器端将Vue组件与Wicket组件捆绑在一起(在HomePage.java中)
  • 我们告诉Vuecket它需要哪个Vue.JS库来呈现“ vue-markdown”
  • 然后,一切都变得很简单:Wicket,当将页面呈现到浏览器时,使用了“#Vuecket的世界”,这是我们在添加Wicket组件时设置的,Vuecket帮助浏览器加载了必要的VueJS库,启动了VueJS应用程序,并将问候呈现为渲染的Markdown


Github致力于帮助



输入消息并预览



在这一步中,我们将使应用程序复杂化:我们将输入消息并进行预览。

让我们在HomePage.html中添加一个textarea来输入消息,并将此字段和vue-markdown绑定到VueJS变量“ text”。



<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>


我们已经在使用“文本”变量,但是现在我们需要将其添加到数据Vue组件中。在Vuecket中,有几种方法可以做到这一点,但让我们走得最长一些:



  • 为Vue应用程序创建自己的VueComponent
  • 让我们将其与* .vue文件关联
  • 让我们在* .vue文件中编写逻辑:现在,仅“文本”字段


这是我们将要进行的一些更改:



//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);
	}
}


好吧,ChatApp.vue本身:



<script>
module.exports = {
    data: function() {
        return {
            text : ""
        }
    }
}
</script>


结果,当您启动`mvn jetty:run`并输入一些文本时,您会看到以下内容




在本章中,我们学习了如何:创建熟悉的* .vue文件并将它们与Apache Wicket组件相关联



GitHub致力于帮助



显示消息列表并添加新消息



本章将不涉及任何Vuecket或Wicket:纯粹的VueJS闪耀。

如果我们分解任务,那么我们将需要执行以下操作:



  • 在我们的Vue应用程序中添加一个列表框以保存消息
  • 添加方法以将新消息添加到列表
  • 显示消息列表,不要忘记降价促销


首先,让我们更改ChatApp.vue并添加必要的逻辑:带有消息列表的新`messages`字段和添加新消息的`addMessage`方法。而且不要忘了,在将消息添加到列表时,最好清除原始输入字段。对于消息,我们将不仅存储文本,还存储添加/发送的日期。将来,可以扩展其他字段,例如,谁发送了此消息,优先级,必需的突出显示等。



<script>
module.exports = {
    data: function() {
        return {
            text : "",
            messages: []
        }
    },
    methods: {
    	addMessage : function() {
    		this.messages.push({
    			message: this.text,
    			date: new Date()
    		});
    		this.text = "";
    	}
    }
}
</script>


当按下Ctrl-Enter时,我们还将更改HomePage.html,添加消息列表的显示并添加对addMessage方法的调用。



<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>


当您运行`mvn jetty:run`并输入一些消息时,您将看到类似这样的内容




在本章中,我们仅讲授了使用VueJS将应用程序添加到列表中并显示消息的应用程序。



GitHub致力于帮助



开启协作



如果在此之前,访客留言的内容对于页面的每个访问者都是唯一的,则在本章中,我们将启用与服务器的通信并允许与所有访问者进行同步。为此,我们需要Vuecket Data Fibers,该解决方案允许浏览器端对象与服务器端对象同步。最有趣的是,我们不需要在客户端为此做任何事情!听起来不错?我们去编码吧!尽管...在我们的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);
}


这里发生了什么:



  • 我们创建了一个MESSAGES模型,每个人都可以使用,因为它是作为static final创建的。
  • 添加了数据纤维,该数据纤维将客户端的message对象与服务器端的MESSAGES模型内部的对象绑定在一起。
  • , data-fiber 3 : load, observe, refresh. Load — , Observe — , Refresh — .


-




GitHub commit





在上一章中,我给所有站点访问者一次授予了对消息集合的读/写访问权限的欺骗,这有点欺骗。不建议这样做,因为这样,任何发件人都可以通过数据光纤使用自己的东西覆盖服务器上的所有消息,甚至擦除它们。数据纤维仅应用于将自定义浏览器端对象链接到属于同一用户的服务器端数据对象。这意味着没有静态模型或数据!



我们如何解决这种情况?为此,我们必须:



  • 沟渠数据光纤,它可以全面使用,并且仅用于最初加载消息列表。
  • 使用服务器端方法将新消息添加到列表中。


因此,每个人只能将新消息添加到常规列表中,但不能删除或更改现有消息。让我们稍微复杂一点服务器端:我们将不仅保存从客户端收到的JSON,还保存带有必要字段,方法等的专用Message类。在服务器端处理数据。



让我们从用于存储用户消息的Message类开始。顺便说一下,这可能是一些JPA类,它允许您将数据保存到数据库。



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;
	}	
}


注意@JsonProperty。因此,我们已将JSON字段“ message”重定向到我们的Java字段“ text”。



接下来,让我们更改ChatApp.java以执行上述操作:添加vuecket方法以保存消息。同样,在代码中,您可以注意到消息列表仅减少了20条(Habr用户非常勤奋),但是当删除消息时,它仍然永远保存在服务器日志中。



@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));
	}
}


看到@VueMethod批注方法吗?在其中,我们收到一条新消息,将其保存在列表中,进行剪切并将已更新的列表发送给客户端。还要注意,数据纤维已重新配置为仅在Vue应用程序启动时请求数据。



我们还需要更改ChatApp.vue中的逻辑,以便以异步模式(vcInvoke)向服务器发送新消息,而不是本地“ messages”字段



module.exports = {
    data: function() {
        return {
            text : "",
            messages: []
        }
    },
    methods: {
    	addMessage : function() {
    		this.vcInvoke("addMessage", {
    			message: this.text,
    			date: new Date()
    		});
    		this.text = "";
    	}
    }
}


我们从本章中学到了什么:



  • 如何为Vuecket创建服务器端方法
  • 如何从浏览器调用服务器上的方法
  • 如何将必要的更改发送给客户端


对于守法访问者,什么都没有改变,但是黑客再也不能轻易更改服务器上邮件的常规列表了




GitHub致力于帮助



结论



今天,让我四舍五入。可以对我们的代码进行很多改进,但是亲爱的读者,我会把它留给您。如果您需要帮助,请写信,我们将为您提供帮助!



你喜欢这个框架吗?请分享您的意见。毕竟,您认为开放源代码能够生存和发展。



即将到来的Vuecket改进的破坏者
  • WebSocket' .
  • , .
  • data-fiber' .
  • Vuecket/Wicket , VueJS , , Markdown





All Articles