Open easonyq opened 6 years ago
对于4个问题
如果页面不包含
<mip-content>
,则<body>
下的所有除<script>
之外的节点全部认为属于<mip-content>
下。
我想表达的意思和你是相同的,但漏写了除 <mip-shell>
,已经补充。
我当时的考虑是不论在哪个环境,都出相同的 AppShell。但现在看来直接访问用户站点,可以根据用户的情况出不同的 Shell是一种功能,那补充一下设计:
开发者如果要实现在直接打开时和搜索时两种情况出不同的 AppShell,可以采用 use
属性进行标识。如下:
<mip-shell id="title" use="search">{{ titleText }}</mip-shell>
<mip-shell id="title" use="standalone">{{ anotherTitleText }}</mip-shell>
通过使用相同的 id
和不用的 use
来实现两者的差别和替换。如果开发者在直接打开时不需要这个 Shell,也可以不写第二句。默认情况下不使用 use
属性的即认为两种情况都有且内容相同。
回到问题 2,这样的补充设计我想应该也是支持多个 Shell 的。支持多个的原因主要在于 position
属性,因为根据不同的 position
在退场时采取不同的方向,比起简单的 fade 看上去更加好看和合理一些。
这个提议非常好。至于在内存中存储多少个 Page,我也没有经验。先暂定一个数字,以观后效。
这个问题就是我最后列出的存疑点。我的想法如下:
因为 Shell 和 Content 挂载点不同,因此萌生了多个 Mip 实例的想法。但开发者编写时是写在一起,并且 data 只有一份,且 vue-router 是只有一个实例的,因此这个方案应该不现实。
既然仍然是一个实例,那么挂载点只能在 <mip-content>
,那就会导致 AppShell 也一起被挂到内容里面,还需要额外用 js 把它取出来,这个做法太 LOW 且不确定是否有闪动的可能性。我就比较好奇 Vue 是如何完成既渲染 <router-view>
的节点,又能渲染 <router-view>
平级的 Shell 节点,且都在同一个实例中。这个我会继续研究。
组件能不能访问 this.$router this.$routes 等对象?
@clark-t 能,功能设计第二点
为每个页面提供当前路由信息,如当前 URL、参数、域名、hash 等等
就是这个。我会把 route 信息放到 Mip.prototype
上就可以使用了
App shell设计和搜索侧的是否能兼容,否则后续在搜索侧以及站点单独打开时技术能力表现会不一致。
App Shell 和之前讨论的设计方式一致,搜索侧用另外的 App Shell 组件替代渲染
当前站点希望流畅切换到下一个站点,这里是不是得考虑Iframe方案?或者说我们体验上就是要跳转。
另外,如果是集成熊掌号的登录和支付相关的能力,也不能是当前上下文渲染吧?
切换到不同站点会直接跳出,不会用 iframe 包裹起来
这个很有可能是需求,能满足吗?如果不能,我理解可能需要重新考虑设计。 @PengXing @windtalkers
我不建议把mip-shell作为core的一部分,集成到mip的核心代码里面,本质上,mip-shell还是一个组件,router是实现组件用的一个库,我们这里需要首先讨论清楚并达成一致的是:
我们的设计是一个shell需要考虑哪些东西?
这些东西在shell里面怎么DSL抽象?
用户怎么使用这些DSL抽象进行定制shell功能?
@windtalkers 我们也同意 mip-shell 是一个组件。但目前它是 mip-router 会用到的组件,虽然和内置组件(mip-img 等等)实现上略有不同,但最终也是打包到 mip.js 里面。我想我们分歧的点应该在于 mip-shell 的代码应不应该打包到 mip.js 里面 对吗?
关于设计思路方面,我们最终方案是让用户去选择预先提供的几种 Shell 的一种,然后提供需要的内容(例如通过 slot 之类的机制提供模板,并提供初始数据)。MIP 把它当成是个普通组件进行渲染,进行进场退场动画的注册和进行。通过 store 进行数据的管理,Shell 的显示由 store 里面某些数据的变化而变化。
设计思路我觉得没有问题,我关注的点是mip-shell这个组件的dsl设计,我们的重点是怎么设计mip-shell。那么我这里为什么坚持shell是一个组件的重要原因就是,shell的dsl是规范固定的,那么,基于这个DSL,搜索结果页和全站mip的情况,就可以做不通的处理。
mip-router 设计方案
mip-router 用来处理多个 MIP 页面间的跳转,主要功能包括:
mip-router 其实是一段 JS。鉴于 MIP 2.0 必然依赖 mip-router 和 mip,因此 mip-router 的代码就直接包含在 mip.js 内部,不再额外独立成单独的文件了。
SPA 融合方案
mip-router 的核心之一是将多个单独的 MIP 页面融合为 SPA。实现方案如下:
准备工作
mip-router 要求页面以一定的结构使用两个标签
<mip-content>
和<mip-shell>
。<mip-content>
一般位于<body>
的一个子节点,用以标识哪一段是页面的主体内容,区别于其他内容(如 AppShell,script 引用等等)。<mip-shell>
和 AppShell 的实现有关,将在后面详述。举例来说,一个可能的页面结构是:
<mip-content>
只能存在一个,<mip-shell>
可以存在多个。如果页面不包含<mip-content>
,则<body>
下的所有除<mip-shell>
和<script>
之外的节点全部认为属于<mip-content>
下。首次打开时
<style mip-custom>
和尾部的几个<script>
标签保留,维持原状。<mip-shell>
和<mip-content>
里的内容,传递给 Mip 构造函数(由 mip-core 提供)syncData
方法之后的模板,我们称之为中间模板mount
方法进行挂载。挂载点可以设置在原<mip-content>
,则将内部的原始模板清空;也可以在其平级创建一个新的挂载点,同时将<mip-content>
节点删除。后续跳转页面
如果跳转到站外,则使用
<a>
标签,和普通站点一样跳转。如果跳转到站内,则使用
<router-link>
标签,mip-router 的操作步骤如下:<style mip-custom>
的内容,替换当前页面的同名标签<body>
底部的<script>
标签,和当前页面的同名标签进行比较:相同的保留;不同的替换。<mip-shell>
和<mip-content>
里的内容,传递给compile
函数(由 mip-core 提供)mount
方法进行挂载。这里为了过场动画(默认右向左滑动),需要在右侧重新建立一个容器作为新的挂载点如果是前进/后退,基本过程类似,从数组中找到上一个页面的 URL,并执行跳转站内的逻辑。略有不同的点在于:
AppShell 的支持
AppShell 不是 mip-router 的一部分,但是它的支持方案和 mip-router 息息相关。
第一版
考虑到排期压力,第一版规定每个页面都有一个固定的 AppShell,即头部标题栏。
因此在每个页面的
<body>
中,都应该拥有这样一个标签:其中
id
属性是必填项,用以区分 AppShell。{{ titleText }} 用以将标题内容绑定到一个变量上,仅为示例,以实际实现为准。不论是首次打开还是切换页面,mip-router 会获取当前/目标页面的
<mip-shell>
的内容并传递给 mip-core 进行解析。挂载之后再将其移动到挂载点外的平级。(这里应该有更好的做法,既渲染 shell 内容,又不至于让 shell 一开始被挂载到 content 的内部)由于
<mip-shell>
和挂载点平级,因此可以脱离过场动画之外。完整方案(草案)
<mip-shell>
的id
属性是相同的。如果不同,那么 AppShell 一样将被退场。<mip-shell position="bottom">
。开发者如果要实现在直接打开时和搜索时两种情况出不同的 AppShell,可以采用
use
属性进行标识。如下:通过使用相同的
id
和不用的use
来实现两者的差别和替换。如果开发者在直接打开时不需要这个 Shell,也可以不写第二句。默认情况下不使用use
属性的即认为两种情况都有且内容相同。<mip-shell>
目前拥有的属性集合:'search/standalone'
。用以标识 AppShell 在哪种访问模式下展现。不填写时表示两种模式都展现。id
和use
两者的组合必须唯一'top/bottom/left/right'
。用以标识 AppShell 在页面上的位置,从而在进场/退场时执行对应方向的动画。如取值为top
的进场时从上到下;退场时从下到上。不填写时使用 fade 进行动画。和 mip-core 的交互
compile
,用以后续跳转链接时传入新的模板。注意这里并不创建新的实例,而是全局只有一个 mip 实例router
对象并实时更新,使它们能够获取当前 URL 信息存疑
<router-view>
平级的 shell