Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android : 使用 vue-router ,带有 position: fixed 属性的 dom 不会消失 #2310

Closed
vfasky opened this issue Jan 18, 2017 · 25 comments
Closed

Comments

@vfasky
Copy link

vfasky commented Jan 18, 2017

例如,有二个 view: home.vue, user.vue

home.vue 中的 div.test 使用了 position: fixed
跳转到 user.vue , home.vue 中的 div.test 仍会出现

weex-sdk version = "0.9.4"

@Hanks10100
Copy link
Member

0.9.4 版本还不支持用 Vue ,从 0.9.5 开始支持的。

@vfasky
Copy link
Author

vfasky commented Jan 18, 2017

https://github.com/alibaba/weex/blob/dev/android/sdk/build.gradle#L51
官方这里,最新的,还是 0.9.4 啊
而且,代码是能跑起来的,只是那个元素一直在啊

@Hanks10100
Copy link
Member

可能是代码里的版本号未及时改掉,建议使用我们发布的 SDK 写页面。

你是怎么用的 vue-router ,有例子吗?

@vfasky
Copy link
Author

vfasky commented Jan 18, 2017

用这里的代码 https://github.com/weexteam/weex-hackernews
随便在 views 里加一个元素 ,让 css position: fixed , 都可以重现

@Hanks10100
Copy link
Member

position: fixed 就是让组件显示在固定位置的,如果使用 router ,“页面跳转”仍然是在同一个页面(instance)之内的,所以通过 router 跳转后, fixed 的组件还是会显示在原位置。

@dongnaebi
Copy link

也就是说vue-router在原生中的跳转只相当于浏览器中改变hash,要做到原生示例跳转并有跳转动画,只能再新建一个router-view,并像老版本一样编译出多个js文件?

web端也要建立相应的页面或者用xhr来引用并渲染不同的js,vue-router只起到相当于切换选项卡的作用?如果这样的话,使用vue-router的性价比就太低了。相当于一个应用要弄两套路由,第一层是页面间跳转,第二层是页面内(选项卡)跳转。然而用到选项卡的页面少之又少,vue-router大材小用

能否在native端实现this.$router.push()跳转的时候切换实例,并可以选择跳转动画?当然也可以由开发者选择性的使用。这样做的好处是:

  1. 一个应用只用编译出一个js,切换页面更快,如果文件过大可以使用懒加载。客户端校验最新版更易实现
  2. 可以使用成熟的vue-router作为整个应用的路由
  3. 在web端还可以配置使用History API,从而实现SEO优化

@Hanks10100 @Jinjiang

@Hanks10100
Copy link
Member

@dongnaebi 就 vue-router 而言,是这样。因为 vue-router 的设计和实现都是在同一个页面内的,是 SPA 概念里的产物。其实前端路由也是基于 SPA 产生的概念,在 Weex 或者原生应用这种多页跳转的场景里可能并不合适,至少不能拿来就用。

我们现在也在构思实现原生页面跳转的“路由”方案,不过客户端上的页面不一定都是 Weex 写的,如何实现从 Weex 页面跳的其他原生页面,或者 web 页面也是得考虑的。即使只考虑 Weex 页面之间的跳转,因为 Weex 现在支持 Vue 、 Rax 以及旧版前端框架,不同框架语法、数据格式不一样,如何支持不同框架的页面之间互相跳转也是个问题。

this.$router.push 这种方式是 vue-router 里的,依赖 this ,路由功能也与自身页面里 DSL 的写法有关,如果要想在多框架之间跳转,应该将路由设计成独立的模块,但是我们已经有了 navigator 模块。

@dongnaebi
Copy link

好吧,我搞错方向了。本来今颠高高兴兴,撸了两三天的vux+vue-router,又要重新架构了。。。

@vfasky
Copy link
Author

vfasky commented Jan 22, 2017

不做SPA, 那用 vuex 的意义就不是很大了。想想 vuex 解决的痛点。

另外,我们发现安卓的 position sticky 是工作的,于是,有了这个临时的方案:

创建一个 最小高度等于屏幕高度的主内容容器,然后将需要要 fixed 的元素全部放它下面。
理由:让 sticky 生效了,其实就是 fixed

@vfasky
Copy link
Author

vfasky commented Jan 22, 2017

抱歉,几位,chrome 还不支持 sticky 。
最后,我们发现了

https://github.com/weexteam/weex-components/blob/master/src/wxc-tabbar.we

参考了思路,用 absolute

@Hanks10100
Copy link
Member

@vfasky 即使不建议 spa ,也会有 vuex 之类的状态管理的功能的,不过会设计的更通用一些,不基于某个内置前端框架。参考 #1938

@vfasky
Copy link
Author

vfasky commented Jan 23, 2017

@Hanks10100 https://market.weex-project.io/#9 这个项目不是官方的?

@Hanks10100
Copy link
Member

@vfasky 是我们团队人写的 https://github.com/zhangquan/weex-router ,不过只支持原有 .we 的语法,基于 navigator 模块封装的语法糖。

@vfasky
Copy link
Author

vfasky commented Jan 23, 2017

@Hanks10100 如果我没看错的话, https://github.com/zhangquan/weex-router/blob/master/js/js/navigator.js 用的并不是 navigator 模块

@dongnaebi
Copy link

@Hanks10100 有个疑问还望解答一下,现在我是这样理解架构的:

我在src目录下写了 home.vuelist.vue 文件,如果用weex-vue-rander来渲染,那必须还要建对应的home.jslist.js来初始化:

//home.js
import home from './home.vue'
home.el = '#root'
export default new Vue(home )
//list.js
import list from './list.vue'
list.el = '#root'
export default new Vue(list )

各自编译成index.web.jslist.web.js,在index.html通过url参数判断加载对应的js。

但是这样有点麻烦,最主要是还要新建组件(页面)对应的js?有没有更好的办法?

@vfasky 你呢?你是怎么做的

@vfasky
Copy link
Author

vfasky commented Feb 7, 2017

我们现在的解决方法比较奇怪。
1, web 用 vue-router 跳转
2, iOS , android 用 navigator (这样,原生的后退就能用)

我贴一下关键代码

入口代码

if (WXEnvironment.platform !== 'Web') {
    let bundleUrl = String(weex.config.bundleUrl)
    if (bundleUrl.indexOf('#') === -1) {
        router.push('/')
    } else {
        let baseUrl = String(weex.config.bundleUrl).split('#').pop()
        router.push(baseUrl)
    }
}

vue 中的跳转代码

const navigator = weex.requireModule('navigator')
export default {
    methods: {
        goTo (url: string) {
            if (WXEnvironment.platform === 'Web' && this.$router) {
                this.$router.push(url)
            } else {
                let baseUrl = String(weex.config.bundleUrl).split('#').shift()
                let bundleUrl = baseUrl + '#' + url
                navigator.push({
                    url: bundleUrl,
                    animated: "true"
                }, () => {})
            }
        },
        back () {
            if (WXEnvironment.platform === 'Web' && this.$router) {
                this.$router.back()
            } else {
                navigator.pop({
                    animated: "true"
                }, () => {})
            }
        }
    }
}

这样的方案,算比较完美了(后退动作也正常了),只是 android 没有缓存, 每次都重新重载有点慢。iOS 表现非常赞!

@dongnaebi
Copy link

dongnaebi commented Feb 7, 2017

@vfasky 这样的话,web端只编译出一个js,native端还是对应vue文件分别编译?
按这个思路,我有一个product/detail.vue,native端照样编译成product/detail.js,web端app.js里的routerMap写:

import router from 'vue-router'
import detail from ./product/detail.vue
const router = new router({
  routes: [
    { path: '/product/:id', component: detail }
  ]
})

运维人员添加了一个广告位,链接为http://m.xxx.com/#product/452434,在goto方法里接收到这个链接,web端直接跳转,但native还要写一个bundleMap来解析到对应jsBundle。

{path:"/product/:id",bundle:"http://m.xxx.com/dist/product/detail.js?id=:id"}

并且接收参数也要写两套。

如果是集成到现有APP,web端直接跳转,native端如果bundleMap里没有对应的path,就跳原生页,否则加载jsBundle,这样看来好像这个方案确实是很完美了。

我试着写成一个跳转组件,写得好的话发出来共享

@dongnaebi
Copy link

来了,写成了个vue插件,已经发布到npm,稍后带来example
https://github.com/dongnaebi/weex-vue-router

@vfasky
Copy link
Author

vfasky commented Feb 24, 2017

@dongnaebi 这个跳转方案有点复杂,稍候整理下我们的方案出来一起讨论下。

另外:对于 android 不能隐藏 fixed dom 的 bug , 我们已经有一个比较好的解决方案 (当然,还是期望官方修复)
https://github.com/MMF-FE/weex-vue-fixed 欢迎使用

@vfasky
Copy link
Author

vfasky commented Feb 25, 2017

@dongnaebi @Hanks10100 weex-vue-navigator 能让 native 端使用原生跳转,在 web 端 使用 SPA

@Hanks10100
Copy link
Member

不好意思,刚发现这个 issue 还在回复,已经歪楼了……

@dongnaebi @vfasky 你们两个的 router 和 navigator 我都看了一下,都挺不错的。实现不一样,但是思路都差不多,是想实现在 web 上保持 spa 或者 vue-router 那种体验,然后在 native 上保持多页特性。(不知道我有没有理解错)

要想实现这个效果的话,还得解决一些工程上的问题。native 上的多页是对应了多个 url 的,把 hash 转成静态的 url,就得打包多个 js bundle 文件。如果路由里含有模式(/:id(\\d+))匹配难度就很大,在 native 上写一份 bundleMap 是不是意味着 native 上又有了一套 router 机制 ……?而且路由之间传参也是个问题。

其实实现 router 还要解决一个问题就是管理数据和作用域。spa 里上一个视图可以向下一个视图传参,而且每个页面都可能会修改全局状态的;然而在 native 上,多个页面的创建销毁调用的是 native 接口,js 层面很难传参,而且数据状态是不共享的。为了避免内存泄露,还专门限制了全局变量,多页面之间不会共享状态的。

如果要保持 native 的特性,就得在 web 上限制多个页面之间能共享状态,不然和 native 上的特性就不一致了。如果 web 上也不能共享状态的话,spa 就鸡肋了。

@dongnaebi
Copy link

传参我是这样做的:
链接:/path/1/2?query=3#a
对应map:{path:'/path/:foo/:bar',component:'/dist/path.js'}
处理成:/dist/path.js?foo=1&bar=2&query=3#a

获取参数的时候再对应map取得paramqueryhash

状态共享确实是没法弄了,坚持做SPA是想得到更好的跳转体验,和更优雅的链接。。。其他的就缺省方案吧

@vfasky 你这个只做了跳转?没做参数传递么?

@vfasky
Copy link
Author

vfasky commented Feb 27, 2017

@dongnaebi 参数通过url传递。 我们在 app 的实现原理,其实就相当于web中新窗口打开同一个应用,然后执行对应的路由。 所以,一份代码就可以跑三端。上面所说的"工程"问题,也解决了。

@Jinjiang Jinjiang removed the discuss label Mar 1, 2017
@YorkShen
Copy link
Contributor

This PR/issue doesn't receive response since Weex migrated to Apache two years ago and this repository is no longer active yet.

Feel free to ask question in new repository and thanks for your contribution.

@Hanks10100
Copy link
Member

This issue is outdated for a long time and will be closed now. You can create a new one if you still have questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants