UX framework for JavaScript libraries
In one of my JS projects, I needed to implement UX interfaces in the Web SDK. Such a Web SDK was embedded on pages of third-party sites and for security reasons should not contain any external dependencies, including libraries like React. For these purposes, an own implementation of the UX framework was created, which can be embedded on the country of any site without problems and conflicts.
The code is implemented as a JS library and posted on GitHub under the MIT license. Build size - 12kb uncompressed (4kb gzipped).
The library consists of the following modules (classes):
- Component (extends State) - ensures the life cycle of the UX component and their states.
- Locale (extends State) - provides localization of interfaces.
- Service (extends State) - provides data exchange with the backend.
- HashRouter (extends Router) - implements roaming logic based on hashes in the address line.
Components and states
Usually the application consists of separate interconnected components. The Component
class is used to describe the logic of each UX component. This includes the following functionality:
- component status events:
- added - a new element is added to one of the state fields (for arrays);
- deleted - element of one of the state fields is deleted (for arrays);
- updated - the value of one of the status fields has changed;
- component lifecycle events:
- mounted - mounting the component in the DOM;
- removed - removing the component from the DOM;
- changed - the input parameters of the component have been changed;
- component’s overrideable properties:
- data() - function for determining the initial value of the component state;
- events() - function for defining event handlers for a component;
- template() - function for determining the HTML template of a component (EJS format).
In addition, there is a set of component methods that allow you to manage the state, subscribe to events, etc.
An example of a component description:
import { Component } from 'libux';
export default class MyView extends Component {
constructor (...args) {
super(...args);
// this.params - includes this component arguments
this.mount(document.body);
}
template () {
return `<div>Hello <%- this.state.text %>!</div>`;
}
data() {
return {
text: 'World'
};
}
events() {
return [
mounted () {
// ...
}
];
}
Localization
Localization of components allows you to display text information in different languages. This functionality is implemented in the Locale
class.
Example of using localization:
import { Locale } from 'libux';
// create a new instance
const locales = {
en: { hello: 'Hello %{name}!' },
ru: { hello: 'Привет %{name}!' }
};
const l10n = new Locale({ locales, lang: 'en' });
// get translation for specified path
l10n.t('hello', { name: 'World' }); // Hello World!
// list of supported languages
l10n.languages; // ['en', 'ru']
// switch to localization 'ru'
l10n.update({ lang: 'ru' });
Hash Routing
Routing at the application level allows you to organize the logic of switching components (pages of the SPA application). This functionality is implemented in the HashRouter
class.
import { HashRouter } from 'libux';
import TodoView from 'views/todo';
const router = new HashRouter({
routes: {
'#/': TodoView
}
});
router.show(location.hash);
Services
Services are the layer between the components and the backend API. They implement CRUD functions for exchanging data with the backend. This functionality is implemented in the Service
class.
const service = new Service({
url: 'http://localhost:3000/api/items'
});
// create new record
service.post({ id: '1', field1: 'a', field2: 'b' });
// get all records
service.get();
// get the record by id
serice.get('1');
// update the record by id
service.put('1', { field1: 'c', field2: 'd' });
// remove the record by id
service.delete('1');
CSS modules
Styles are recommended to be connected as CSS modules. Each style will be assigned a unique identifier during assembly, which allows you to avoid conflicts with other styles on the page. In the project code, you will need to import a style file and call specific styles from the imported file by their name in it.
Example of using CSS modules:
import css from 'todomvc-app-css/index.css';
export default class TodoView extends Component {
template () {
return `
<section class="${css.todoapp}">
...
</section>
<footer class="${css.info}">
...
</footer>
`;
}
}
The project has documentation in JSDoc format and a tutorial with an example of use in the form of the To-Do List application.
Comments