Key Words:
Thư viện React và Redux:
ES6:


Sẽ gồm 4 thành phần chính:
View và Actions sẽ có liên kết gọi là Dispatch. Dispatch là ghi nhận thao tác của người dùng tác động lên giao diện View.
dispatch trên View, thì luồng dữ liệu sẽ truy cập vào Actions lấy ra mô tả hành động action tương ứng, sau đó chuyển thông tin action này sang Reduce xử lý.store.state ứng dụng, tại đây chỉ có chức năng getValue(state).function nguyên thủy(pure function) gọi là reduce;
State hiện tại và thông tin Action, sau đó trả về một State mới để cập nhật vào store.
Predictable, tức là cùng 1 state, cùng 1 action thì nó luôn luôn cho ra 1 state mới giống nhau, luôn luôn là như vậy.Store được update do có thêm state mới sau xử lý reduce, thì thành phần view cần được update lại, khi này sẽ dùng chức năng subscribe. Ta có thể gọi đây là chức năng Render dữ liệu từ Store cho VIEW.

Store bao gồm các State(current) sẽ được Render, và hiển thị trên View.View, người dùng thao tác trên giao diện này được gọi là các dispatch.State(current) và dispatch sẽ được đưa đến thành phần Actions chứa các mô tả về các loại action để nhận biết dispatch đó thuộc action nào.action, luồng dữ liệu gồm State(current) và action sẽ được chuyển tiếp đến thành phần Reducer tương ứng action xử lý.Reducer sẽ xử lý các State(current) thành State(new) và cập nhật vào store.store được cập nhật State(new) , nên View sẽ cần được Render lại để cập nhật.

index.html và phần dữ liệu sẽ không viết các element thành phần chi tiết mà sẽ dùng kiểu CSR (Client Side Rendering) thao tác dùng DOM để chọn element id ='root' để truyền dữ liệu render vào đây.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Todo App</title>
</head>
<body>
<div id="root"></div>
</body>
<script type="module" src="./script.js"></script>
</html>
index.html sẽ link với file script.js theo dạng module : ` `.store sẽ bao gồm các state trạng thái chứa dữ liệu, nên ở đây ta sẽ viết 1 hàm để xử lý chuyển 1 mảng danh sách state, truyền vào element #root như sau:
ES6 - Tagged template literals như sau:const rootElement = document.querySelector('#root');
const cars = ['BMW', 'Porsche', 'Mercedes'];
const html = `
<h1>TODO List</h1>
<ul>
${cars.map((car) => `<li>${car}</li>`).join('')}
<ul>
`;
console.log(html);
rootElement.innerHTML = html;
const rootElement = document.querySelector('#root');
const cars = ['BMW', 'Porsche', 'Mercedes', true, undefined, null, NaN, false];
const isSucceeded = false;
const html = `
<h1>${isSucceeded} && TODO List</h1>
<ul>
${cars.map((car) => `<li>${car}</li>`).join('')}
<ul>
`;
console.log(html);
rootElement.innerHTML = html;

export default function html([first, ...values], ...strings) {
return values
.reduce(
(acc, cur) => {
return acc.concat(strings.shift(), cur);
},
[first]
)
.filter((x) => (x && x !== true) || x === 0)
.join('');
}
import html from './core.js';
const cars = ['BMW', 'Porsche', 'Mercedes'];
const isSucceeded = false;
const output = html`
<h1>${isSucceeded} && TODO List</h1>
<ul>
${cars.map((car) => `<li>${car}</li>`)}
<ul></ul>
</ul>
`;
const rootElement = document.querySelector('#root');
rootElement.innerHTML = output;
html() được gọi là template view // core.js LIBRARY
function html([first, ...strings], ...values) {
return values
.reduce((acc, cur) => acc.concat(cur, strings.shift()), [first])
.filter((x) => (x && x !== true) || x === 0)
.join('');
}
function createStore(dataAndAction) {
let state = dataAndAction();
const roots = new Map();
function render() {
for (const [root, component] of roots) {
const output = component();
root.innerHTML = output;
}
}
return {
// enter action from user: add, edit, delete...
dispatch(action, ...args) {
state = reducer(state, action, args);
render();
},
// get data, action and use action to process data
connect: function connect(
selector = function selector(state) {
return state;
}
) {
return function (component) {
return function (props, ...args) {
return component(Object.assign({}, props, selector(state), ...args));
};
};
},
// display data to user-interface
attach(component, root) {
roots.set(root, component);
render();
},
};
}
// DATA
var init = {
cars: ['toyota', 'honda', 'porsche'],
};
// reducer.js getDATA and createACTIONs
export default function reducer(action, state = init, ...args) {
console.log(action);
switch (action) {
case 'ADD': // action add, edit, delete...
let [newCar] = args;
return {
cars: [...state.cars, newCar],
};
break;
case 'DEL': // action add, edit, delete...
const index = args[0]
console.log('args::', index,state);
if (index > -1) {
state.cars.splice(index, 1); // 2nd parameter means remove one item only
}
return state;
break;
default:
return state;
}
}
function reducer(state = init, action, args) {
switch (action) {
case 'ADD': // action add, edit, delete...
const [newCar] = args;
return {
cars: [...state.cars, newCar],
};
default:
return state;
}
}
// store.js USING LIBRARY
const { attach, connect, dispatch } = createStore(reducer);
window.dispatch = dispatch;
// Cycle: dispatch -> connect -> attach -> dispatch -> connect -> ...
// App.js
var App = connect()(
// using connect, explaining role of connect here
function ({ cars }) {
// using html
return html`
<ul>
${cars.map((car) => `<li>${car}</li>`)}
</ul>
<button onclick="dispatch('ADD', 'PORSCHE')">Add car</button>
`;
// using dispatch-global
}
);
// script.js
attach(App, document.getElementById('root')); // using attach
// THE END
// Good luck! You can do it :D