mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-24 04:25:27 +08:00
**Problem** StyleSheet's implementation was overly complex. It required `flattenStyle` to use `expandStyle`, and couldn't support mapping React Native style props to CSS properties without also exposing those CSS properties in the API. **Response** - `flattenStyle` is concerned only with flattening style objects. - `StyleSheetRegistry` is responsible for registering styles, mapping the React Native style prop to DOM props, and generating the CSS for the backing style element. - `StyleSheetRegistry` uses a simpler approach to caching styles and generating style sheet strings. It also drops the unobfuscated class names from development mode, as the React Dev Tools can provide a better debugging experience (pending a fix to allow props/styles to be changed from the dev tools). - `StyleSheet` will fall back to inline styles if it doesn't think a style sheet has been rendered into the document. The relationship is currently only implicit. This should be revisited. - `StyleSheet` exports `renderToString` as part of the documented API. - Fix processing of `transformMatrix` and add tests for `processTransform`. - Fix `input[type=search]` rendering in Safari by using `display:none` on its pseudo-elements. - Add support for `textDecorationLine` and `textAlignVertical`. - Note the `View` hack to conditionally apply the `flex-shrink:0` reset from css-layout. This is required because React Native's approach to resolving `style` is to give precendence to long-hand styles (e.g., `flexShrink`) over short-hand styles (e.g., `flex`). This means the `View` reset overrides any `flex:1` declaration. To get around this, `flexShrink` is only set in `View` if `flex` is not set.
102 lines
2.6 KiB
JavaScript
102 lines
2.6 KiB
JavaScript
/**
|
|
* Copyright (c) 2016-present, Nicolas Gallagher.
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import prefixAll from 'inline-style-prefix-all'
|
|
import hyphenate from './hyphenate'
|
|
import expandStyle from './expandStyle'
|
|
import flattenStyle from './flattenStyle'
|
|
import processTransform from './processTransform'
|
|
import { predefinedClassNames } from './predefs'
|
|
|
|
let stylesCache = {}
|
|
let uniqueID = 0
|
|
|
|
const getCacheKey = (prop, value) => `${prop}:${value}`
|
|
|
|
const normalizeStyle = (style) => {
|
|
return processTransform(expandStyle(flattenStyle(style)))
|
|
}
|
|
|
|
const createCssDeclarations = (style) => {
|
|
return Object.keys(style).map((prop) => {
|
|
const property = hyphenate(prop)
|
|
const value = style[prop]
|
|
return `${property}:${value};`
|
|
}).sort().join('')
|
|
}
|
|
|
|
class StyleSheetRegistry {
|
|
/* for testing */
|
|
static _reset() {
|
|
stylesCache = {}
|
|
uniqueID = 0
|
|
}
|
|
|
|
static renderToString() {
|
|
let str = `/* ${uniqueID} unique declarations */`
|
|
|
|
return Object.keys(stylesCache).reduce((str, key) => {
|
|
const id = stylesCache[key].id
|
|
const style = stylesCache[key].style
|
|
const declarations = createCssDeclarations(style)
|
|
const rule = `\n.${id}{${declarations}}`
|
|
str += rule
|
|
return str
|
|
}, str)
|
|
}
|
|
|
|
static registerStyle(style: Object): number {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
Object.freeze(style)
|
|
}
|
|
|
|
const normalizedStyle = normalizeStyle(style)
|
|
|
|
Object.keys(normalizedStyle).forEach((prop) => {
|
|
const value = normalizedStyle[prop]
|
|
const cacheKey = getCacheKey(prop, value)
|
|
const exists = stylesCache[cacheKey] && stylesCache[cacheKey].id
|
|
if (!exists) {
|
|
const id = ++uniqueID
|
|
// add new declaration to the store
|
|
stylesCache[cacheKey] = {
|
|
id: `__style${id}`,
|
|
style: prefixAll({ [prop]: value })
|
|
}
|
|
}
|
|
})
|
|
|
|
return style
|
|
}
|
|
|
|
static getStyleAsNativeProps(styleSheetObject, canUseCSS = false) {
|
|
const classList = []
|
|
const normalizedStyle = normalizeStyle(styleSheetObject)
|
|
let style = {}
|
|
|
|
for (const prop in normalizedStyle) {
|
|
const value = normalizedStyle[prop]
|
|
const cacheKey = getCacheKey(prop, value)
|
|
let selector = stylesCache[cacheKey] && stylesCache[cacheKey].id || predefinedClassNames[cacheKey]
|
|
|
|
if (selector && canUseCSS) {
|
|
classList.push(selector)
|
|
} else {
|
|
style[prop] = normalizedStyle[prop]
|
|
}
|
|
}
|
|
|
|
return {
|
|
className: classList.join(' '),
|
|
style: prefixAll(style)
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = StyleSheetRegistry
|