ReactNative – FlatList

Son makalede, ListView’un kullanımını öğrendik ve üç farklı stilin liste görünümünü uyguladık.Her ne kadar ListView yaygın olarak kullanılsa da, birçok eksikliğe de sahiptir, örneğin, ayrı baş ve kuyruk bileşenlerini desteklememektedir, veri miktarı çok fazla olduğunda, bellek kullanımı önemli ölçüde artar, performans etkilenir ve çerçeve düşmesi meydana gelir. Böylece, React Native versiyonunun tekrarlamalı güncellemesi ile ListView, FlatList ve SectionList ile değiştirilir.FlatList gruplandırılmamış listeler için kullanılırken, SectionList liste uygulamalarını gruplandırmak için kullanılır. FlatList ve SectionList aşağıdaki avantajlara sahiptir:

Bu makalede, adım adım Douban filmlerine benzer bir liste görünümü uygulamak için FlatList’i kullanmayı öğreniyoruz. Öncelikle, FlatList’in ilgili özelliklerini anlamalıyız, resmi web sitesi dokümanlarına başvurabilir, çok detaylı açıklayabilir, burada sadece temel özellikleri açıklayabilirsiniz.

Veri – ListView Veri Kaynağından farklı olan veri kaynağı dizisi, FlatList’in veri kaynağı olarak doğrudan data özelliğine bir dizi ayarlayabilirsiniz, API daha basit ve kullanışlıdır.

keyExtractor – listedeki her bir öğe için benzersiz bir anahtar üretmek için kullanılan işlev Anahtarın rolü, aynı türdeki farklı bireyleri ayırt etmeyi, böylece yenileme sırasındaki ek yükü azaltarak değişikliğin konumunu belirleyebilmeyi sağlamaktır. . Bu işlevi belirtmezseniz, item.key varsayılan olarak anahtar değer olarak çıkarılır. İtem.key mevcut değilse, dizi alt dizinini kullanın. Bu özellik ListView’da mevcut değildir, FlatList ve SectionList’teki her öğe için benzersiz bir tanımlayıcı olarak kullanılır.

renderItem – Listedeki her veri satırına göre her satırın bileşenlerini işler . ListView’daki renderRow’a benzer şekilde, fark, FlatList’in keyExtractor belirtmesi gerektiği ve renderRow’un bu anahtara ihtiyacı olmadığıdır.

Yukarıdaki üç özellik ile bir liste görünümü uygulayabiliriz, ancak aşağıdaki özellikler çok önemlidir:

numColumns – Öğenin ızgara düzenini elde etmek için yatay olmayan modda sütun sayısını ayarlayın.Bu, ListView’den daha kullanışlıdır.FlexWrap’i artık ayarlamanıza gerek yoktur.

columnWrapperStyle – Çok sütunlu bir düzen ayarlanmışsa (yani, numColumns değeri 1’den büyük bir tamsayıya ayarlanmışsa), ek olarak, bu stilin her kap satırı için geçerli olduğunu belirtebilirsiniz. Örneğin, 4 satır ve 3 sütundan oluşan bir ızgaramız var, her satırda 3 öğe var, bu 3 öğe bir satırda görüntüleniyor, bu 3 öğenin bir kapsayıcı tarafından sarıldığını düşünebiliriz, columnWrapperStyle özelliği bu kabın stilini ayarlamaktır. , bu 3 öğenin kaptaki görüntüleme konumunu ayarlamak için kullanılır ve kullanıcı arayüzünü daha güzel hale getirir.

onEndReachedThreshold – İçeriğin altından bir mesafe olduğunda onEndReached geri aramaların nasıl tetikleneceğini belirler. Bu parametrenin piksel birimi yerine bir oran olduğunu unutmayın. Örneğin, 0.5, içeriğin tabanından mesafenin geçerli listenin görünür uzunluğunun yarısı olduğu anlamına gelir. Değer, 0 ile 1 arasında, 0 ile 1 arasındadır. Bu açıkça ListView’dan ayırt edilmelidir.

Tamam, yukarıda belirtilenler daha önemli özelliklerden bazılarıdır.Diğer özellikler için lütfen resmi belgelere bakın. Aşağıda gösterilen film listesini uygulamak için FlatList’in nasıl kullanılacağına bir göz atalım.

Bir film listesine ulaşmak için önce veriye sahip olmalıyız, burada Douban’ın açık arabirimini kullanarak film verilerini elde ediyoruz.

Öncelikle, proje kök dizininde src dizinini oluşturun ve genel sınıfları, UI arabirimlerini ve özel UI bileşenlerini depolamak için src dizininde ortak, ekran ve gereç dizinlerini oluşturun. Arayüz adresi:

 /// 查询正在上映的电影export function queryMovies(city, start, count) { return "https://api.douban.com/v2/movie/in_theaters?city=" + city + "&start=" + start + "&count=" + count } /// 查询即将上映的电影export function comingMovies(city, start, count) { return "https://api.douban.com/v2/movie/coming_soon?city=" + city + "&start=" + start + "&count=" + count } 复制代码 

Şehir bir şehir, kolaylık sağlamak için doğrudan Pekin’e yazıyoruz start parametresi verinin ilk birkaç veriden (başlangıçta 0’dan başlayarak) başladığını ve sayım her seferinde kaç veri yüklendiğini gösterir.

Uygulamada gereken renk değerlerini saklamak için bir Color.js dosyası tanımlayın.

 export default { themeColor: '#268dcd' , // 主题颜色separatorColor: '#e0e0e0' , // 分割线颜色backgroundColor: '#f3f3f3' // 背景色} 复制代码 

Böyle bir tabtabar anahtarının etkisini elde etmek için, tamamlamak için reaksiyon navigasyonunu kullanıyoruz. 

Proje kök dizinini bulun ve npm install --save react-navigation komutunu terminalde yazarak bağımlılık kütüphanesine girin. 

Başarısızsanız, yarn add react-navigation komutunu kullanabilirsiniz.

Kurulum tamamlandıktan sonra, ilk önce ilgili arayüzü oluşturacağız, ekran dizininde RootScreen, MovieListScreen. Aşağıdaki kodu basitçe yazabiliriz:

 import React, {Component} from 'react' ; import {View} from 'react-native' ; export default class MovieListScreen extends Component { render () { return ( <View/> ) } } 复制代码 

Etki şemasına göre, görüntülenen iki arayüzümüz var ve iki ekran görüntüleniyor, iki arayüz adresi iki arayüzün verisine karşılık geliyor, iki arayüzün döndürdüğü verilerin analizinden sonra iki arayüzün veri yapılarının tutarlı olduğu tespit edildi. Dolayısıyla, burada sadece bir MovieListScreen sayfası oluşturmamız gerekiyor, iki arayüz de bir js dosyasını paylaşıyor, kodun tekrarlanmasını önlemek için çağrılacak arayüzü ayırt etmek zorunda.

Zaten iki film sayfasının temel bir uygulamasına sahibiz ve şimdi iki liste sayfasını kök görünüm olarak kontrol etmek için bir tabBar kabına ihtiyacımız var. Burada RootScreen’i uygulamak için efekt gezinti kullanmanız gerekir.

İlk önce, TabNavigator bileşenini kullanarak bir sekme kabı oluşturacağız:

 const Tab = TabNavigator( { First: { screen: MovieListScreen, navigationOptions: ({navigation}) => ({ tabBarLabel: '正在热映' , tabBarIcon: ({focused, tintColor}) => ( <TabBarItemComponent tintColor={tintColor} focused={focused} normalImage={require( '../../assets/image/playing.png' )} selectedImage={require( '../../assets/image/playing-active.png' )} /> ) }), }, Second: { screen: MovieListScreen, navigationOptions: ({navigation}) => ({ tabBarLabel: '即将上映' , tabBarIcon: ({focused, tintColor}) => ( <TabBarItemComponent tintColor={tintColor} focused={focused} normalImage={require( '../../assets/image/coming.png' )} selectedImage={require( '../../assets/image/coming-active.png' )} /> ) }) } }, { tabBarComponent: TabBarBottom, tabBarPosition: 'bottom' , swipeEnabled: false , animationEnabled: false , lazy: true , tabBarOptions: { activeTintColor: Color.themeColor, inactiveTintColor: '#888888' , style: {backgroundColor: '#ffffff' } } } ); 复制代码 

Kaptaki Birinci ve İkinci’ye karşılık gelen ekranın MovieListScreen olduğunu görebilirsiniz.TabBarItemComponent, simgeleri ve metni görüntülemek için kullanılan özel bir tabItem bileşenidir. Sekme kabını oluşturduktan sonra, başlığı görüntülemek için bir gezinti çubuğuna da ihtiyacımız var ve bu gezinti çubuğu da sayfa gezinti rolünü oynuyor, StackNavigator bileşenini reaksiyon gezintiinde kullanmanız gerekiyor:

 const Navigator = StackNavigator( { Tab: {screen: Tab}, }, { navigationOptions: { headerBackTitle: null, headerTintColor: '#ffffff' , headerStyle: {backgroundColor: Color.themeColor}, showIcon: true } } ); 复制代码 

RootScreen’deki Render işlevinde, genel sayfa yapısının tamamlanması için Navigator bileşenini döndürmemiz gerekir.

 render () { return <Navigator/> } 复制代码 

Şimdi alt kısımda bir tabBar ve alt kısımda bir gezinti çubuğuna sahip bir sayfa yapısı elde ediyoruz.

Şimdi film listesini uygulama zamanı.

MovieListScreen’de verileri almak için arayüzü çağırmamız ve ardından uygun işlemden sonra verileri FlatList bileşenine atamamız gerekir. İlk olarak, yapıcı işlevinde durum verilerini oluşturun.

 constructor(props) { super(props); this.state = { movieList: [], // 电影列表的数据源loaded: false , // 用来控制loading视图的显示,当数据加载完成,loading视图不再显示}; } 复制代码 

Verileri elde etmek için arayüzü çağırmak için alma işlevini kullanın: İşte, yayınlanan film verisinin nasıl yükleneceği:

 /** * 加载正在上映的电影列表,此处默认城市为北京,取20条数据显示*/ loadDisplayingMovies () { let that = this; fetch(queryMovies( '北京' , 0, 20)).then((response) => response.json()).then((json) => { console.log(json); let movies = []; for ( let idx in json.subjects) { let movieItem = json.subjects[idx]; let directors = "" ; // 导演for ( let index in movieItem.directors) { // 得到每一条电影的数据let director = movieItem.directors[index]; // 将多个导演的名字用空格分隔开显示if (directors === "" ) { directors = directors + director.name } else { directors = directors + " " + director.name } } movieItem[ "directorNames" ] = directors; // 拼装主演的演员名字,多个名字用空格分隔显示let actors = "" ; for ( let index in movieItem.casts) { let actor = movieItem.casts[index]; if (actors === "" ) { actors = actors + actor.name } else { actors = actors + " " + actor.name } } movieItem[ "actorNames" ] = actors; movies.push(movieItem) } that.setState({ movieList: movies, loaded: true }) }).catch((e) => { console.log( "加载失败" ); that.setState({ loaded: true }) }).done(); } 复制代码 

ComponentDidMount öğesinde, geçerli sayfaya göre, karşılık gelen verileri elde etmek için hangi arabirimin çağrılacağını belirleyin.

 componentDidMount () { /// 根据routeName来判断当前是哪个界面,react-navigation中可以通过navigation.state.routeName来获取let routeName = this.props.navigation.state.routeName; if (routeName === 'First' ) { this.loadDisplayingMovies(); } else { this.loadComingMovies(); } } 复制代码 

İşte render işlevindeki sayfanın görüntülenmesi.

 render () { if (!this.state.loaded) { return ( <View style={styles.loadingView}> <ActivityIndicator animating={ true } size= "small" /> <Text style={{color: '#666666' , paddingLeft: 10}}>努力加载中</Text> </View> ) } return ( <FlatList data={this.state.movieList} renderItem={this._renderItem} keyExtractor={(item) => item.id} /> ) } 复制代码 

Arabirim isteği bitmeden önce, kullanıcının yüklemesini istemek için bir yükleme görünümü yaparız Arabirim çağrıldıktan sonra, yüklü alan true olarak ayarlanır, böylece render doğrudan FlatList’i görüntüler ve filmin kimliğini her satırın benzersiz tanımlayıcısı olarak kullanır. keyExtractor. renderItem her görünüm çizgisini oluşturur:

 _renderItem = (item) => { return ( <MovieItemCell movie={item.item} onPress={() => { console.log( '点击了电影----' + item.item.title); }}/> ) }; 复制代码 

MovieItemCell, her film verisini görüntüleyen özel bir satır görünümüdür. Kod burada yayınlanmamıştır, arka plan vurgulama bileşeni olarak TouchableHighlight kullanır, TouchableHighlight’ın, Görünüm ve TouchableOpacity kabı gibi diğer kontrolleri sarmak için bir kap olarak kullanılamayacağına dikkat edilmelidir.

Burada basit bir film listesi tamamlandı, özel demo adresi burada , detaylar sayfası ile basit uygulamanın tam sürümü burada . Genel olarak, React Native ile bir liste sayfasını uygulamak hala çok basittir: Bir sonraki bölümde, bu demoyu tek bir liste sayfasına dönüştürmek ve gösterilen ve gelecek olan filmleri gruplamak ve React Native ile ilgili içeriği öğrenmeye ve özetlemeye devam etmek için SectionList kullanıyoruz.

Çeviridir: https://juejin.im/post/5a90ca01f265da4e853d70cc

https://reactnativeexample.com/a-beautiful-and-customizable-material-design-bottom-navigation-for-react-native/

https://github.com/msal4/royal_news