简单的MVC+Router模式实现,可能实现得不太好,先记录下来,以后再改....
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基于MVC+router基本原理实现</title>
</head>
<body>
<div id="root"></div>
</body>
<script>
class Router {
constructor(){
this.routerFunction = {};
this.showFunction = function(){
return this.routerFunction;
}
}
add(router,fn){
if(!this.routerFunction[router]){
this.routerFunction[router] = fn;
}else{
throw new Error(`${router}已存在`);
}
}
del(router){
if(this.routerFunction[router]){
delete this.routerFunction[router];
}else{
throw new Error(`${router}不存在`);
}
}
init(){
window.addEventListener('load', () => {
this.currentUrl = location.hash.slice(1) || '/';
if(this.currentUrl === '/'){
this.routerFunction[this.currentUrl]();
}else{
this.routerFunction['other'](this.currentUrl)
}
},false);
window.addEventListener('hashchange', () => {
this.currentUrl = location.hash.slice(1) || '/';
if(this.currentUrl === '/'){
this.routerFunction[this.currentUrl]();
}else{
this.routerFunction['other'](this.currentUrl)
}
},false)
}
}
class Model{
constructor(){
this.value = {};
this.showValue = function () {
return this.value;
}
}
add(valueName,value){
if(!this.value[valueName]){
this.value[valueName] = value;
}else{
throw new Error(`${valueName}已存在`)
}
}
del(valueName,value){
if(this.value[valueName]){
this.value[valueName] = value;
}else{
throw new Error(`${valueName}不存在`)
}
}
change(valueName,value){
if(this.value[valueName] !== value){
this.value[valueName] = value;
control.change(valueName);
return true;
}else{
return false;
}
}
}
class View{
constructor(parent){
this.parent = parent;
this.template = {};
this.showTemplate = function () {
return this.template;
}
}
add(templateName,template){
if(!this.template[templateName]){
this.template[templateName] = template;
}else{
throw new Error(`${templateName}已存在`)
}
}
del(templateName){
if(this.template[templateName]){
delete this.template[templateName];
}else{
throw new Error(`${templateName}不存在`)
}
}
mix(templateName,model){
return this.template[templateName](model.value[templateName])
}
change(templateName,model){
let children = document.getElementById(this.parent).children;
for(let i = 0;i < children.length;i++){
for(let attr of children[i].attributes){
if(attr.nodeName.indexOf('z-') >= 0){
functionMix[attr.nodeName.slice(2)].call(children[i],model.value[templateName])
}
}
}
}
init(){
for(let props in this.template){
document.getElementById(this.parent).innerHTML = this.mix(props,model);
}
}
}
class Controller{
constructor(){
this.control = {};
this.showControl = function () {
return this.control;
}
}
add(name,fn){
if(!this.control[name]){
this.control[name] = fn;
}else{
throw new Error(`${name}已存在`)
}
}
del(name){
if(this.control[name]){
delete this.control[name];
}else{
throw new Error(`${name}不存在`)
}
}
change(name){
view.change(name,model);
}
init(){
for(let prop in this.control)this.control[prop]();
}
}
const functionMix = {
text:function(value) {
this.innerText = value;
},
value:function(value){
this.value = value;
}
};
let model = new Model();
model.add('input','hello moonburn');
let view = new View('root');
view.add('input',function (value) {
return `<input id="input" z-value="0" value="${value}"/><span z-text="0">${value}</span>`
});
let control = new Controller();
control.add('input',function () {
let _dom = document.querySelector('#input');
_dom.addEventListener('input',(event)=>{
model.change('input',event.target.value)
})
});
const router = new Router();
router.add('/',function () {
model.change('input',model.value['input'])
});
router.add('other',function (value) {
model.change('input',value)
});
view.init();
control.init();
router.init();
</script>
</html>