mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-01-12 22:51:09 +08:00
[add] support directly requiring image assets
Thanks to IjzerenHein <hrutjes@gmail.com>. See #84
This commit is contained in:
@@ -16,6 +16,25 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
## Image assets
|
||||
|
||||
In order to require image assets (e.g. `require('assets/myimage.png')`), add
|
||||
the `url-loader` to the webpack config:
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
module: {
|
||||
loaders: {
|
||||
test: /\.(gif|jpe?g|png|svg)$/,
|
||||
loader: 'url-loader',
|
||||
query: { name: '[name].[hash:16].[ext]' }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Web-specific code
|
||||
|
||||
Minor platform differences can use the `Platform` module.
|
||||
|
||||
@@ -36,6 +36,14 @@ suite('components/Image', () => {
|
||||
assert(backgroundImage.indexOf(defaultSource.uri) > -1)
|
||||
})
|
||||
|
||||
test('prop "defaultSource" with string value"', () => {
|
||||
// emulate require-ed asset
|
||||
const defaultSource = 'https://google.com/favicon.ico'
|
||||
const dom = utils.renderToDOM(<Image defaultSource={defaultSource} />)
|
||||
const backgroundImage = dom.style.backgroundImage
|
||||
assert(backgroundImage.indexOf(defaultSource) > -1)
|
||||
})
|
||||
|
||||
test('prop "onError"', function (done) {
|
||||
this.timeout(5000)
|
||||
utils.render(<Image
|
||||
@@ -50,10 +58,7 @@ suite('components/Image', () => {
|
||||
|
||||
test('prop "onLoad"', function (done) {
|
||||
this.timeout(5000)
|
||||
utils.render(<Image
|
||||
onLoad={onLoad}
|
||||
source={{ uri: 'https://google.com/favicon.ico' }}
|
||||
/>)
|
||||
utils.render(<Image onLoad={onLoad} source={{ uri: 'https://google.com/favicon.ico' }} />)
|
||||
function onLoad(e) {
|
||||
assert.equal(e.nativeEvent.type, 'load')
|
||||
done()
|
||||
@@ -91,7 +96,28 @@ suite('components/Image', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('prop "source"')
|
||||
test('prop "source"', function (done) {
|
||||
this.timeout(5000)
|
||||
const source = { uri: 'https://google.com/favicon.ico' }
|
||||
utils.render(<Image onLoad={onLoad} source={source} />)
|
||||
function onLoad(e) {
|
||||
const src = e.nativeEvent.target.src
|
||||
assert.equal(src, source.uri)
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
test('prop "source" with string value', function (done) {
|
||||
this.timeout(5000)
|
||||
// emulate require-ed asset
|
||||
const source = 'https://google.com/favicon.ico'
|
||||
utils.render(<Image onLoad={onLoad} source={source} />)
|
||||
function onLoad(e) {
|
||||
const src = e.nativeEvent.target.src
|
||||
assert.equal(src, source)
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
suite('prop "style"', () => {
|
||||
test('converts "resizeMode" property', () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* global window */
|
||||
import { NativeMethodsDecorator } from '../../modules/NativeMethodsMixin'
|
||||
import resolveAssetSource from './resolveAssetSource'
|
||||
import CoreComponent from '../CoreComponent'
|
||||
import ImageResizeMode from './ImageResizeMode'
|
||||
import ImageStylePropTypes from './ImageStylePropTypes'
|
||||
@@ -14,27 +15,32 @@ const STATUS_LOADING = 'LOADING'
|
||||
const STATUS_PENDING = 'PENDING'
|
||||
const STATUS_IDLE = 'IDLE'
|
||||
|
||||
const ImageSourcePropType = PropTypes.oneOfType([
|
||||
PropTypes.shape({
|
||||
uri: PropTypes.string.isRequired
|
||||
}),
|
||||
PropTypes.string
|
||||
])
|
||||
|
||||
@NativeMethodsDecorator
|
||||
export default class Image extends Component {
|
||||
static propTypes = {
|
||||
accessibilityLabel: CoreComponent.propTypes.accessibilityLabel,
|
||||
accessible: CoreComponent.propTypes.accessible,
|
||||
children: PropTypes.any,
|
||||
defaultSource: PropTypes.object,
|
||||
defaultSource: ImageSourcePropType,
|
||||
onError: PropTypes.func,
|
||||
onLoad: PropTypes.func,
|
||||
onLoadEnd: PropTypes.func,
|
||||
onLoadStart: PropTypes.func,
|
||||
resizeMode: PropTypes.oneOf(['contain', 'cover', 'none', 'stretch']),
|
||||
source: PropTypes.object,
|
||||
source: ImageSourcePropType,
|
||||
style: StyleSheetPropType(ImageStylePropTypes),
|
||||
testID: CoreComponent.propTypes.testID
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
accessible: true,
|
||||
defaultSource: {},
|
||||
source: {},
|
||||
style: {}
|
||||
};
|
||||
|
||||
@@ -42,7 +48,7 @@ export default class Image extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
const { uri } = props.source
|
||||
const uri = resolveAssetSource(props.source)
|
||||
// state
|
||||
this.state = { status: uri ? STATUS_PENDING : STATUS_IDLE }
|
||||
// autobinding
|
||||
@@ -51,13 +57,13 @@ export default class Image extends Component {
|
||||
}
|
||||
|
||||
_createImageLoader() {
|
||||
const { source } = this.props
|
||||
const uri = resolveAssetSource(this.props.source)
|
||||
|
||||
this._destroyImageLoader()
|
||||
this.image = new window.Image()
|
||||
this.image.onerror = this._onError
|
||||
this.image.onload = this._onLoad
|
||||
this.image.src = source.uri
|
||||
this.image.src = uri
|
||||
this._onLoadStart()
|
||||
}
|
||||
|
||||
@@ -113,9 +119,10 @@ export default class Image extends Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.source.uri !== nextProps.source.uri) {
|
||||
const nextUri = resolveAssetSource(nextProps.source)
|
||||
if (resolveAssetSource(this.props.source) !== nextUri) {
|
||||
this.setState({
|
||||
status: nextProps.source.uri ? STATUS_PENDING : STATUS_IDLE
|
||||
status: nextUri ? STATUS_PENDING : STATUS_IDLE
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -135,8 +142,7 @@ export default class Image extends Component {
|
||||
} = this.props
|
||||
|
||||
const isLoaded = this.state.status === STATUS_LOADED
|
||||
const defaultImage = defaultSource.uri || null
|
||||
const displayImage = !isLoaded ? defaultImage : source.uri
|
||||
const displayImage = resolveAssetSource(!isLoaded ? defaultSource : source)
|
||||
const backgroundImage = displayImage ? `url("${displayImage}")` : null
|
||||
const style = StyleSheet.flatten(this.props.style)
|
||||
|
||||
|
||||
5
src/components/Image/resolveAssetSource.js
Normal file
5
src/components/Image/resolveAssetSource.js
Normal file
@@ -0,0 +1,5 @@
|
||||
function resolveAssetSource(source) {
|
||||
return ((typeof source === 'object') ? source.uri : source) || null
|
||||
}
|
||||
|
||||
export default resolveAssetSource
|
||||
Reference in New Issue
Block a user