taro icon indicating copy to clipboard operation
taro copied to clipboard

两个页面不能共用一个公共组件

Open Roderick-cc opened this issue 4 years ago • 14 comments
trafficstars

相关平台

微信小程序

复现仓库

https://github.com/shide-L/taro 小程序基础库: 2.14.0 使用框架: React

复现步骤

都是微信小程序下

  1. 2个页面 pageA,pageB,都使用同一个组件的话,另外一个pageB页面会非正常显示,scss没有加载
  2. demo部分的页面都引入同一个组件,非正常显示了,只要注释其中一个即可

期望结果

能实现组件跨页面复用

实际结果

不能复用,非正常显示或者是打包的时候没有把sacc中的样式

环境信息

 Taro CLI 3.0.13 environment info:
    System:
      OS: macOS 10.14.5
      Shell: 5.3 - /bin/zsh
    Binaries:
      Node: 10.16.3 - /usr/local/bin/node
      Yarn: 1.19.1 - /usr/local/bin/yarn
      npm: 6.14.8 - /usr/local/bin/npm
    npmPackages:
      @tarojs/components: 3.0.13 => 3.0.13
      @tarojs/mini-runner: 3.0.13 => 3.0.13
      @tarojs/react: 3.0.13 => 3.0.13
      @tarojs/runtime: 3.0.13 => 3.0.13
      @tarojs/taro: 3.0.13 => 3.0.13
      @tarojs/webpack-runner: 3.0.13 => 3.0.13
      babel-preset-taro: 3.0.13 => 3.0.13
      eslint-config-taro: 3.0.13 => 3.0.13
      react: ^16.10.0 => 16.14.0
      taro-ui: ^3.0.0-alpha.3 => 3.0.0-alpha.3
    npmGlobalPackages:
      typescript: 3.6.4

Roderick-cc avatar Dec 01 '20 08:12 Roderick-cc

同样的问题, 但是我是两个页面元素都不显示, 变成空白页面了 taro3.0.17

myxmxy1234 avatar Dec 03 '20 06:12 myxmxy1234

@shide-L @myxmxy1234 使用 demo 在 3.0.17 中一开始复现了,后续不断修改若干次代码后突然好了,然后把代码恢复最初,再没有复现了,可以试试重新编译,或重启开发者工具试试。

image image

截图只是把这两处注释取消后运行得出:

image

Chen-jj avatar Dec 03 '20 07:12 Chen-jj

@Chen-jj , @shide-L 我今天也遇到这个问题的。然后分析了一下:

  1. 单页面引用组件时,组件的样式会直接被写入到页面的 wxss 中;
  2. 多页面引用组件时,组件的样式会被抽成公共样式并被放在 common.wxss 中;

然后出现「多页面引用同一组件后,组件样式失效」的原因是「common.wxss」这个文件并不是微信小程序的「公共样式」!!!!微信小程序的公共样式是「app.wxss」。

然后这里的问题来了,为什么 Taro 要把公共样式放在「common.wxss」上,而不是「app.wxss」呢? 这个只能找「Taro之父」聊聊了。

说一下解决怎么解决这个问题的方法其实很简单:在 src 下创建 app.scss ,然后在 app.tsx/app.jsx 中引用这个文件就好了,如下:

// app.jsx
import './app.scss';
// app.scss
.global-app {};

结论与建议

这个问题可能跟开发的习惯有关,有些开发会有引入公共样式的习惯,有些开发没有。如果没有引用公共样式的话,又有代码洁癖的人会把 app.jsx 上引入 的 「import './app.scss」删除,然后问题就会出现。Taro 是在编译后在「app.wxss」用「@import './common.wxss」引入。但是如果我们在 app.jsx 中没有「import './index.scss」,Taro 在编译后也不会生成「app.wxss」,结果就是「common.wxss」也没有被引入了。

建议 Taro 默认都生成一个「app.wxss」避免类似问题

leeenx avatar Dec 12 '20 06:12 leeenx

@Chen-jj , @shide-L 我今天也遇到这个问题的。然后分析了一下:

  1. 单页面引用组件时,组件的样式会直接被写入到页面的 wxss 中;
  2. 多页面引用组件时,组件的样式会被抽成公共样式并被放在 common.wxss 中;

然后出现「多页面引用同一组件后,组件样式失效」的原因是「common.wxss」这个文件并不是微信小程序的「公共样式」!!!!微信小程序的公共样式是「app.wxss」。

然后这里的问题来了,为什么 Taro 要把公共样式放在「common.wxss」上,而不是「app.wxss」呢? 这个只能找「Taro之父」聊聊了。

说一下解决怎么解决这个问题的方法其实很简单:在 src 下创建 app.scss ,然后在 app.tsx/app.jsx 中引用这个文件就好了,如下:

// app.jsx
import './app.scss';
// app.scss
.global-app {};

结论与建议

这个问题可能跟开发的习惯有关,有些开发会有引入公共样式的习惯,有些开发没有。如果没有引用公共样式的话,又有代码洁癖的人会把 app.jsx 上引入 的 「import './app.scss」删除,然后问题就会出现。Taro 是在编译后在「app.wxss」用「@import './common.wxss」引入。但是如果我们在 app.jsx 中没有「import './index.scss」,Taro 在编译后也不会生成「app.wxss」,结果就是「common.wxss」也没有被引入了。

建议 Taro 默认都生成一个「app.wxss」避免类似问题

找了2天样式失效的问题,终于找到了,太坑了 感谢🙏

maroon1 avatar Jan 06 '22 09:01 maroon1

@Chen-jj , @shide-L 我今天也遇到这个问题的。然后分析了一下:

  1. 单页面引用组件时,组件的样式会直接被写入到页面的 wxss 中;
  2. 多页面引用组件时,组件的样式会被抽成公共样式并被放在 common.wxss 中;

然后出现「多页面引用同一组件后,组件样式失效」的原因是「common.wxss」这个文件并不是微信小程序的「公共样式」!!!!微信小程序的公共样式是「app.wxss」。

然后这里的问题来了,为什么 Taro 要把公共样式放在「common.wxss」上,而不是「app.wxss」呢? 这个只能找「Taro之父」聊聊了。

说一下解决怎么解决这个问题的方法其实很简单:在 src 下创建 app.scss ,然后在 app.tsx/app.jsx 中引用这个文件就好了,如下:

// app.jsx
import './app.scss';
// app.scss
.global-app {};

结论与建议

这个问题可能跟开发的习惯有关,有些开发会有引入公共样式的习惯,有些开发没有。如果没有引用公共样式的话,又有代码洁癖的人会把 app.jsx 上引入 的 「import './app.scss」删除,然后问题就会出现。Taro 是在编译后在「app.wxss」用「@import './common.wxss」引入。但是如果我们在 app.jsx 中没有「import './index.scss」,Taro 在编译后也不会生成「app.wxss」,结果就是「common.wxss」也没有被引入了。

建议 Taro 默认都生成一个「app.wxss」避免类似问题

使用css modules如何操作呢,这种方法还是不奏效。。

lxsunbin avatar Feb 08 '22 11:02 lxsunbin

@maroon1 请问一下使用css module如何处理这种情况呢?

lxsunbin avatar Feb 08 '22 12:02 lxsunbin

@lxsunbin 我使用的是 CSS in JS 方案,所以不确定 CSS Module 方案是否有什么不一样,不过请确保代码中按以下方法做了

在 src 下创建 app.scss ,然后在 app.tsx/app.jsx 中引用这个文件

可以看看代码生成结果中是否正确引用了 common.wxss 以确定我们遇到的是同样问题

maroon1 avatar Feb 09 '22 07:02 maroon1

@lxsunbin 我使用的是 CSS in JS 方案,所以不确定 CSS Module 方案是否有什么不一样,不过请确保代码中按以下方法做了

在 src 下创建 app.scss ,然后在 app.tsx/app.jsx 中引用这个文件

可以看看代码生成结果中是否正确引用了 common.wxss 以确定我们遇到的是同样问题

以确定这些都正常,就是样式没有生效。。

lxsunbin avatar Feb 09 '22 09:02 lxsunbin

@lxsunbin 最好可以提供一个最小的可复现的代码

maroon1 avatar Feb 09 '22 10:02 maroon1

我这里遇到Taro混编到支付宝小程序中,多个页面不能用同一个组件的问题。各位大佬有解决吗?

xiaotianmei avatar Mar 16 '22 10:03 xiaotianmei

在原生支付宝小程序项目里混编时也遇到了相同的问题。taro 3.4.2

我们的解决方案是在支付宝项目的 app.acss 里引入 taro 的 app.acss

@import "taro/app.acss"

1oo1 avatar Mar 16 '22 11:03 1oo1

这个官方是不是可以修复一下@Chen-jj

lxsunbin avatar Mar 22 '22 08:03 lxsunbin

没有使用 common 的方式,只是正常将一个 component 被 2 个 page 引用,就空白了。

JoshYuJump avatar Aug 27 '22 10:08 JoshYuJump

写了一个plugin暂时程序添加一下引用,对小程序插件开发影响很大啊,插件根本没有app.wxss- -

const { ConcatSource } = require('webpack-sources')
const Regexp = /(?<=plugin\/(components|pages))\/.+\.wxss/g

class WxssImportPlugin {
  apply(compiler) {
    compiler.hooks.emit.tapAsync(
      'WxssImportPlugin',
      (compilation, callback) => {
        // Do something async...
        // 寻找 plugin/page 文件下 的wxss文件
        for (let [name, assets] of Object.entries(compilation.assets)) {
          if (Regexp.test(name)) {
            // 找路径下有几个/
            const times = name.split('/').length - 2
            // 创建首行引用语句 @import '../../common.wxss'
            const firstLine = `@import '${Array(times).fill('../').join('') + 'common.wxss'}';\n`
            compilation.assets[name] = new ConcatSource(firstLine + assets.source())
          }
        }

        callback()
      }
    );
  }
}

module.exports = WxssImportPlugin

ranmeizi avatar Sep 05 '22 05:09 ranmeizi

同样的问题, 但是我是两个页面元素都不显示, 变成空白页面了 taro3.0.17

同样的问题,请问有解决方案了嘛

Linjovi avatar Feb 20 '23 05:02 Linjovi

Taro v3.6.8 修复:

  1. buildNativeComp 模式下,为各组件自动引入 common 公共样式
  2. 当开发者没有全局样式文件时,仍能正确引入 common 公共样式

Chen-jj avatar Jun 08 '23 09:06 Chen-jj

没有使用 common 的方式,只是正常将一个 component 被 2 个 page 引用,就空白了。

+1 解决了吗

forsakesoul avatar Nov 19 '23 12:11 forsakesoul

没有使用 common 的方式,只是正常将一个 component 被 2 个 page 引用,就空白了。

已解决。我使用的 less 构建样式表,组件内使用 xxx.less 顶部使用了 @import (once) 'xxx.less' 去掉 once 就可以正常加载了。虽然不知道原因是什么

forsakesoul avatar Nov 19 '23 13:11 forsakesoul