React Native(和React)的全新内容。
我有:
export default class MyApp extends Component {
// Initialize the hardcoded data
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'property1', 'property2', 'property3', 'property4'
])
};
}
render() {
return (
<View style={{flex: 1, paddingTop: 50}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Image style={styles.image} source={require('./images/' + {rowData} + '.jpg')} />}
/>
</View>
);
}
}
我正在尝试显示四个图像(存储在与索引相同的目录中的图像文件夹中)。我已经硬编码了图像名称(property1,property2等)。这给了我一个错误未知的命名模块:&#39; ./ images / [object Object] .jpg&#39;
查看官方文档(https://facebook.github.io/react-native/docs/images.html)中的图片页面我想先创建一个变量来存储完整路径,然后根据文档使用类似<Image source={path} />
的内容。
另外,建议为renderRow创建一个单独的函数吗?
答案 0 :(得分:1)
让我们回顾一下您问题的不同方面:
Unknown named module: './images/[object Object].jpg'
您正在将string
数组传递给dataSource
,因此rowData
中的renderRow
拥有字符串值是有意义的,您可以直接连接然而,到了'./images'
,你正在混合JavaScript和JSX&#39;上下文&#39; (因为没有更好的术语)。当你这样做时:
(rowData) => <Image style={styles.image} source={require('./images/' + {rowData} + '.jpg')}
无论你在{}
内传递什么,因为道具的价值被评估为JavaScript,所以source={require('./images/' + {rowData} + '.jpg')}
将是纯JavaScript。因此,当你将rowData
包裹在这个&#39; context&#39;中的花括号中时,你将它转换为一个对象,因为你正在使用新的ES6&#39;快捷键&#39;对于对象文字,你基本上做的是实例化一个具有值为rowData
的键rowData
的对象。从本质上讲,您的转换器正在执行以下操作:
(rowData) => <Image style={styles.image} source={require('./images/' + {rowData: rowData} + '.jpg')}
JavaScript尝试将对象转换为string
,作为课程[object Object]
的默认表示。我会用以下内容替换它(请注意,它在React Native中的图像处理方面仍然是错误的。我将在以后为提供解决方案):
(rowData) => <Image style={styles.image} source={require('./images/' + rowData + '.jpg')}
甚至更好:
(rowData) => <Image style={styles.image} source={require(
./图像/ $ {rowData} .JPG )}
您可以在MDN上阅读有关模板字符串的更多信息。
现在,对于图像的问题,如docs中所述,静态资产的名称必须是静态知道的(也就是说,在&#39; transpilation&#39; time),所以动态字符串连接生成的名称无效。我认为这样做的原因是可以识别应用程序中的所有资源,以便将它们打包在捆绑包中。
尽管如此,有一些简单的解决方法。在您的情况下,您可以执行以下操作:
const property1 = require('./images/property1.jpg');
const property2 = require('./images/property2.jpg');
const property3 = require('./images/property3.jpg');
const property4 = require('./images/property4.jpg');
const images = {property1, property2, property3, property4}; // ES6 literal objects. This basically means {property1: property1, property2: property2, ...
// Now images are known statically
export default class MyApp extends Component {
// Initialize the hardcoded data
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'property1', 'property2', 'property3', 'property4'
])
};
}
render() {
return (
<View style={{flex: 1, paddingTop: 50}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Image style={styles.image} source={images[rowData]} />}
/>
</View>
);
}
}
至于你的上一个问题:我说创建一个单独的功能只取决于&#39;尺寸&#39;函数:如果你只是在做一个简单的映射,就像在你发布的代码片段中那样,一个单独的函数是不可取的,因为这样的代码更具可读性。但是如果要进行2-3行计算,最好将功能包装在外部函数中。
答案 1 :(得分:0)
此示例取自我自己的项目,并且工作正常。
<Image style={styles.facebookImage} source={require('../statics/facebook-logo-white.png')}></Image>
设置源动态的方法是使用状态,如下所示:
<Image style={styles.facebookImage} source={require(this.state.imageRoute)}></Image>
当然,您必须正确设置状态组件,如下所示:
this.setState({imageRoute: 'your rute here'});
如果我是你,我会使用单独的renderRow函数,以使代码更具可重复性,尝试这样的事情:
_renderRow(rowData) {
return (
<Image style={styles.facebookImage} source={require(this.state.imageRoute)}></Image>
);
}
并且不要忘记包括像本地反应原生的图像:
import {
...
Image
} from 'react-native';
希望它对你有所帮助。
答案 2 :(得分:0)
基本上你不能用React Native做到这一点。您可能必须在文件顶部要求它们并将它们作为变量而不是动态路径使用它们。他们的开发团队引用了一句话:
我们故意不支持动态生成的图片名称,因为随着时间的推移管理资产变得非常困难,就像你不想做的那样,我需要做一个myComponent = require(&#39; ./ &#39; + libName + typeOfComponent);或类似的东西。像这样生成动态图片名称也不会使用我们正在推出的新动态资产管理系统,让您只需使用cmd + R即可添加和更新资产(不再需要添加到Xcode并重新编译)。