NutUI 是一款京东风格的移动端组件库。NutUI 目前支持 Vue 和 React技术栈,支持Taro多端适配。
期待您早日成为我们共建大军中的一员!
微信群:hanyuxinting(暗号:NutUI-React)
官网GitHub: 点击进入
欢迎共建、使用!
背景
HTML 提供了一个全局属性 dir 用于设置文本的方向,dir有三个取值:ltr、rtl、auto。
- ltr,指从左到右,用于那种从左向右书写的语言(比如英语);
- rtl,指从右到左,用于那种从右向左书写的语言(比如阿拉伯语);
- auto,指由用户代理决定方向。它在解析元素中字符时会运用一个基本算法,直到发现一个具有强方向性的字符,然后将这一方向应用于整个元素。
NutUI-React 的国际化方案中目前提供了不同的语言文本,但是并没有对文本的方向进行支持。所以近期我们在对文本方向相关的内容进行处理。
开发环境配置
为了进行 RTL 的验证和对组件进行修改,我们需要先让本地开发支持预览和调试。这里我们选择在 html 上设置 dir="rtl"。然后提供 pnpm dev:rtl 来启动开发环境。由于 html 文件是共享给非 RTL 的开发环境使用的,所以我们采用了 vite 向页面中注入变量的方式来进行区分。
首先我们需要改动 html 文件, 添加 dir属性。通过给 html设置 dir="rtl",可以使得整个页面的文本从右到左布局。
<html lang="en" dir="%VITE_RTL%">
VITE_RTL是我们定义的环境变量,在执行 pnpm dev:rtl 的时候进行设置,之后环境变量VITE_RTL由 Vite 解析,并替换到 HTML 文件中。
验证 RTL 效果
在完成这一步骤之后,我们发现很多组件的布局出现了异常,主要是因为在 CSS 中给元素设置了固定的外边距方向、内边距方向、变换方向,从而导致了大部分组件出现异常。
例如组件设置了 margin-right: 16px, 在 rtl 模式下,应该转换为 margin-left: 16px。这样的转换比较多,而且也具有流程化的特点,可以借助程序进行处理。为了验证这一想法,我们首先在开发环境中进行了验证。
验证这一思路使用的工具是 postcss 的 postcss-rtlcss 插件。
postcss: {
plugins: [
process.env.VITE_RTL === 'rtl' ? rtl() : () => {},
],
},
批量处理 SCSS 文件
通过这个步骤,我们发现可以解决大部分组件的问题。但是在开发环境中引入的 postcss-rtlcss 插件并不会生成修改后的代码。所以我们需要借助它,处理组件的样式文件,并进行原地更新操作。
const scss = require('postcss-scss')
const plugins = [
rtl({ mode: 'override', rtlPrefix: [`[dir="rtl"]`, `.nut-rtl`] }),
]
const css = fs.readFileSync(readFrom, 'utf8')
postcss(plugins)
.process(css, { syntax: scss })
.then((result) => {
fs.writeFile(writeTo, result.css, () => {})
})
这样我们就获取到了支持 rtl 的 scss 文件。接下来我们只需要处理一些交互相关的逻辑,比如 swiper 的反向滑动等。
[dir='rtl'] .nut-avatar,
.nut-rtl .nut-avatar {
.avatar-img {
left: auto;
right: 50%;
transform: translate(50%, -50%);
}
}
总结
以上就是我们实现 RTL 的一个思路,通过 Vite 支持在 HTML 文件中替换环境变量的特性开发,到采用 postcss 插件来验证和批量处理。
最后
感谢阅读,文中可能存在不准确或错误之处,如果您发现任何问题,欢迎指正,非常感激。
NutUI GitHub 仓库:
- React:jdf2e/nutui-react
- Vue:jdf2e/nutui
NutUI 官网:nutui.jd.com
欢迎关注,欢迎 Star~