Modern front-end development has produced many excellent JavaScript frameworks, each with its own characteristics in terms of performance and efficiency, and each front-end team has its own development framework that is comfortable to use. This article introduces a new front-end framework, Mithril. Js, which is a high-performance JavaScript framework whose size and speed make it a good choice for view-model needs. Most of the work in Mithril.js is pure JavaScript. In addition, Mithril. Js is a great tutorial for learning functional programming. This article builds a simple application that displays the list of posts and implements CRUD operations in simple steps:
- Project initialization
- Setting Application Components
- Set routes between pages
- The implementation of listing
- Implement create/update forms
- Add delete button
- The Bootstrap beautify UI
If you need to see the final result, you can find it on GitHub.
Mithril. Js official website: mithril.js.org/
Project initialization
The front-end project framework is usually introduced by referring to the core Mithril. Js file on the public CDN, by NPM install or by other scaffolding. In this paper, the scaffolding Vite. TypeScript will be used in this application.
First, create the base application and install the dependencies, here naming the project mithril-Study, then use the Vite template Vane-ts.
npm init vite@latest ./ --template
Copy the code
Install dependencies:
npm install mithril -- save
npm install bootstrap --save
npm install @types/mithril -- save-dev
Copy the code
Setting Application Components
Now create an application component that renders the root element of the application (
) and will become a container for all other components in the application. Replace the SRC >main.ts code with:
import "./style.css"; import m from "mithril"; function App(): m.Component { return { view: () => m( "div.app", m("header", "Mithril Study"), m("main", "[main content]"), m( "footer", "Mithril is simple yet powerful, a simple yet powerful front-end framework "),}; } m.mount(document.body, App);Copy the code
So what’s going on here?
- Install dependencies
Mithril.js
It’s all in the foldernode_modules
In the applicationimport
Import, and give it a short namem
To facilitate subsequent calls. - Defines a function
App
, it returns oneMithril
Components. Defines a returnMithril
Component functionsApp
。Mithril
A component is any object that has view methods. byApp
The component returned by the function will be called from hereapp
Components. - The view method will
m
As a function call, its first argument looks like a CSS selectordiv.app
. This is going to appear to be<div class="app"></div>
. rightm
Multiple calls are added as arguments to the first call, which is rendered as nested elements. - Finally, tell
Mithril
Apply colours to a drawingApp
Whatever the function returns and renders todocument.body
Element.
Now run NPM run dev in terminal to run Vite, then navigate to the application as follows:
Open the file index.html in the root directory and remove the div with the ID app, because the project’s render root is Document.body.
Set routes between pages
Add the following three functions to SRC >main.ts before setting the route:
function GetList(): m.Component { return { view: () => "Get List", }; } function PostForm(): m.Component { return { view: () => "Post Form", }; } function setupRouting(root: Element): void { m.route.prefix = ""; {m.r oute (root, "/", "/" : the GetList, / / access list "/ posts" : PostForm, / / send data/posts / : "id" : PostForm, / / update the data}); }Copy the code
The first two are component functions, so the convention is that component functions are named with a capital letter, just like App functions, and need to render some virtual text.
The setupRouting function does the following:
- First, it takes an HTML element from the DOM as input.
- By putting the
m.route.prefix
Set to an empty string that defines how the route should be resolved from the browser URL. If I ignore it,Mithril
Will use stroke point hashes just like any other front-end framework#!
That would provide something similarhttp://localhost:3000/#! /posts/1
The URL. Change the URL format to the following by setting it to an empty stringhttp://localhost:3000/posts/1
. - call
m.route(...)
Function to set three parameters, the first being an HTML element that acts as a routing container, in which all the routing content will be displayed. The second parameter is the fallback route to use when the browser navigates to a URL that has no route defined. The third parameter is an object that maps the route (URL path) to the component function. - Finally, look at the route
/posts/:id
. This route maps a portion of the URL to a variableid
. You can check the route parameter in the component.
You need to call setupRouting from somewhere to provide it with an HTML element. In the App function, place m(“main”…) The line changes to the following:
m("main", {
oncreate: (vnode: m.VnodeDOM) => setupRouting(vnode.dom),
})
Copy the code
When the second argument to M is a non-component object, it is used to configure the element created by the first argument. In this case, one of Mithril’s lifecycle hooks is used: onCreate. This hook is called when Mithril creates an element in the DOM and exposes a virtual node (an internal representation of the element) with the DOM element attached. Supply the DOM element to setupRouting.
Now the browser type http://localhost:3000 to see the contents of the main elements to Get the List, then enter http://localhost:3000/posts as you can see the main content into a Post Form.
Implementing real lists
The previous list was just text content; now it’s time to get the list data through Ajax. To implement the GetList component, add the following interface and update the GetList function:
interface IPost { userId: number; id: number; title: string; body: string; } function GetList(): const posts: IPost[] = [{userId: 1, id: 1, title: "Array of JavaScript data structures ", body: In JavaScript, arrays are modified objects. Unlike other languages, each slot in an array can store any type of data. This means you can create an array whose first element is a string, the second element is a number, and the third element is an object. 2, title: "JavaScript data structure Object", body: "Object is one of the most commonly used data types in ECMAScript and is ideal for storing and interacting data between applications. Object defines an unordered collection of properties, which can be thought of as a hash table. return { view: () => m( "section.post-list", m( "ul", posts.map((post) => m( "li", m( m.route.Link, { href: ` / posts / ${post. Id} `,}, post. The title)))), m (m.r oute. Link, {href: "/ posts", the className: "button,"}, "new")),}; }Copy the code
The above code does the following:
- First defines the data structure of the article, namely the interface
IPost
And define the article dataposts
; - in
view
Method to create a list (ul
), and set a CSS class for it; - Add one
new
Connection button of
View the running result, as shown below:
Next, go back to GetList to increment the actual interface call data, and insert the following code before return:
m.request<IPost[]>({ method: "GET", url: "https://jsonplaceholder.typicode.com/posts", }).then((data) => posts.push(... data));Copy the code
Call m.test and insert the response data into the posts variable. With TypeScript, add a type parameter to m.test
to predict what type the response data will be.
Implement the Create/edit page
The PostForm function will be updated and a function will be added to hold the article data:
function savePost(post: IPost, callback: Function): void { const isCreate = post.id === -1; const url = "https://jsonplaceholder.typicode.com/posts" + (isCreate ? "" : `/${post.id}`); m.request<IPost>({ method: isCreate ? "POST" : "PUT", url, body: post, }).then((data) => callback(data)); } function PostForm(): m.Component { let post: IPost = { userId: -1, id: -1, title: "", body: "", }; const id = m.route.param("id"); if (id) { m.request<IPost>({ method: "GET", url: `https://jsonplaceholder.typicode.com/posts/${id}`, }).then((data) => (post = data)); } return {view: (a) = > m (" form ", m (" div ", m (" label ", "the title:"), m (' input [type = "text"] ', {value: the post title, onchange: (e: Event) => (post.title = (e.target as HTMLInputElement).value),})), m(" div", m("label", "contents: "), m('textarea[rows="5"]', { value: post.body, onchange: (e: Event) => (post.body = ( e.target as HTMLTextAreaElement ).value), }) ), m( "div", m("label", ""), M ('button.button[type=" button.button "]', {onclick: () => savePost(post, () => {console.log(" save operation completed "); }),}, "Save now"))),}; }Copy the code
Then click on the article to see the following effect:
Add delete button
As the last CRUD operation, this is where the delete function is implemented. Go back to the GetList function and add a delete button to each list item and bind the button with a click event to send a delete request to the API.
function deletePost(postId: number): void {
m.request({
method: "DELETE",
url: `https://jsonplaceholder.typicode.com/posts/${postId}`,
});
}
Copy the code
Bootstrap
Now use Bootstrap to make simple adjustments to the interface. The specific code is not shown here, but can be viewed on GitHub. The final result is as follows:
conclusion
At this point, a simple CRUD application is built. Mithril takes care of rendering, routing, and HTTP requests, while pure JavaScript takes care of the rest. So far, you can see the simplicity of Mithril building applications. Because it is a learning nature, some interactions are incomplete, such as the operation after a successful save or delete is not implemented, including subsequent logical updates. If you are interested, please refer to the official documentation: mithril.js.org/