lia_acp_1
Version:
//初始项目构建案例:创建config.js文件 const acp = require('lia_acp_1');
958 lines (880 loc) • 30.3 kB
JavaScript
const fs = require('fs');
const path = require('path');
function init(fileObj) {
const dirPath = '../../';
if(!fs.existsSync(path.join(__dirname, dirPath, 'lia.js'))) {
fs.writeFile(path.join(__dirname, dirPath, 'lia.js'), template_html('js', 'lia'), function(err) {
if(err) {
console.log(err);
}
});
}
if(!fs.existsSync(path.join(__dirname, dirPath, 'event.js'))) {
fs.writeFile(path.join(__dirname, dirPath, 'event.js'), template_html('js', 'event'), function(err) {
if(err) {
console.log(err);
}
});
}
traverse(fileObj, dirPath);
}
function traverse(fileObj, dirpath) {
for(const i in fileObj) {
if(typeof fileObj[i] === 'object') {
if(!fs.existsSync(path.join(__dirname, dirpath, i))) {
fs.mkdirSync(path.join(__dirname, dirpath, i));
traverse(fileObj[i], path.join(dirpath, i));
} else {
console.log(i + '文件夹已存在');
traverse(fileObj[i], path.join(dirpath, i));
}
} else {
if(fileObj[i] === 0) {
const fname = i.split('_')[0] + '.' + i.split('_')[1];
if(!fs.existsSync(path.join(__dirname, dirpath, '/', fname))) {
let template = '';
if(i.split('_')[1] == 'html') {
template = template_html('html', i.split('_')[0]);
} else if(i.split('_')[1] == 'css') {
template = template_html('css', i.split('_')[0]);
} else if(i.split('_')[1] == 'js') {
template = template_html('js', i.split('_')[0]);
}
fs.writeFile(path.join(__dirname, dirpath, '/', fname), template, function(err) {
if(err) {
console.log(err);
}
});
} else {
console.log(fname + '文件已存在')
}
} else {
console.log(fileObj[i] + ':输入错误!')
}
}
}
}
function template_html(type, name) {
if(type == 'html') {
//html文件模板
if(name == 'index') {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="https://qileshang.top/resources/image/logo2.jpg" type="image/x-icon">
<link rel="stylesheet" href="./${ name }.css">
<title>欢迎使用lia.js</title>
</head>
<body>
<!-- template -->
<div class="${ name }">
<div class="${ name }-header">
</div>
<div class="${ name }-mainer">
</div>
<div class="${ name }-footer">
</div>
</div>
<!-- template -->
<script src="./${ name }.js" type="module"></script>
</body>
</html>`
} else if(name == 'head') {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="./head.css">
<title>head</title>
</head>
<body>
<!-- template -->
<div class="head">
<div class="logo">
<img src="https://qileshang.top/resources/image/logo2.jpg" alt="">
<span class="title">lia框架使用模板--(测试阶段)</span>
</div>
<nav>
<div class="bt-link main_link">
<span>首页</span>
</div>
<div class="bt-link anime_link">
<span>动画</span>
</div>
<div class="bt-link comic_link">
<span>漫画</span>
</div>
<div class="bt-link novel_link">
<span>小说</span>
</div>
<div class="bt-link game_link">
<span>游戏</span>
</div>
<div class="bt-link info_link">
<span>资讯</span>
</div>
</nav>
<div class="search">
<input type="text" placeholder="请输入">
</div>
<div class="login">
<div class="box">
<img src="https://qileshang.top/resources/image/logo.jpg" alt="">
<span>任相随</span>
</div>
</div>
</div>
<!-- template -->
<script src="./head.js" type="module"></script>
</body>
</html>`
} else if(name == 'main') {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="https://qileshang.top/resources/image/logo2.jpg" type="image/x-icon">
<link rel="stylesheet" href="./${ name }.css">
<title>欢迎使用lia框架</title>
</head>
<body>
<!-- template -->
<div class="${ name }">
<p>main组件</p>
<div class="${ name }-header">
</div>
<div class="${ name }-mainer">
</div>
<div class="${ name }-footer">
</div>
</div>
<!-- template -->
<script src="./${ name }.js" type="module"></script>
</body>
</html>`
} else if(name == 'foot') {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="https://qileshang.top/resources/image/logo2.jpg" type="image/x-icon">
<link rel="stylesheet" href="./${ name }.css">
<title>欢迎使用lia框架</title>
</head>
<body>
<!-- template -->
<div class="${ name }">
<p>foot组件</p>
<div class="${ name }-header">
</div>
<div class="${ name }-mainer">
</div>
<div class="${ name }-footer">
</div>
</div>
<!-- template -->
<script src="./${ name }.js" type="module"></script>
</body>
</html>`
} else {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="https://qileshang.top/resources/image/logo2.jpg" type="image/x-icon">
<link rel="stylesheet" href="./${ name }.css">
<title>欢迎使用lia框架</title>
</head>
<body>
<!-- template -->
<div class="${ name }">
<p>${ name }组件</p>
<div class="${ name }-header">
</div>
<div class="${ name }-mainer">
</div>
<div class="${ name }-footer">
</div>
</div>
<!-- template -->
<script src="./${ name }.js" type="module"></script>
</body>
</html>`
}
} else if(type == 'css') {
//css文件模板
if(name == 'index') {
return `a {
font-size: 16px;
}
span {
font-size: 16px;
}
body {
padding: 0;
margin: 0;
}
.${ name } {
background-color: white;
}`
} else if(name == 'head') {
return `a {
font-size: 16px;
}
span {
font-size: 14px;
}
body {
margin: 0;
padding: 0;
}
.head {
width: 100%;
min-width: 1140px;
background-color: #f6f6f6;
display: grid;
justify-content: space-between;
}
.head .logo {
grid-column: 1;
grid-row: 1 / span 2;
display: flex;
justify-content: center;
align-items: center;
margin-left: 50px;
}
.head .logo img {
width: 100px;
margin-right: 10px;
}
.head .logo .title {
font-size: 24px;
}
.head nav {
width: 480px;
height: 60px;
grid-column: 2;
grid-row: 1;
display: flex;
justify-content: space-between;
align-items: center;
}
.head nav .bt-link{
width: 50px;
height: 35px;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.head nav .bt-link span {
pointer-events: none;
}
.head .search {
width: 480px;
grid-column: 2;
grid-row: 2;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 30px;
}
.head .search input{
width: 480px;
height: 35px;
text-indent: 2em;
box-sizing: border-box;
border: 2px solid #8d8383;
border-radius: 15px;
}
.head .login {
width: 100px;
grid-column: 3;
grid-row: 1 / span 2;
display: flex;
justify-content: center;
align-items: center;
margin-right: 50px;
position: relative;
}
.head .login .box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
position: static;
}
/*.entry-box-more {
width: 80px;
height: 100px;
background-color: #ffffff;
position: fixed;
right: 50px;
top: 200px;
border-radius: 10px;
box-shadow: 0 0 13px 2px #3d3d3d;
cursor: pointer;
}*/
.head .login .box img {
width: 30px;
border: 1px solid #8d8383;
border-radius: 50%;
padding: 5px;
margin-bottom: 15px;
cursor: pointer;
animation: userIamge 2s infinite;
}
userIamge {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`
} else if(name == 'main') {
return `a {
font-size: 16px;
}
span {
font-size: 16px;
}
body {
padding: 0;
margin: 0;
}
.${ name } {
width: 100%;
height: 500px;
background-color: white;
display: flex;
justify-content: center;
align-items: center;
}
.${ name } p {
font-size: 30px;
}`
} else if(name == 'foot') {
return `a {
font-size: 16px;
}
span {
font-size: 16px;
}
body {
padding: 0;
margin: 0;
}
.${ name } {
width: 100%;
height: 120px;
background-color: #f6f6f6;
display: flex;
justify-content: center;
align-items: center;
}
.${ name } p {
font-size: 30px;
}`
} else {
return `a {
font-size: 16px;
}
span {
font-size: 16px;
}
body {
padding: 0;
margin: 0;
}
.${ name } {
width: 100%;
height: 500px;
background-color: white;
display: flex;
justify-content: center;
align-items: center;
}
.${ name } p {
font-size: 30px;
}`
}
} else if(type == 'js') {
//js文件模板
if(name == 'index') {
return `import lia from './lia.js';
import head from './component/head/head.js'
import main from './component/main/main.js'
import foot from './component/foot/foot.js'
const index = {
name: 'index',
data: null,
router: null,
main: function() {
const initObj = {
'.index-header': head,
'.index-mainer': main,
'.index-footer': foot
}
lia.init(initObj);
index_code();
}
}
function index_code() {
}
lia.run(index);
export {
index
}`
} else if(name == 'head') {
return `import lia from '../../lia.js';
import main from '../main/main.js';
import anime from '../anime/anime.js';
import comic from '../comic/comic.js';
import game from '../game/game.js';
import novel from '../novel/novel.js';
import info from '../info/info.js';
const head = {
name: 'head',
data: null,
router: {
'.main_link': {
'.index-mainer': main
},
'.anime_link': {
'.index-mainer': anime
},
'.comic_link': {
'.index-mainer': comic
},
'.novel_link': {
'.index-mainer': novel
},
'.game_link': {
'.index-mainer': game
},
'.info_link': {
'.index-mainer': info
}
},
main: function() {
head_code();
}
}
function head_code() {
}
//单独运行组件
lia.run(head);
export default head;`;
} else if(name == 'lia') {
return `//此处组件的概念:
//这里的组件指的是一个包含了html、css和js三类文件的组合体,它的表象是一个里面有着html、css和js这三类文件并与三者同名的文件
//比如:有一个名为head的文件夹,该文件夹里面有head.html文件、head.css文件以及head.js文件,这些组合起来称之为head组件
import events from "./event.js";
let bindModelViewObj = {};
let bindViewModelObj = {
value: [],
textarea: []
};
let proxyObj = {};
const lia = {
//注册事件,删除事件----这样应该可以减少各组件之间的依赖,确保的它们独立性!!!
//注销事件函数
//遍历所有注册过的事件,并将之注销
unregister: function (entryClassName) {
lia.traverse(events.index, entryClassName);
},
traverse: function (obj, entryClassName = null) {
//console.log(obj);
if(entryClassName != null) {
if(obj.el == entryClassName) {
document.removeEventListener('scroll', obj.events[0]);
if(obj.childs != null) {
for(let i in obj.childs) {
lia.traverse(obj.childs[i]);
}
}
} else {
if(obj.childs != null) {
for(let i in obj.childs) {
lia.traverse(obj.childs[i], entryClassName);
}
}
}
} else {
document.removeEventListener('scroll', obj.events[0]);
if(obj.childs != null) {
for(let i in obj.childs) {
lia.traverse(obj.childs[i]);
}
}
}
},
//el对象
//el全称是element,即元素
//通过el()方法可以获取到一个跟DOM元素相关的对象,该对象包含了很多实现DOM操作的属性,这些属性的值本质上是封装了DOM操作的函数
el: function (ClassName) {
return {
backgroundColor: function(value) {
document.querySelector(ClassName).style.backgroundColor = value;
},
color: function(value) {
document.querySelector(ClassName).style.color = value;
},
width: function(value) {
document.querySelector(ClassName).style.width = value;
},
height: function(value) {
document.querySelector(ClassName).style.height = value;
},
display: function(value) {
document.querySelector(ClassName).style.display = value;
},
visibility: function(value) {
document.querySelector(ClassName).style.visibility = value;
},
value: function(value) {
document.querySelector(ClassName).value = value;
},
get: function() {
return document.querySelector(ClassName);
}
};
},
//ajax函数
//对原生ajax的简单封装
ajax: function (method, url, callback, asc) {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) { //这一步很重要,不能省略
callback(this.response);
}
}
xhr.open(method, url, asc);
xhr.send();
},
//组件配置函数component()
//通过该函数可以实现在任意位置添加组件
component: function (entryClassName, componentName, componentJs, routerObj, dpath = './component/') {
let url = dpath + componentName + '/' + componentName +'.html';
lia.ajax('GET', url, function(response) {
//第一步:添加html模板
const template = response.split('<!-- template -->')[1];
document.querySelector(entryClassName).innerHTML = template;
//第二步:添加css样式
//实现了entryClassName当前位置对应的样式link元素的切换
//也就是entryClassName当前位置添加了哪个组件就切换使用那个组件的样式
let previous_link = document.querySelector('[data-sign="l' + entryClassName + '"]');
if(!previous_link) {
//如果entryClassName对应的样式link元素未存在,则在下面创建link元素并添加到html文档的head里面
let link = document.createElement('link');
link.rel = 'stylesheet'
link.href = dpath + componentName + '/' + componentName + '.css';
link.type = 'text/css'
link.dataset.sign = 'l' + entryClassName;
document.head.appendChild(link);
} else {
//如果entryClassName对应的样式link元素已存在,则先删除原来的link元素,再创建新的link元素并添加到html文档的head里面
previous_link .remove();
let link = document.createElement('link');
link.rel = 'stylesheet'
link.href = dpath + componentName + '/' + componentName + '.css';
link.type = 'text/css'
link.dataset.sign = 'l' + entryClassName;
document.head.appendChild(link);
}
}, false);
//第三步:添加js脚本
//componentJs()是当前组件对应的方法,基本包含了该组件的脚本内容实现
//这里设置componentJs()相当于为html文档添加了js文件,只是与设置script元素形式上不同,但内容实现是一样的
componentJs();
//如果routerObj存在,那就意味着不仅为entryClassName对应位置添加组件,同时还为该组件设置路由
if(routerObj) {
lia.router(routerObj, dpath);
}
},
//页面初始配置函数init()
//该函数是用来在index.html文件中相应的位置添加组件
//initOb为页面初始配置对象
init: function (initObj, dpath) {
//console.log(obj);
for(const entryClassName in initObj) {
const componentName = initObj[entryClassName].name;
const componentJs = initObj[entryClassName].main;
const routerObj = initObj[entryClassName].router;
lia.component(entryClassName, componentName, componentJs, routerObj, dpath);
}
},
//路由配置函数router()
//该函数是用来为当前组件设置路由用的
//routerObj路由配置对象
router: function (routerObj, dpath) {
for(const linkClassName in routerObj) {
for(const entryClassName in routerObj[linkClassName]) {
if(document.querySelector(entryClassName)) {
const componentName = routerObj[linkClassName][entryClassName].name;
const componentJs = routerObj[linkClassName][entryClassName].main;
const next_routerObj = routerObj[linkClassName][entryClassName].router;
document.querySelector(linkClassName).addEventListener('click', function() {
lia.unregister(entryClassName);
setTimeout(function() {
document.documentElement.scrollTop = 0;
lia.component(entryClassName, componentName, componentJs, next_routerObj, dpath);
}, 100);
});
}
}
}
},
//后面的待完善
//数据渲染视图
record: function (obj) {
for(let key in obj) {
bindModelViewObj[key]=[];
}
},
//单向数据绑定
bindModelView: function (domName, type, property) {
if(document.querySelector(domName) && (typeof lia.getProxy()) != 'undefined') {
if(type == 'backgroundColor') {
//console.log('ok');
document.querySelector(domName).style.backgroundColor = lia.getProxy()[property];
}else if(type == 'color') {
//document.querySelector(domName).style.color = lia.getProxy()[property];
} else if(type == 'width') {
document.querySelector(domName).style.width = lia.getProxy()[property];
} else if(type == 'height') {
document.querySelector(domName).style.height = lia.getProxy()[property];
} else if(type == 'display') {
document.querySelector(domName).style.display = lia.getProxy()[property];
} else if(type == 'visibility') {
document.querySelector(domName).style.visibility = lia.getProxy()[property];
} else if(type == 'input') {
document.querySelector(domName).value = lia.getProxy()[property];
} else {
document.querySelector(domName).setAttribute(type, lia.getProxy()[property]);
}
} else {
if(typeof bindModelViewObj[property] != 'undefined') {
bindModelViewObj[property].push([domName, type]);
}
}
},
achieveModelToView: function (target, key) {
for(const property in bindModelViewObj) {
//遍历原始数据对象,完成初始化页面数据的渲染
if(!key) {
for(let i = 0; i < bindModelViewObj[property].length; i++) {
let [domName, type] = bindModelViewObj[property][i];
if(type == 'backgroundColor') {
lia.el(domName).backgroundColor(target[property]);
} else if(type == 'color') {
lia.el(domName).color(target[property]);
} else if(type == 'width') {
lia.el(domName).width(target[property]);
} else if(type == 'height') {
lia.el(domName).height(target[property]);
} else if(type == 'display') {
lia.el(domName).display(target[property]);
} else if(type == 'visibility') {
lia.el(domName).visibility(target[property]);
} else if(type == 'input') {
lia.el(domName).value(target[property]);
} else {
document.querySelector(domName).setAttribute(type, target[property]);
}
}
}
//侦听数据变化,并重新渲染页面
if(property == key) {
for(let i = 0; i < bindModelViewObj[property].length; i++) {
let [domName, type] = bindModelViewObj[property][i];
if(type == 'backgroundColor') {
document.querySelector(domName).style.backgroundColor = target[key];
} else if(type == 'color') {
document.querySelector(domName).style.color = target[key];
} else if(type == 'width') {
document.querySelector(domName).style.width = target[key];
} else if(type == 'height') {
document.querySelector(domName).style.height = target[key];
} else if(type == 'display') {
document.querySelector(domName).style.display = target[key];
} else if(type == 'visibility') {
document.querySelector(domName).style.visibility = target[key];
} else if(type == 'input') {
document.querySelector(domName).value = target[key];
} else {
document.querySelector(domName).setAttribute(type, target[key]);
}
}
}
}
},
//视图更新数据
//单向数据绑定
bindViewModel: function (domName, type, property) {
if(type == 'value') {
bindViewModelObj.value.push([domName, property]);
} else if(type == 'textarea') {
bindViewModelObj.textarea.push([domName, property]);
}
},
achieveViewToModel: function (proxy) {
for(const i in bindViewModelObj) {
if(bindViewModelObj[i].length != 0) {
if(i == 'value') {
for(let j = 0; j < bindViewModelObj[i].length; j++) {
let [domName, property] = bindViewModelObj[i][j];
document.querySelector(domName).addEventListener('keyup', function() {
proxy[property] = document.querySelector(domName).value;
});
}
}
}
}
},
//双向数据绑定
bind: function (domName, type, property) {
//下面两者结合相当于双向数据绑定
lia.bindModelView(domName, type, property);
lia.bindViewModel(domName, type, property);
},
ref: function (obj) {
let o = new Object();
o.runs = function() {
lia.achieveModelToView(obj);
const proxy = new Proxy(obj, {
set(trapTarget, key, value, receiver) {
const result = Reflect.set(...arguments);
lia.achieveModelToView(receiver, key);
return result;
}
});
}
},
//使用代理实现数据绑定的效果
proxyFun: function (target) {
//页面初始化时触发
lia.achieveModelToView(target);
const proxy = new Proxy(target, {
set(trapTarget, key, value, receiver) {
const result = Reflect.set(...arguments);
//更改数据时触发
lia.achieveModelToView(receiver, key);
return result;
}
});
lia.achieveViewToModel(proxy);
proxyObj.proxy = proxy;
},
getProxy: function () {
return proxyObj.proxy;
},
//组件运行函数
run: function (componentObj) {
if(document.querySelector('.' + componentObj.name)) {
if(componentObj.data != null) {
//记录原始数据对象
lia.record(componentObj.data);
}
if(componentObj.router != null) {
//配置路由功能
lia.router(componentObj.router, '../');
}
componentObj.main('../');
if(componentObj.data != null) {
//实例化响应数据
lia.proxyFun(componentObj.data);
}
}
}
}
export default lia;`
} else if(name == 'event') {
return `//事件处理机制————现在感觉很完美
let indexObj = {
index: {
el: null,
events: [],
childs: {
head: {
el: '.index-header',
events: [],
chils: null
},
main: {
el: '.index-mainer',
events: [],
childs: null
},
anime: {
el: '.index-mainer',
events: [],
childs: null
},
comic: {
el: '.index-mainer',
events: [],
childs: null
},
novel: {
el: '.index-mainer',
events: [],
childs: null
},
game: {
el: '.index-mainer',
events: [],
childs: null
},
info: {
el: '.index-mainer',
events: [],
childs: null
},
foot: {
el: '.index-mainer',
events: [],
childs: null
}
}
}
};
const events = new Proxy(indexObj, {
get(target, key) {
return Reflect.get(...arguments);
},
set(target, key, value) {
return Reflect.set(...arguments);
}
});
export default events;`;
} else {
return `import lia from '../../lia.js';
const ${ name } = {
name: '${ name }',
data: null,
router: null,
main: function() {
${ name }_code();
}
}
function ${ name }_code() {
}
//单独运行组件
lia.run(${ name });
export default ${ name };`
}
}
}
module.exports = {
init: init
}