RN项目第二节 -- 首页实现

一、微组件的封装

每个页面的导航都会有不同的样式或者图片,为了实现代码的复用性,可以将导航统一封装成一个微小组件。 封装的Item需要有可点击事件,需要显示文字和图片。

import React, { PureComponent } from 'react'
import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native'

export default class NavigationItem extends PureComponent {
    render() {
    // 图片和文字时从外界传入的 所以用到props
        let icon = this.props.icon &&
            <Image style={[styles.icon, this.props.iconStyle]} source={this.props.icon} />

        let title = this.props.title &&
            <Text style={[styles.title, this.props.titleStyle]}>{this.props.title}</Text>
        return (
            <TouchableOpacity style={styles.container} onPress={this.props.onPress}>
                {icon}
                {title}
            </TouchableOpacity>
        );
    }
}

// 样式
const styles = StyleSheet.create({
    container: {
        flex:1,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
    },
    icon: {
        width: 27,
        height: 27,
        margin: 8,
    },
    title: {
        fontSize: 15,
        color: '#333333',
        margin: 8,
    }
});

再来分析每个页面都有不同的字体出现,比如说标题、段落、小标题。所以也可以将文字封装成单独的组件。

import React from 'react';
import ReactNative, { StyleSheet, Dimensions, Text ,ReactElement} from 'react-native'
import color from './color'

export function Heading1({style, ...props}) {
    return <Text style={[styles.h1, style]} {...props} />
}

export function Heading2({style, ...props}) {
    return <Text style={[styles.h2, style]} {...props} />
}

export function Paragraph({style, ...props}) {
    return <Text style={[styles.p, style]} {...props} />
}

//设置样式
const styles = StyleSheet.create({
    h1: {
        fontSize: 15,
        fontWeight: 'bold',
        color: '#222222',
    },
    h2: {
        fontSize: 14,
        color: '#222222',
    },
    p: {
        fontSize: 13,
        color: '#777777',
    },
});

将整个页面分为两部分,页面最下方是一个列表,可以当成是iOS中的tableView,而页面上方可以看做是头部的View,这个View里面存放了各种模块。模块之间会有分割线,可以将分割线也封装成组件。

import React, { PureComponent } from 'react'
import { View, Text, StyleSheet } from 'react-native'

import color from './color'

export default class SpacingView extends PureComponent {
    render() {
        return (
            <View style={styles.container}>
            </View>
        );
    }
}

// define your styles
const styles = StyleSheet.create({
    container: {
        height: 14,
        backgroundColor: color.background,
    },
});

在设置样式的时候,会用到全屏,因此可以把全屏幕的尺寸也封装起来。

import { Dimensions, Platform, PixelRatio } from 'react-native'

export default {
    width: Dimensions.get('window').width,
    height: Dimensions.get('window').height,
    onePixel: 1 / PixelRatio.get(),   //在iphone4+中代表一个像素点
    statusBarHeight: (Platform.OS === 'ios' ? 20 : 0)  //iOS平台状态栏默认为0,安卓平台默认为20
}

二、首页封装

1) 首页导航的实现 同样也是在navigationOptions调用箭头函数。返回标题、图片。当然左右两边可以返回已经封装好的NavigationItem属性。

static navigationOptions = ({ navigation }) => ({
        headerTitle: (
            <TouchableOpacity style={styles.searchBar}>
                <Image source={require('../../img/Home/search_icon.png')} style={styles.searchIcon} />
                <Paragraph>一点点</Paragraph>
            </TouchableOpacity>
        ),
        headerRight: (
            <NavigationItem
                icon={require('../../img/Home/icon_navigationItem_message_white.png')}
                onPress={() => {

                }}
            />
        ),
        headerLeft: (
            <NavigationItem
                title='福州'
                titleStyle={{ color: 'white' }}
                onPress={() => {

                }}
            />
        ),
        headerStyle: { backgroundColor: color.theme },
    })

2)列表的实现

首页要实现列表功能,采用组件FlatList。

  • 引用必要的组件
import color from '../../widget/color'
import NavigationItem from '../../widget/NavigationItem'
import SpacingView from '../../widget/SpacingView'
import screen from '../../common/screen'
import api from '../../api'
import { Heading1, Heading2, Paragraph } from '../../widget/Text'
  • 在render方法中返回FlatList并设置它的属性
render() {
        return (
            <View style={styles.container}>
                <FlatList
                    data={this.state.dataList}   //请求的数据
                    keyExtractor={this.keyExtractor} //设置每个item唯一的key
                    onRefresh={this.requestData}   //刷新的操作
                    refreshing={this.state.refreshing}   //刷新状态
                    ListHeaderComponent={this.renderHeader}  //头部页面展示
                    renderItem={this.renderCell}  //每个item
                />
            </View>
        );
    }
  • 存放的数据要在state中声明并指定属性。(类中)
state: {
        discounts: Array<Object>,
        dataList: Array<Object>,
        refreshing: boolean,
    }
  • 在构造函数中设置初始值,并绑定要实现的方法
constructor(props) {
        super(props)

        this.state = {
            discounts: [],
            dataList: [],
            refreshing: false,
        }

        { this.requestData = this.requestData.bind(this) }
        { this.renderCell = this.renderCell.bind(this) }
        { this.onCellSelected = this.onCellSelected.bind(this) }
        { this.keyExtractor = this.keyExtractor.bind(this) }
        { this.renderHeader = this.renderHeader.bind(this) }
        { this.onGridSelected = this.onGridSelected.bind(this) }
        { this.onMenuSelected = this.onMenuSelected.bind(this) }
    }
  1. 实现方法
  • keyExtractor设置每个item唯一的key
keyExtractor(item, index) {
        return item.id
    }
  • onRefresh对应的requestData方法做刷新的操作 每次请求数据,都要进行刷新,所以刷新的状态要改为true。而且要刷新之后,要刷新折扣版块和列表版块的内容。为了代码简洁,将这两个功能封装成方法
requestData() {
        //每次请求数据 都要进行刷新
        this.setState({ refreshing: true })
        //调用折扣
        this.requestDiscount()
        //调用推荐方法
        this.requestRecommend()
    }
  • 实现折扣模块的方法

这里使用ES7的的异步线程语法。await表示紧跟在后面的表达式需要等待结果。也就是说当执行到awiat的时候,执行器将交给其他线程,等执行权返回再从暂停的地方往后执行。 这里做的是请求数据的操作,用fetch函数传入api得到全部的折扣数据结果。然后再转化为json数据,接着把json中的data赋值给discounts数组。

 async requestDiscount() {
        try {
            let response = await fetch(api.discount)
            let json = await response.json()
            this.setState({ discounts: json.data })
        } catch (error) {
            alert('错误信息:'+error)
        }
    }
  • 实现推荐列表的方法

上图是从API中的recommend的url解析出来的json数据。选取需要的数据。在代码中用fetch将数据解析成json格式,取出data集合中的数据传入箭头函数中,一一赋值给指定变量之后返回给数组dataList。如此一来,就可以用setState方法改变数组的数据。

async requestRecommend(){
        try{
            let response = await fetch(api.recommend)
            let json = await response.json()
            let dataList = json.data.map(
                (info)=>{
                    return{
                        id:info.id,
                        imageUrl:info.squareimgurl,
                        title:info.mname,
                        subtitle:`$[{info.range}]${info.title}`,
                        price:info.price
                    }
                }
            )
            this.setState({
                dataList:dataList,
                refreshing:false,
            })
        }catch (error){
            this.setState({
                refreshing:false
            })
        }
    }

为了不影响渲染效果,可以将请求数据的方法放在componentDidMount方法中

componentDidMount() {
        this.requestData()
    }
  • 处理列表

在iOS或者其他编程语言中,会采用各类框架来防止代码冗余。最常用的是MVC模式。在本项目中,为了返回列表,可以先将列表的UI封装起来。

import React,{Component} from 'react'
import {View,Text,StyleSheet,TouchableOpacity,Image} from 'react-native'
import {Heading1,Paragraph}from '../../widget/Text'
import screen from '../../common/screen'
import color from '../../widget/color'
export default class GroupPurchaseCell extends Component{
    render(){
        let {info} = this.props
        let imageUrl = info.imageUrl.replace('w.h','160.0')
        return(
            <TouchableOpacity style={style.container} onPress = {()=>this.props.onPress(info)}>
                <Image source={{uri:imageUrl}} style={styles.icon}/>
                <View style={styles.rightContainer}>
                    <Heading1>{info.title}</Heading1>
                    <View>
                    </View>
                    <Paragraph numberOfLines={0} style={{ marginTop: 8 }}>{info.subtitle}</Paragraph>
                    <View style={{ flex: 1, justifyContent: 'flex-end' }}>
                        <Heading1 style={styles.price}>{info.price}元</Heading1>
                    </View>

                </View>
            </TouchableOpacity>
        )
    }
}
const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        padding: 10,
        borderBottomWidth: screen.onePixel,
        borderColor: color.border,
        backgroundColor: 'white',
    },
    icon: {
        width: 80,
        height: 80,
        borderRadius: 5,
    },
    rightContainer: {
        flex: 1,
        paddingLeft: 20,
        paddingRight: 10,
    },
    price: {
        color: color.theme
    }
});
  • 到首页中调用 引入框架
import GroupPurchaseCell from '../GroupPurchase/GroupPurchaseCell'

将数据传给cell并调用

renderCell(info) {
        return (
            <GroupPurchaseCell
                info={info.item}
                onPress={this.onCellSelected}
            />
        )
    }

实现cell的onPress方法

onCellSelected(info) {
        //把状态栏的样式给成暗色
        StatusBar.setBarStyle('default', false)
        //跳转到详情页面,并把本页信息传递给详情页
        this.props.navigation.navigate('GroupPurchase', { info: info })
    }

当点击cell的时候,导航会跳转到详情页面,那么就要把要跳转页面的名称传入到navigate中。

  • 为了测试,先简单封装详情页 建立一个.js文件GroupPurchaseScene,用来测试
import React, { Component } from 'react'
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, ListView, Image, InteractionManager } from 'react-native'

export default class GroupPurchaseScene extends Component {
    render(){
    return(
        <View>
            <Text>
                详情页面
            </Text>>
        </View>
    )
}
}
const Styles = StyleSheet.create({
    container: {
        flex:1,
        backgroundColor:'pink'
    }
})
  • 测试 在RootScene中引用详情页,并把它加入到导航当中
import GroupPurchaseScene from './scene/GroupPurchase/GroupPurchaseScene'
const Navigator = StackNavigator(
    {
        Tab: { screen: Tab },  //框架的页面
        // Web: { screen: WebScene }, //webview的页面
        GroupPurchase: { screen: GroupPurchaseScene },//详情页
    },

为了测试,先把首页的renderHeader()方法添加进去

renderHeader(){
        return(
            <View>
                <Text style={{fontSize:24}}>头部啊头部ddddddddddnihaoaha</Text>
            </View>
        )
    }

测试结果如下:

点击详情页也能跳转

  • 首页导航实现
static navigationOptions = ({ navigation }) => ({
        headerTitle: (
            <TouchableOpacity style={styles.searchBar}>
                <Image source={require('../../img/Home/search_icon.png')} style={styles.searchIcon} />
                <Paragraph>一点点</Paragraph>
            </TouchableOpacity>
        ),
        headerRight: (
            <NavigationItem
                icon={require('../../img/Home/icon_navigationItem_message_white.png')}
                onPress={() => {

                }}
            />
        ),
        headerLeft: (
            <NavigationItem
                title='福州'
                titleStyle={{ color: 'white' }}
                onPress={() => {

                }}
            />
        ),
        headerStyle: { backgroundColor: color.theme },
    })
  • 添加样式
searchBar: {
        width: screen.width * 0.7,
        height: 30,
        borderRadius: 19,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'white',
        alignSelf: 'center',
    },
searchIcon: {
        width: 20,
        height: 20,
        margin: 5,
    }
  • 封装头部

头部分为2个部分,一个是滚动的部分,另一个则是格子的部分。并且这两部分底部都有一个分割线。现在来封装这两个部分。 先封装最上方的部分,新建一个HomeMenuView.js。而这个部分又是由许多小的view组成的。所以将这些小的view也封装起来。新建一个文件HomeMenuItem。而这个类返回的只要是一个图片和文字即可。

import React, {Component } from 'react'
import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native'
import { Heading2 } from '../../widget/Text'
import screen from '../../common/screen'
export default class HomeMenuItem extends Component{
    render(){
        return(
            <TouchableOpacity
                style={styles.container}
                onPress = {this.props.onPress}
            >
                <Image source={this.props.icon} resizeMode='contain' style={styles.icon}/>
                <Heading2>
                    {this.props.title}
                </Heading2>

            </TouchableOpacity>
        );
    }

}

const styles = StyleSheet.create({
    container: {
        justifyContent: 'center',
        alignItems: 'center',
        width: screen.width / 5,
        height: screen.width / 5,
    },
    icon: {
        width: screen.width / 9,
        height: screen.width / 9,
        margin: 5,
    }
});

现在来封装HomeMenuView

这个View的主体是一个ScrollView和一个PageControl,当然RN中是没有特定的页面控制器的,所以该PageControl是需要自己封装的。把它放入widget组件中。

现在考虑PageControl需要什么属性。属性可以用propTypes来规定,然而最近React组件已经把PropTypes组件移除了React库,所以需要引入prop-types。import PropTypes from 'prop-types';

numberofPage:首先是各个组件能够分为多少页,这个是必须要传入的。规定为number类型。可以用isRequired来约束。 currentPage:当前页用来控制亮点会出现在哪一页,number类型。 hidesForSinglePage:当页面为1时,是否隐藏控制器,bool类型。 pageIndicatorTintColor:控制器上点的颜色,string类型。 currentPageIndicatorTintColor:当前亮点的颜色,string类型。 indicatorSize:指示器的大小,规定为object类型, indicatorStyle:指示器的样式,它是View规定的类型,所以规定为View.propTypes.style类型 currentIndicatorStyle:当前指示器的样式。同上 onPageIndicatorPress:点击指示器的处理时间,func类型。

引入头文件

import React, {Component } from 'react'
import { View, StyleSheet, TouchableWithoutFeedback } from 'react-native'
import assign from 'object-assign';
import PropTypes from 'prop-types';

在类中规定属性类型

 static propTypes = {
        numberOfPages: PropTypes.number.isRequired,
        currentPage: PropTypes.number,
        hidesForSinglePage: PropTypes.bool,
        pageIndicatorTintColor: PropTypes.string,
        currentPageIndicatorTintColor: PropTypes.string,
        indicatorSize: PropTypes.object,
        indicatorStyle: View.propTypes.style,
        currentIndicatorStyle: View.propTypes.style,
        onPageIndicatorPress: PropTypes.func
    }

给属性设置为默认值

static defaultProps = {
        numberOfPages: 0,
        currentPage: 0,
        hidesForSinglePage: false,
        pageIndicatorTintColor: 'gray',
        currentPageIndicatorTintColor: 'white',
        indicatorSize: { width: 8, height: 8 },
        indicatorStyle: {},
        currentIndicatorStyle: {},
        onPageIndicatorPress: function () { }
    }

实现方法

 onPageIndicatorPress(index) {
        this.props.onPageIndicatorPress(index);
    }

实现render方法

render() {
//解构赋值,取出所有的属性
        var { style, ...props } = this.props;
//给指示器设置默认的属性,备用
        var defaultStyle = {
            height: this.props.indicatorSize.height
        };
//设置每个小点的样式
        var indicatorItemStyle = {
            width: this.props.indicatorSize.width,
            height: this.props.indicatorSize.height,
            borderRadius: this.props.indicatorSize.height / 2,
            marginLeft: 5,
            marginRight: 5
        };
//指示器整体样式
        var indicatorStyle = assign({}, indicatorItemStyle, this.props.indicatorStyle, {
            backgroundColor: this.props.pageIndicatorTintColor
        });
//选中指示器的样式
        var currentIndicatorStyle = assign({}, indicatorItemStyle, this.props.currentIndicatorStyle, {
            backgroundColor: this.props.currentPageIndicatorTintColor
        });
//创建一个数组,将小点添加到pages里面。
        var pages = [];
        for (var i = 0; i < this.props.numberOfPages; i++) {
            pages.push(i);
        }
     //页面隐藏设置为真并且页面长度<=1时,返回null,否则返回一个个的小点。
        return (
            this.props.hidesForSinglePage && pages.length <= 1 ? null : <View style={[styles.container, defaultStyle, style]}>
            
 {/*从小点的集合中取出每个点,如果是当前的点就返回当前点样式,否则返回普通样式*/}
                {pages.map((el, i) => <TouchableWithoutFeedback key={i} onPress={this.onPageIndicatorPress.bind(this, i)}>
                        <View style={i == this.props.currentPage ? currentIndicatorStyle : indicatorStyle} />
                    </TouchableWithoutFeedback>
                )}
            </View>
        )
    }

现在可以做封装HomeMenuView的操作了 先把render函数要返回的东西梳理清楚

return (
 
  //scrollView里面要包含多个Item。将数组menuView添加到view里面
            <View style={styles.container}>
                <ScrollView contentContainerStyle={styles.contentContainer}
                    horizontal
                    showsHorizontalScrollIndicator={false}
                    pagingEnabled
                    onScroll={(e) => this.onScroll(e)}
                >
                    <View style={styles.menuContainer}>
                        {menuViews}
                    </View>
                </ScrollView>


                <PageControl
                    style={styles.pageControl}
                    numberOfPages={pageCount}
                    currentPage={this.state.currentPage}
                    hidesForSinglePage
                    pageIndicatorTintColor='gray'
                    currentPageIndicatorTintColor={color.theme}
                    indicatorSize={{ width: 8, height: 8 }}
                />
            </View>
        );

scrollview中包含的是menuView,也就是每个设置好样式的items。 在render方法的return方法之前,创建一个数组,该数组用来存放每个item。

render() {
        //取出属性中的menuinfos和onMenuSelected
        let { menuInfos, onMenuSelected } = this.props
        // 将属性传给每个HomeMenuitem
        let menuItems = menuInfos.map(
            (info, i) => (
                <HomeMenuItem
                    key={info.title}
                    title={info.title}
                    icon={info.icon}
                    onPress={() => {
                        onMenuSelected && onMenuSelected(i)
                    }} />
            )
        )
        //创建一个menuViews数组,用来表示每一页
        let menuViews = []
        //像上取整得到页数
        let pageCount = Math.ceil(menuItems.length / 10)

        for (let i = 0; i < pageCount; i++) {
            //slice() 方法可从已有的数组中返回选定的元素。start和end,表示一页放十个
            let items = menuItems.slice(i * 10, i * 10 + 10)
            // 一整页的
            let menuView = (
                <View style={styles.itemsView} key={i}>
                    {items}
                </View>
            )
            //加入到所有页面的数组
            menuViews.push(menuView)
        }
        //此处是省略的return 在上面已经写了
        }

上面return方法中要返回的PageControl要将currentPage传入进去,所以在MenuView应该先有一个状态机以便在用户滚动页面的时候实施修改。

 state: {
        currentPage: number
    }

    constructor(props) {
        super(props)

        this.state = {
            currentPage: 0
        }
    }

实现滚动的方法

onScroll(e) {
            //拿到x的偏移量
        let x = e.nativeEvent.contentOffset.x
              //用偏移量/宽度得到当前页数
        let currentPage = Math.round(x / screen.width)

        console.log('onScroll  ' + e.nativeEvent.contentOffset.x + '  page ' + currentPage + '  current ' + this.state.currentPage)
        if (this.state.currentPage != currentPage) {
                    //改变状态机

            this.setState({
                currentPage: currentPage
            })
        }
    }

设置样式

const styles = StyleSheet.create({
    container: {
        backgroundColor: 'white',
    },
    contentContainer: {
    },
    menuContainer: {
        flexDirection: 'row',
    },
    itemsView: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        width: screen.width,
    },
    pageControl: {
        margin: 10,
    }
});
  • 到首页中修改readerHeader方法 引入头文件
import HomeMenuView from './HomeMenuView'

将HomeMenuView添加到方法中去

renderHeader() {
        return (
            <View>
                <HomeMenuView menuInfos={api.menuInfo} onMenuSelected={this.onMenuSelected} />
                <SpacingView />
                <View style={styles.recommendHeader}>
                    <Heading2>猜你喜欢</Heading2>
                </View>
            </View>
        )
    }

设置样式

recommendHeader: {
        height: 35,
        justifyContent: 'center',
        borderWidth: screen.onePixel,
        borderColor: color.border,
        paddingVertical: 8,
        paddingLeft: 20,
        backgroundColor: 'white'
    },

接下来封装头部的第二部分 原理同第一部分类似,建立第二个部分的js文件HomeGridView和第二部分的每一小项HomeGridItem。

HomeGridItem:

export default class HomeGridItem extends PureComponent {
    render() {
        let info = this.props.info

        let title = info.maintitle
        let color = info.typeface_color
        let subtitle = info.deputytitle
        let imageUrl = info.imageurl.replace('w.h', '120.0')

        return (
            <TouchableOpacity style={styles.container} onPress={this.props.onPress}>
                <View>
                    <Heading1 style={{ color: color, marginBottom: 10 }}>{title}</Heading1>
                    <Heading2 >{subtitle}</Heading2>
                </View>

                <Image style={styles.icon} source={{ uri: imageUrl }} />
            </TouchableOpacity>
        );
    }
}

// define your styles
const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        width: screen.width / 2 - screen.onePixel,  //一行放两个,减去一个像素点
        height: screen.width / 4,
        backgroundColor: 'white',
        borderBottomWidth: screen.onePixel,
        borderRightWidth: screen.onePixel,
        borderColor: color.border
    },
    icon: {
        width: screen.width / 5,
        height: screen.width / 5,
    }
});

HomeGridView:

import React, { PureComponent } from 'react';
import { View, Text, StyleSheet } from 'react-native'
import color  from '../../widget/color'
import  screen from '../../common/screen'
import HomeGridItem from './HomeGridItem'

export default class HomeGridView extends PureComponent {
    //设定一个数组,用来接收数据
    static defaultProps = {
        infos: []
    }

    render() {
        return (
            <View style={styles.container}>
            //将infos赋值给Item
                {this.props.infos.map((info, index) => (
                    <HomeGridItem
                        info={info}
                        key={index}
                        onPress={() => this.props.onGridSelected(index)} />
                ))}
            </View>
        );
    }
}

// define your styles
const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        justifyContent: 'space-between',
        borderTopWidth: screen.onePixel,
        borderLeftWidth: screen.onePixel,
        borderColor: color.border
    },
});

在HomeScene中 引入头文件

import HomeGridView from './HomeGridView'

修改renderHeader方法,将gridView加入进去

<HomeGridView infos={this.state.discounts} onGridSelected={(this.onGridSelected)} />
 <SpacingView />

到构造函数中绑定onGridSelected和onMenuSelected

 { this.onGridSelected = this.onGridSelected.bind(this) }
        { this.onMenuSelected = this.onMenuSelected.bind(this) }

将这两个方法的原型写出来

onGridSelected(index) {

    }
    onMenuSelected(index) {
        alert(index)
    }

首页第一个界面完成,其余的页面放在之后讲解。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Web 开发

来聊聊 DOM 中的Node、Element、Text

1所表示的ELEMENT_NODE 很常见,我们平时用的 div 等标签,其类型都是 ELEMENT_NODE。

610
来自专栏前端说吧

js - 预加载+监听图片资源加载制作进度条

这两天遇到一个新需求:一个一镜到底的h5动画。因为功能的特殊性,就要求我们提前监听页面的静态图片是否全部加载完毕。即处理预加载。

1211
来自专栏逸鹏说道

C# 窗体常用API函数 应用程序窗体查找

常用的处理窗体的API函数如下(注意:API函数必须放在窗体中...): 使用C#语言,要引用DllImport,必须要添加using System.Runti...

4046
来自专栏hightopo

原 基于 HTML5 WebGL 的 3D

1354
来自专栏菩提树下的杨过

Office Open XML学习(1)-创建excel文档,并向单元格中插入字符串

做企业级应用,跟office打交道是少不了的。这里的Office不仅仅局限于微软的Office,还有第三方的Open Office之类。.Net传统的Offic...

2779
来自专栏Django中文社区

拓展 Django Pagination 实现完善的分页效果

在 使用 Django Pagination 实现简单的分页功能 中,我们实现了一个简单的分页导航效果。但想实现下面这样的一个比较完善的分页导航时,Django...

2876
来自专栏林德熙的博客

win10 uwp 分治法

算法涉及到了一个平面几何的知识。就是三角形p1p2p3的面积等于以下行列式的二分之一: % <![CDATA[ \begin{array}{cccc} | ...

541
来自专栏菩提树下的杨过

c#4.0中的动态编程

c#4.0中的dynamic早已不是新闻了,虽然内部用反射机制,略微会有一些性能上的额外开销,但是有些特殊场景还是很有用的,二害相权,取其轻吧(也正是因为这些动...

1818
来自专栏偏前端工程师的驿站

WebComponent魔法堂:深究Custom Element 之 从过去看现在

前言  说起Custom Element那必然会想起那个相似而又以失败告终的HTML Component。HTML Component是在IE5开始引入的新技术...

18310
来自专栏葡萄城控件技术团队

Wijmo 更优美的jQuery UI部件集:导出Wijmo的GridView到Excel

Wijmo GridView 控件不提供导出Excel文件的方法。本篇博客介绍一种将Wijmo的GridView控件保存到Excel的简单方法。你可以使用同样的...

2358

扫码关注云+社区