前言

目前流行的前端UI组件库都支持移动设备优先的响应式布局特性。但基于Mobile和PC两个场景的不同用户体验,也往往会实现Mobile和PC两个版本。

PC场景下的Web工程,如大量的后台前端管理模版,虽然支持Mobile自适应,但其用户体验差强人意。

Cabloy采用不同的思路,仍然基于移动优先,同时通过特殊的布局优化,使得移动页面可以完整的用于PC场景,既保证了用户体验,又提升了开发效率,大大简化了开发工作量。

演示

上图

Mobile布局

PC布局

进一步分析

Cabloy的PC布局将页面切分为若干个Mobile+Pad的组合,带来了与众不同的用户体验。

从此开发类似于微信公众号H5混合开发的项目,再也不用建立两套独立的工程。

内部机制

Cabloy前端基于Framework7,并一直跟进其最近的开发进度,从1.0到2.0,再到3.0。Cabloy充分利用了Framework7的优良特性,充分发挥其最大价值。

Cabloy的作者zhennannFramework7的贡献图如下:

Framework7将页面分为若干个View,每个View对应一个Router,管理若干个Page,从而非常方便的实现Page之间的堆叠。

Cabloy的PC布局,将页面分为若干个Tab,每个Tab再包含若干个View。通过对Router的patch,实现Tab之间与View之间的URL跳转。

代码实现

根结点组件

Cabloy通过不同的模块封装不同布局的实现逻辑,然后在根结点组件中针对页面的尺寸的变化渲染不同的布局。

需要特别说明的是,Cabloy中的模块是一个相对独立的实体,可以根据需要异步加载,提升页面加载性能。

egg-born-front/src/base/mixin/config.js:

config.js配置布局信息,可通过修改配置实现自己的布局管理逻辑

// config
const config = {
modules: {},
layout: {
breakpoint: 800,
items: {
mobile: {
module: 'a-layoutmobile',
component: 'layout',
},
pc: {
module: 'a-layoutpc',
component: 'layout',
},
},
},
};

egg-born-front/src/inject/pages/app.vue:

app.vue是根结点组件,动态异步加载所需的布局组件

<script>
import Vue from 'vue';
export default {
render(c) {
const children = [];
// statusbar
children.push(c('f7-statusbar', { ref: 'statusbar' }));
// layout
if (this.layout) {
children.push(c(this.layout, {
ref: 'layout',
}));
}
const app = c('f7-app', { props: { params: this.$root.$options.framework7 } }, children);
return c('div', [ app ]);
},
data() {
return {
layout: null,
};
},
methods: {
ready() {
if (this.$f7.device.ie) {
this.$f7.dialog.alert('Supports All Modern Browsers Except IE');
return;
}
// check query
const documentUrl = location.href.split(location.origin)[1];
if (documentUrl && documentUrl.indexOf('/?') === 0) {
history.replaceState(null, '', location.origin);
}
// hash init
const hashInit = this.$meta.util.parseHash(location.href);
if (hashInit && hashInit !== '/') this.$store.commit('auth/setHashInit', hashInit);
// on resize
this.$f7.on('resize', this.onResize);
// auth echo first
this._authEcho(() => {
// resize
this.resize();
});
},
getLayout() {
return this.$refs.layout;
},
resize() {
// layout
const breakpoint = this.$meta.config.layout.breakpoint;
let layout = window.document.documentElement.clientWidth > breakpoint ? 'pc' : 'mobile';
if (!this.$meta.config.layout.items[layout]) {
layout = layout === 'pc' ? 'mobile' : 'pc';
}
// check if switch
if (this.layout === layout) {
const component = this.getLayout();
if (component) component.onResize();
} else {
// load module layout
this.$meta.module.use(this.$meta.config.layout.items[layout].module, module => {
this.$options.components[layout] = module.options.components[this.$meta.config.layout.items[layout].component];
// clear router history
this.$meta.util.clearRouterHistory();
// ready
this.layout = layout;
});
}
},
reload(ops) {
ops = ops || { echo: false };
if (ops.echo) {
this._authEcho(() => {
this._reloadLayout();
});
} else {
this._reloadLayout();
}
},
onResize: Vue.prototype.$meta.util.debounce(function() {
this.resize();
}, 300),
login(url) {
const hashInit = this.$store.state.auth.hashInit;
this.$store.commit('auth/setHashInit', null);
url = `${url}?returnTo=${encodeURIComponent(this.$meta.util.combineHash(hashInit))}`;
location.assign(url);
},
_authEcho(cb) {
// get auth first
this.$api.post('/a/base/auth/echo').then(user => {
this.$store.commit('auth/login', {
loggedIn: user.agent.anonymous === 0,
user,
});
return cb && cb();
}).catch(() => {
return cb && cb();
});
},
_reloadLayout() {
const layout = this.layout;
this.layout = null;
this.$nextTick(() => {
// clear router history
this.$meta.util.clearRouterHistory();
// restore layout
this.layout = layout;
});
},
},
beforeDestroy() {
this.$f7.off('resize', this.onResize);
},
mounted() {
this.$f7ready(() => {
this.ready();
});
},
};
</script>

Mobile布局组件

Mobile布局组件源码参见:https://github.com/zhennann/egg-born-module-a-layoutmobile/blob/master/front/src/components/layout.vue

a-layoutmobile/front/src/config/config.js:

config.js可以灵活配置布局的显示元素

export default {
layout: {
login: '/a/login/login',
loginOnStart: true,
toolbar: {
tabbar: true, labels: true, bottomMd: true,
},
tabs: [
{ name: 'Home', tabLinkActive: true, iconMaterial: 'home', url: '/a/base/menu/list' },
{ name: 'Atom', tabLinkActive: false, iconMaterial: 'group_work', url: '/a/base/atom/list' },
{ name: 'Mine', tabLinkActive: false, iconMaterial: 'person', url: '/a/user/user/mine' },
],
},
};

PC布局组件

Mobile布局组件源码参见:https://github.com/zhennann/egg-born-module-a-layoutpc/blob/master/front/src/components/layout.vue

a-layoutpc/front/src/config/config.js:

config.js可以灵活配置布局的显示元素

export default {
layout: {
login: '/a/login/login',
loginOnStart: true,
header: {
buttons: [
{ name: 'Home', iconMaterial: 'dashboard', url: '/a/base/menu/list', target: '_dashboard' },
{ name: 'Atom', iconMaterial: 'group_work', url: '/a/base/atom/list' },
],
mine:
{ name: 'Mine', iconMaterial: 'person', url: '/a/user/user/mine' },
},
size: {
small: 320,
top: 60,
spacing: 10,
},
},
};

结语

Cabloy是采用Javascript进行全栈开发的最佳实践。

Cabloy不重复造轮子,而是采用业界最新的开源技术,进行全栈开发的最佳组合。

欢迎大家拍砖、踩踏。

地址:https://github.com/zhennann/cabloy

Cabloy全栈JS框架微创新之一:不一样的“移动优先 PC适配”的更多相关文章

  1. 全栈式框架的选择:MEAN or MEANS?

    说明:个人博客地址为edwardesire.com,欢迎前来品尝.本博客作为备份和引流 这两个月一直在进行sails后端开发,其中遇到的问题不断.放在研究用户访问控制矸例程上的时间太多,最后也没用弄出 ...

  2. 前端面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    写在前面 参考答案及资源在看云平台发布,如果大家想领取资源以及查看答案,可直接前去购买.一次购买永久可看,文档长期更新!有什么意见与建议欢迎您及时联系作者或留言回复! 文档描述 本文是关注微信小程序的 ...

  3. 一个小时搭建一个全栈 Web 应用框架

    把想法变为现实的能力是空想家与实干家的区别.不管你是在一家跨国公司工作,还是正在为自己的创业公司而努力,那些有能力将创意转化为真正产品的人,都具有宝贵的技能并拥有明显的实力.如果你能在不到一个小时的时 ...

  4. 一名全栈工程师Node.js之路-转

    Node.js 全球现状 虽然 Node.js 在国内没有盛行,但据 StackOverflow 2016 年开发者调查,其中 node.js .全栈.JavaScript 相关的技术在多个领域(包括 ...

  5. Node.js 全栈开发(一)——Web 开发技术演化

    这些年一直不断接触学习 Node 技术栈,个人的技术开发学习兴趣也越来越倾向 node 流.也许是由于英语的关系,也许是因为墙增加了学习国外一手资料的难度,加上现在流行的 web 开发技术并不太容易上 ...

  6. Node.js 中开源库探秘 object-assign | 全栈之路

    这篇内容呢,讲的是另一个技术栈 Node.js 系列,虽然和咱们这里的主题不是特别吻合,不过嘛,汲取多样性的养分是快速成长的好方法,也是现在流行的全栈工程师的必经之路. 由于这篇内容涉及的是 Node ...

  7. 使用 Flask 和 Vue.js 来构建全栈单页应用

    在这个教程中,我将向你展示如何将 Vue 的单页面应用和 Flask 后端连接起来. 简单的来说,如果想在 Flask 中使用 Vue 框架是没有什么问题的. 但在实际中存在一个明显的问题就是 Fla ...

  8. 且看这个Node全栈框架,实现了个Cli终端引擎,可无限扩充命令集

    背景介绍 一般而言,大多数框架都会提供Cli终端工具,用于通过命令行执行一些工具类脚本 CabloyJS提供的Cli终端工具却与众不同.更确切的说,CabloyJS提供的是Cli终端引擎,由一套Cli ...

  9. 分享一款自带工作流引擎的NodeJS全栈框架,接单快手、创业神器

    CabloyJS是什么 CabloyJS是一款自带工作流引擎的Node.js全栈框架, 接单快手.创业神器, 基于koa + egg + vue + framework7 + mysql 在线演示 场 ...

随机推荐

  1. PHP 数组转字符串后仍保留数组格式

    写此方法的目的是,我想把一个PHP数组配置文件读进程序,添加些配置,然后在写入文件: var_export 方法会把原来的配置打乱(比如数组序号我没有加,他自动给我加上 0,1,2,3...),而且格 ...

  2. Mybatis mapper动态代理的原理详解

    在开始动态代理的原理讲解以前,我们先看一下集成mybatis以后dao层不使用动态代理以及使用动态代理的两种实现方式,通过对比我们自己实现dao层接口以及mybatis动态代理可以更加直观的展现出my ...

  3. 写论文的第四天 Spark安装 使用sparkshell

    Spark分布式安装 Spark安装注意:需要和本机的hadoop版本对应 前往spark选择自己相对应的版本下载之后进行解压 命令:tar –zxf spark-2.4.0-bin-hadoop2. ...

  4. ZooKeeper 相关概念以及使用小结

    Dubbo 通过注册中心在分布式环境中实现服务的注册与发现,而注册中心通常采用 ZooKeeper,研究注册中心相关源码绕不开 ZooKeeper,所以学习了 ZooKeeper 的基本概念以及相关 ...

  5. idea设置docker远程插件

    简介 docker都是通过命令来操作容器,使用idea插件可以减少重复命令输入等. 使用步骤 Idea内安装插件 打开Idea,Preferences | Plugins 进入插件安装界面,在搜索框中 ...

  6. HTML的发展及认识

    首先HTML全称是Hypertext Markup Language,它是一门超文本标记语言: HTML已经有了HTML2.0.HTML3.2.HTML 4.0. HTML4.01. HTML5几个阶 ...

  7. 图解Java数据结构之队列

    本篇文章,将对队列进行一个深入的解析. 使用场景 队列在日常生活中十分常见,例如:银行排队办理业务.食堂排队打饭等等,这些都是队列的应用.那么队列有什么特点呢? 我们知道排队的原则就是先来后到,排在前 ...

  8. js中的数据类型,以及如何检测数据类型

    基本数据类型:string,number,boolean,null,undefined,symbol 引用数据类型:object(array,function...) 常用的检测数据类型的方法一般有以 ...

  9. Spring入门(十一):Spring AOP使用进阶

    在上篇博客中,我们了解了什么是AOP以及在Spring中如何使用AOP,本篇博客继续深入讲解下AOP的高级用法. 1. 声明带参数的切点 假设我们有一个接口CompactDisc和它的实现类Blank ...

  10. #第 12 篇:解锁博客侧栏,GoGoGo!

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 我们的博客侧边栏有四项内容:最新文章.归档.分类和标签云.这些内容相对比较固定和独立, ...