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

需要和flexble.js一起使用,怎样自己维护一份vux还能保持更新 #1796

Open
54leibo opened this issue Aug 4, 2017 · 54 comments

Comments

@54leibo
Copy link

54leibo commented Aug 4, 2017

我需要和flexble.js结合使用,框架中的px被转后出现了问题,所以现在想要自己维护一份,是需要这样吗:改动vux源码=》发布一个npm包=》安装使用
如果改动频繁需要不断发布npm包,好像会很麻烦,有更好的方式做这件事情吗

@airyland
Copy link
Owner

airyland commented Aug 4, 2017

会很麻烦。你可以说说你的具体需求,看看能否直接在 vux 源码来支持。

@54leibo
Copy link
Author

54leibo commented Aug 4, 2017

我想要实现视图自适应屏幕尺寸,目前想要采取的方案是淘宝的flexible.js(https://github.com/amfe/lib-flexible),但是在使用过程中发现,把px转化为rem的时候把vux的px转化成了rem(使用px2rem),这样造成的问题是:1.没能避免不需要转化的(比如:border:1px solid #000;中的1px);2.我们的设计图是750px的,而vux好像是375px,这也造成了转化结果不是想要的;

@54leibo
Copy link
Author

54leibo commented Aug 4, 2017

补充:js计算的也无法转化为rem,这样在如弹窗组件中会出现部分单位是px,部分单位是rem,结果造成视图有点错乱

@airyland
Copy link
Owner

airyland commented Aug 4, 2017

可否建个应用 flexible 的基础 repo,并能重现上面的问题,我来尝试在 vux 或者 vux-loader 里支持。

@54leibo
Copy link
Author

54leibo commented Aug 5, 2017

可以

@teshun
Copy link

teshun commented Aug 7, 2017

flexible.js的适配是会判断iphone端drp,然后设置viewport,而安卓端统一设置为1。vux的样式用的是px,导致在iphone会被缩小,而在安卓就没问题。

@54leibo
Copy link
Author

54leibo commented Aug 7, 2017

是的,这两天有点忙,我接下来尽快弄一个能重现问题的rp

@wg5945
Copy link
Collaborator

wg5945 commented Aug 8, 2017

目前的处理方法是将vux组件中px转化为PX,避免被转成rem

#932 (comment)

如果引入了1px的话,还要做些特殊处理

目前我是这么搞得,可以参考下

{
      name: 'after-less-parser',
      fn: function (source) {
        if (this.resourcePath.replace(/\\/g, '/').indexOf('/vux/src/components') > -1) {
          source = source.replace(/px/g, 'PX')
        }
        // 自定义的全局样式大部分不需要转换
        if (this.resourcePath.replace(/\\/g, '/').indexOf('App.vue') > -1) {
          source = source.replace(/px/g, 'PX').replace(/-1PX/g, '-1px')
        }
        return source
      }
    },
    {
      name: 'style-parser',
      fn: function (source) {
        if (this.resourcePath.replace(/\\/g, '/').indexOf('/vux/src/components') > -1) {
          source = source.replace(/px/g, 'PX')
        }
        // 避免转换1PX.less文件路径
        if (source.indexOf('1PX.less') > -1) {
          source = source.replace(/1PX.less/g, '1px.less')
        }
        return source
      }
    }

转换rem使用的是postcss-plugin-px2rem,当然 postcss-px2rem 也可以

    require('postcss-plugin-px2rem')({
      rootValue: 75, // 这里对应的是750的设计图尺寸
      selectorBlackList: ['html'],
      mediaQuery: true,
      propBlackList: ['border-radius'] // 如果要保持font-size不转换,替换为 ['font-size']
    }),

@54leibo
Copy link
Author

54leibo commented Aug 9, 2017

搞了一个简单的重现:git@github.com:54leibo/54leibo.github.com.git

@wg5945
Copy link
Collaborator

wg5945 commented Aug 9, 2017

vux的ui是基于weui的,而weui本身并没有使用rem (why)

如果全局转rem的话,会使组件大小位置不正确,所以上面采用的是组件和页面分开处理

你那个demo,我跑了下,font-size都变成0了,原因未知

你上面说的没转成功的,我猜可能是less文件没转换

@54leibo
Copy link
Author

54leibo commented Aug 9, 2017

之前是loader出了点问题,现在已经修复;我先研究下你目前给出的解决方案

@54leibo
Copy link
Author

54leibo commented Aug 9, 2017

after-less-parser、style-parser这两个是在哪里配置的呢

@wg5945
Copy link
Collaborator

wg5945 commented Aug 9, 2017

vux-loader里面

https://vux.li/#/zh-CN/vux-loader?id=plugins

@prettybot
Copy link

prettybot commented Aug 11, 2017

可以按照如下方式兼容VUX和手淘flexible适配方案:
将js文件中涉及到data-dpr与缩放scale的代码改写,默认所有设备的data-dpr为1.

if (!i && !j) {
    //将p直接置为false,这样缩放比例都为1,dpr也都设置为了1
    let p = false,
      q = a.devicePixelRatio;
    i = p ? q >= 3 && (!i || i >= 3) ? 3 : q >= 2 && (!i || i >= 2) ? 2 : 1 : 1, j = 1 / i
  }

@xiaolongyuan
Copy link
Contributor

同样遇到这个问题 楼上哪个方案可行?

@jun888
Copy link

jun888 commented Aug 14, 2017

同样遇到这个问题,求可行方案

@Anehta
Copy link

Anehta commented Aug 14, 2017

一样遇到了这个问题=。=,求可行方案。或者暂时的替代方案。

@RenShine
Copy link

同样遇到这个问题 目前使用的是上面贴出的after-less-parser的方案 但是要注意 那段代码有2个地方写的有问题 就是/vux/components那段 要改成vux/components 因为我把路径打印出来发现前面是@vux这种格式

@airyland
Copy link
Owner

airyland commented Aug 14, 2017

@RenShine 感谢提醒,使用 cnpm 安装依赖后路径会是你说的这种情况
cc @wg5945

@wg5945
Copy link
Collaborator

wg5945 commented Aug 14, 2017

@RenShine 上面使用的是indexOf,多个/会有影响么?

原来是使用的cnpm导致vux路径变化哦,cnpm会导致一些不可期的问题,还是使用yarn吧

@wg5945
Copy link
Collaborator

wg5945 commented Aug 14, 2017

对于上面几位寻求解决方案的,方案已经给出了,为什么不自己尝试一下呢?

@xiaolongyuan
Copy link
Contributor

@wg5945 感谢 目前正在尝试整合你的方案 good

@525729985
Copy link

@wg5945 我也正好遇到这个问题,但是觉得好像上边方案不解决问题啊。首先flexble.js会根据不同dpr缩放整个页面,让border保持1像素,如果禁掉这个缩放那flexble就不好用一半。如果保持页面缩放,那vux就算px不转rem,那别的元素按750缩放正常看,vux按375的大小缩放小一半,还是存在问题。

@wg5945
Copy link
Collaborator

wg5945 commented Aug 18, 2017

@525729985 没太明白你的意思

其实上面的最终结果就是:
页面px转成rem,根据dpr缩放
vux组件px转成PX,不缩放

@54leibo
Copy link
Author

54leibo commented Aug 19, 2017

我现在是这样使用的
1.使用after-less-parser、style-parser将vux中的px转为PX,这样在使用px2rem处理时就避免了vux被处理
2.阉割掉了flexible.js中根据dpr缩放的功能

@agileago
Copy link
Contributor

agileago commented Sep 8, 2017

上面几位使用flexible做适配的遇到这么多问题,为什么就不尝试用固定尺寸做适配么?

<meta name="viewport" content="width=375,user-scalable=no">

设计图是多少写多少就行了,没那多转来转去的,到最后效果还是一样,已在项目中使用快一年了

@RenShine
Copy link

@agileago 你这个方案我也用了有2年了 不过我是设置成640的 你这个375其实是有问题的(隐约记得在6P下好像是有点问题) 不过其实大部分场景下都不会有问题 简单粗暴

但是还是有一些特殊情况没有rem好处理 有一些情况下viewport缩放会导致元素有点糊

其实早期大家都是用这个来做适配的(包括天猫) rem的出现就是为了解决viewport解决不了的问题(也是天猫提出这个方案的)而且现在webpack很方便 用postcss平时设计图是多少我们也写多少 都是插件自动转的 所以一般都不使用viewport的方案了

@agileago
Copy link
Contributor

@RenShine 还好吧,暂时没发现有什么问题,除了横竖屏切换的时候有时候没有正常切过来到时页面变得很大(这个加个监听事件重置一下就解决了),现在荔枝fm还在用 http://m.lizhi.fm ,设置成375或者640看你的设计图了,我以前也是用rem的方案,主要那个时候大家都吹嘘着移动端要用rem,稀里糊涂的就用了,然后使用了之后团队很多人就说这东西还得再转一下,并且当时有的人的设计图是320,还有的人是375的,导致一些人觉得这玩意挺麻烦的(有些小项目是不用webpack的,比如有的人只写css),后来发现viewport的方案更简单也没什么大的问题,然后大家都喜欢用,其实viewport比较不好的一点就是不能设置字体在每个分辨率下显示一样大小,而rem就可以

a {
  margin-top: px2rem(120);
  font-size: 14px;
}

这是我觉得他唯一的优点吧

@RenShine
Copy link

@agileago 设置viewport为固定宽度在很多那些不需要webpack的场景下肯定是OK的 不过问题是有的。 一个就是不能使用媒体查询 第二个就是1px边框的问题(时间太久了这一点存疑,但是媒体查询肯定是没法用的)

@hminghe
Copy link

hminghe commented Sep 12, 2017

原来那么多人用flexble.js阿, 我说下我的几个项目睬的坑后用的方案吧。
index.html: 加上
<meta name="flexible" content="initial-dpr=1">
在build加个js文件, 防止1px的给转换 mycss.js

const postcss = require('postcss')
const cssObj = require('css')
const onePxRegExp = /\b1px\b/;

module.exports = postcss.plugin('mycss', function (options) {
  return function (css, result) {
    let oldCssText = css.toString()
    if(oldCssText.indexOf('font-size') === -1) return
    let astObj = cssObj.parse(oldCssText)
    let rules = astObj.stylesheet.rules
    rules.forEach((rule, i) => {
      if(Array.isArray(rule.declarations)) {
        rule.declarations.forEach((declaration, j) => {
          if (declaration.type === 'declaration' && onePxRegExp.test(declaration.value)) {
            let newRule = {
              type: 'comment',
              comment: 'no'
            }
            rule.declarations.splice(j + 1, 0, newRule)
          }
   
        })
      }
    })
    let newCssText = cssObj.stringify(astObj)
    result.root = postcss.parse(newCssText);
  };
});

安装postcss-px2rem
在vue-loader的postcss加上
require('./mycss')(), 和 require('postcss-px2rem')({remUnit: 37.5})
用37.5是因为weui都是这个尺寸的, 所有你要按你自己设计稿转换
例如:设计稿是750, 24px 你在项目里 要用12px

postcss: function () {
    return [
      require('./mycss')(),
      require('autoprefixer')({
        browsers: ['iOS >= 7', 'Android >= 4.1']
      }),
      require('postcss-px2rem')({remUnit: 37.5})
    ]
  }

最后要加个公用方法

getRealPx (px, remUnit = 37.5) {
    return px * (parseFloat(document.getElementsByTagName('html')[0].style.fontSize) / remUnit)
  }

你要在js里用px 都要用这个方法来转变
例如用 ViewBox
<view-box :body-padding-top="getRealPx(50) + 'px'"></view-box>

注意:
不要在style="width:100px" 这样写px 是不用自动转换的
一定要在下面写写

<style>
div {width:100px}
</style>

有空开个git放上去

@agileago
Copy link
Contributor

@RenShine 哈哈,具体用哪个还是得考虑业务场景,如果真的碰上了那就用rem也行,两手准备,但我目前的项目大部分都是固定尺寸先行。不过我是用的hotcss来做rem适配的,走编译路线的,虽说不是什么大问题,但有时候真的很烦,就像你用coffeescript或者Typescript一样,写下的每行代码都要在脑海中自动转换成原生js,这个过程着实烧脑。😁😁😂

@xiaolongyuan
Copy link
Contributor

flexible又来了 2.0版本

@moahmn
Copy link

moahmn commented Oct 31, 2017

我的情况是这样的,用的手淘rem,我的px转rem是用的(github.com/flashlizi/cssrem)插件,并没有使用postcss-px2rem插件,所以不存在所有的px被转换为rem。只有我自己的样式被转换为了rem,现在vux的组件在项目中显示的非常小,请问如何修改可以使用rem + vux?

@wg5945
Copy link
Collaborator

wg5945 commented Nov 1, 2017

@xiaolongyuan
2.0使用的vw,但是目前还是有好几款主流手机不支持,特别是华为的,因此还是要慎重一下

@wg5945
Copy link
Collaborator

wg5945 commented Nov 1, 2017

@moahmn
上面写过了,目前处理方案是不对vux组件进行转化,不管哪种转化方案都有不进行转化的方式,自行处理下就好

@xiaolongyuan
Copy link
Contributor

@wg5945 关键是2.0使用方式让人有点摸不着头脑 amfe/lib-flexible#159

@wg5945
Copy link
Collaborator

wg5945 commented Nov 1, 2017

这我倒没发现,按照他的教程一步步做就好了,在ios和支持的android手机上适配都很完美

@xiaolongyuan
Copy link
Contributor

@wg5945 你竟然成功了 我整合后 VUX有问题 vw 单位转换倒是没问题 能帮我看看?

vue-loader.conf.js


module.exports = {
  loaders: utils.cssLoaders({
    sourceMap: isProduction
      ? config.build.productionSourceMap
      : config.dev.cssSourceMap,
    extract: isProduction
  }),
  transformToRequire: {
    video: 'src',
    source: 'src',
    img: 'src',
    image: 'xlink:href'
  },
  postcss: [
    // require('autoprefixer')({
    //   browsers: ['last 2 versions']
    // }),
    require('postcss-cssnext')({
      // browsers: ['last 2 versions']
      'browsers':'ios >= 7,android >= 4'
    }),
    require('precss')(),
    require('postcss-write-svg')({ /* options */ }),
    require('postcss-aspect-ratio-mini')(),
    // require('postcss-px2rem')({
    //   remUnit: 75,
    //   threeVersion: true
    // }),
    require('postcss-px-to-viewport')({
      viewportWidth: 750,
      viewportHeight: 1334,
      unitPrecision: 5,
      viewportUnit: 'vw',
      selectorBlackList: [],
      minPixelValue: 1,
      mediaQuery: false
    }),
    // require('postcss-adaptive')({
    //   // autoRem:true
    // })

  ]
}

webpack.base.conf.js


module.exports = vuxLoader.merge(webpackConfig, {
  plugins: [
    {
      name: 'vux-ui'
    },
    {
      name: 'progress-bar'
    },
    {
      name: 'duplicate-style',
      // options: {
      //   canPrint: true
      // }
    },
    {
      name: 'after-less-parser',
      fn: function (source) {
        if (this.resourcePath.replace(/\\/g, '/').indexOf('/vux/src/components') > -1) {
          source = source.replace(/px/g, 'PX')
        }
        // 自定义的全局样式大部分不需要转换
        if (this.resourcePath.replace(/\\/g, '/').indexOf('App.vue') > -1) {
          source = source.replace(/px/g, 'PX').replace(/-1PX/g, '-1px')
        }
        return source
      }
    },
    {
      name: 'style-parser',
      fn: function (source) {
        if (this.resourcePath.replace(/\\/g, '/').indexOf('/vux/src/components') > -1) {
          source = source.replace(/px/g, 'PX')
        }
        // 避免转换1PX.less文件路径
        if (source.indexOf('1PX.less') > -1) {
          source = source.replace(/1PX.less/g, '1px.less')
        }
        return source
      }
    }
    // {
    //   name: 'less-theme',
    //   path: 'src/styles/theme.less'
    // },
    // {
    //   name: 'i18n',
    //   vuxStaticReplace: false,
    //   staticReplace: false,
    //   extractToFiles: 'src/locales/components.yml',
    //   localeList: ['en', 'zh-CN']
    // },

  ]
})

@moahmn
Copy link

moahmn commented Nov 1, 2017

@wg5945 我能直接采用你上面的方案?我发现按照上面的配置(没用postcss-px2rem转换,我自己在编辑器里转的,所以也不存在说vux的组件样式px被转换为rem)后组件还是比正常的转换rem的元素小很多
qq 20171101101844
qq 20171101101849

目前也实现了px转换为PX但是组件还是很小

@wg5945
Copy link
Collaborator

wg5945 commented Nov 2, 2017

@xiaolongyuan
这个要看看 postcss-px-to-viewport 里面有什么不转成vw的方案
当初postcss-px2rem是改成PX不转化

@wg5945
Copy link
Collaborator

wg5945 commented Nov 2, 2017

@moahmn
你再仔细看看吧
input组件的大小应该看 .weui-cells 这个样式,你看看呢

@BlackEyeByLee
Copy link

@wg5945 大大说的是vux里边的px转为PX,即避免了插件的px2rem,但其实flexibox的精髓即是根据dpr去缩放页面,即动态设置meta,所以就算是vux里的组件没被转换也会被缩放。现在已知的解决方案是默认设置meta,dpr为1,但感觉这样并不优雅,因为适配的字体方案也是根据dpr设置的

@Amling2017
Copy link

各位大神,有没有完整的解决方案,求助!我发现vux的组件转换合适后,边框和字体缩放就发生了变化。该如何解决,求助大神!

@moahmn
Copy link

moahmn commented Dec 1, 2017

看了下flexible的源码
如果使用了0.3.4的flexible也同时希望使用vux,可以手动设置meta头,在header头部加入
中括号meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"中括号(中括号自己替换下,打不出来)

下面是flexible的部分源码
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
//如果有手动设置的meta头部进入这个逻辑
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(/initial-scale=([\d.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
//这个无关略过
} else if (flexibleEl) {
var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(/initial-dpr=([\d.]+)/);
var maximumDpr = content.match(/maximum-dpr=([\d.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
// dpr 和sacle默认是0,如果上面两个逻辑都没进去的话进入这一步,这就是为什么与vux配合会出现缩放的原因, 根据几倍屏去分别设置不同的meta头
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}

手动设置下meta头就可以不根据IOS 2/3倍屏去缩放

@bingyang519
Copy link

如果不用rem,移动端大家都是用什么做适配的呢?还可以很好的配合这些UI框架?

@callmepinggege
Copy link

https://github.com/callmepinggege/vux-lib-flexible 结合上述大神的方案 自己实现了一套 大家可以直接用

@LuckyDing
Copy link

用网易的解决方案

@agileago
Copy link
Contributor

@RenShine 你说的定宽问题今天被我遇到了,果然是在PLUS上面有问题,这个问题是,当页面是整屏滚动的时候,并且页面的长度在1000px以内,然后你做了个弹窗,滚动了滚动条,这个弹窗上面的按钮的触发区域就上移了

image

我实在模拟器模拟的,弹窗的位置上移了,但显示还是正常的,真的让人很无语,你那边有没有啥好的解决方案

@yangqin007
Copy link

@moahmn 我也遇到了同样的组件很小的问题。请问你解决了么?

@moahmn
Copy link

moahmn commented Jan 30, 2018

中括号meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"中括号 在head中加入这个meta就行了。这是我目前的做法。但手淘的font-dpr那个宏就不起作用了,因为现在的dpr被永久设置为1了。字体的设置我还是使用px,你也可以使用rem做单位虽然说作者是不推荐的,但是我看网易移动端也用rem做字体的单位,你可以参考下。

@yangqin007
Copy link

@moahmn dpr被永久设置为1对什么东西会有影响呢?

@yangqin007
Copy link

@54leibo 请问阉割掉了flexible.js中根据dpr缩放的功能,会对什么东西会有影响呢?

@13168335674
Copy link

13168335674 commented Mar 30, 2018

@ifredom
Copy link

ifredom commented May 20, 2019

首先,移动端我经常把border里面的小尺寸用px,而有的地方又用了rem。。。所以我的方案是 rem+px2rem插件。
项目是vue-cli构建的项目.
第一步。引入rem.js文件
image

第二步. 添加上插件
image

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

No branches or pull requests