2019-01-03 16:01:30 Fakin 阅读数 199
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57545 人正在学习 去看看 李宁

通过前几篇文章的阅读,相信我们对react是什么,react能做什么,react怎么做,有了一个大致的了解了,后面我们还补充了redux和router的文章,在两个库的加持下,写一个简单的应用是完全没问题的。

Fakin-Toutiao

github:https://github.com/CuteFakin/Fakin-Toutiao

技术栈:React+React-Router+Redux+axios

已完成

  • 首页
  • 文章详情页(推荐列表,评论列表)
  • 搜索列表页面

说明:目前项目是能看了,分类还是没有写完
虽然样式是仿今日头条的,但是apihttps://news.baidu.com ,
分析自【百度新闻移动端】这个接口有些小问题,例如返回的图片url有时候错误,文章日期错误等,并且是FormData

剩下的页面基本上也就是复制粘贴的事情了,重复的逻辑,重复的操作,并不复杂!

技术要点:

  • 跨域 (这里不多过解释,很简单)
  • redux和router的引用(可以仔细看代码)
  • redux-persist(数据持久化,在reudx的注释代码中有,默认是注释了)
  • 组件的异步加载
  • 今日头条的菜单特色功能

在这里插入图片描述
比如,现在是’历史’,如果你点击’军事’,历史就会和军事交换位置

实现思路:
一个大菜单一个小菜单,不同的页面传递不同的数据让’历史’这个菜单显示不同的数据。当用户点击小菜单中的任何一行,把小菜单的当前项传递给大菜单作为最后一项,把大菜单的当前项传递给小菜单。

 nromalMenulist(list) {
        let url = this.props.url;
        if (!url) {
            return
        }
        let clist = [...this.state.c_list];//小菜单
        let fList = [...this.state.list];//大菜单
        list.forEach((item, index) => {
            if (url.url === item.url) {//找到当前页面在小菜单数组中的位置
                let lastItem = fList.pop();//返回大菜单删除的项目
                fList.push(item);//大菜单插入当前小菜单
                clist.splice(index, 1, lastItem);//删除菜单中当前页面,并插入默认的搞笑页面
                this.setState({//重新设置小菜单和默认的页面
                    c_list: clist,
                    list: fList
                })
            }
        })
    }
2016-07-31 18:15:12 jj120522 阅读数 7024
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57545 人正在学习 去看看 李宁

      今日头条应用想必大家应该都不陌生,绝对称得上今日之星。媒体上面已经所向披靡,PK掉微信公众号是迟早的事情,我祝今日头条再创辉煌!

      首先我们先看下今日头条的首页:

      

      这里提到一个开源框架:react-native-scrollable-tab-view,类似于安卓中的ViewPagerIndicator+ViewPager等,下面我简单介绍下如何应用以及如何来拓展实现我们想要的效果.

      首先我们先把框架拉进来:npm install react-native-scrollable-tab-view --save 虽说安卓现在用gradle来集成第三方框架方便的许多,但感觉还是react相对简单方便。然后我们就可以引用框架的相关元素。这里用到框架内部的ScrollableTabView,ScrollableTabBar两个组件.其实框架内部还有其他的组件:DefaultTabBar,FacebookTabBar等.

<ScrollableTabView
      initialPage={0}
      scrollWithoutAnimation={true}
      renderTabBar={()=><ScrollableTabBar
                    underlineColor='#ce3d3a'
                    activeTextColor='#fff'
                    inactiveTextColor='rgba(255, 255, 255, 0.7)'
                    underlineHeight={0}
                    textStyle={{ fontSize: 15 }}
                    tabStyle={{ paddingBottom: 0 }}
                    backgroundColor='#ce3d3a'
                    tabStyle={{paddingLeft:12,paddingRight:12}}
                   />}
      >
     <View tabLabel='推荐' style={styles.itemLayout}><Text >推荐板块</Text></View>
     <View tabLabel='头条号'  style={styles.itemLayout}><Text>头条号板块</Text></View>
     <View tabLabel='热点' style={styles.itemLayout}><Text >热点板块</Text></View>
     <View tabLabel='视频'  style={styles.itemLayout}><Text >视频板块</Text></View>
     <View tabLabel='上海'  style={styles.itemLayout}><Text >上海板块</Text></View>
     <View tabLabel='社会'  style={styles.itemLayout}><Text >社会板块</Text></View>
     <View tabLabel='图片'  style={styles.itemLayout}><Text >图片板块</Text></View>
     <View tabLabel='娱乐'  style={styles.itemLayout}><Text >娱乐板块</Text></View>
     <View tabLabel='科技'  style={styles.itemLayout}><Text >科技板块</Text></View>
     <View tabLabel='汽车'  style={styles.itemLayout}><Text >汽车板块</Text></View>
     </ScrollableTabView>

 至此,我们就简单了实现了整个框架,但是右上角的添加搜索按钮如何加上去呢,这就使得我们不得不拓展第三方的框架,首先我们先了解下加入的框架内部结构:


我们要做的就是在ScrollableTabBar.js中的render方法相应的位置加入我们的自定义的按钮组件.

下面我们就自定义添加和搜索两个按钮的TitleButton组件.相对比较简单.

render(){
     return(
       <View style={[styles.titleBar,this.props.style]}>
        <TouchableOpacity style={{flex:1}} onPress={()=>alert('add')}>
        <Image resizeMode='contain' style={styles.search} source={require('../images/add_channel_titlbar.png')}/>
        </TouchableOpacity>
        <TouchableOpacity style={{flex:1}} onPress={()=>alert('search')}>
        <Image style={[styles.search,{width:30,height:30,}]} source={require('../images/white_search_titlebar.png')}/>
        </TouchableOpacity>
       </View>
     );
   }

接下来我们打开第三方框架中ScrollableTabBar,将我们的TitleButton组件加入进去。注意布局是position,其实就达到覆盖在原有的组件上面。

return  <View
      style={[styles.container, {backgroundColor: this.props.backgroundColor, }, this.props.style]}
      onLayout={this.onContainerLayout}
    >
      <ScrollView
        ref={(scrollView) => { this._scrollView = scrollView; }}
        horizontal={true}
        showsHorizontalScrollIndicator={false}
        showsVerticalScrollIndicator={false}
        directionalLockEnabled={true}
        bounces={false}
      >
        <View
          style={[styles.tabs, {width: this.state._containerWidth, }, this.props.tabsContainerStyle]}
          ref={'tabContainer'}
          onLayout={this.onTabContainerLayout}
        >
          {this.props.tabs.map((tab, i) => this.renderTabOption(tab, i))}
          <Animated.View style={[tabUnderlineStyle, dynamicTabUnderline, ]} />
        </View>
      </ScrollView>
     <TitleButton style={{height:49,position:'absolute',top:0,right:0}}/>
    </View>;
到这里我们就完成了整个模拟的过程.

效果图:

         

      Tips:在安卓手机上操作有卡顿现象,但在ios上面操作挺流畅的,不过整体来说还是不错的,希望Fackbook尽快完善React,使其的性能尽可能的流畅!!!


   源码链接


 RN开发群:527459711.欢迎大伙加入.








    

2019-02-26 11:03:48 kisty_yao 阅读数 146
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57545 人正在学习 去看看 李宁

前言

上次初学用 react 写了个后台管理,这次便寻思写个移动端的项目。便有了这次的这个项目。

这个项目以前写了个 vue 的版本。有兴趣的可以 点击进入


模拟数据用的是 Easy Mock

用的是我以前写 vue-toutiao 用到的数据

账号: vue-toutiao

密码: 123456

技术栈

react + react-redux + react-router + webpack

结构:

  • build: webpack配置
  • config: 项目配置参数
  • src
    1. actions: 存放 action 方法
    2. assets: 静态资源文件,存放图片啥的
    3. components: 常用组件
    4. reducers: 存放 reducer
    5. router: 路由管理
    6. store: 状态管理 redux
    7. styles: 样式文件
    8. utils: 常用封装
    9. views: 视图页面
  • static: 静态文件: 存放 favicon.ico 等等

效果演示

 

图片描述

 

 

 

图片描述

 

 

知识点

按需加载

通过 import() 方法加载组件, 在通过高阶组件处理 import 返回的 Promise 结果。

// asyncComponent.js
import React from 'react'

export default loadComponent => (
    class AsyncComponent extends React.Component {
        state = {
            Component: null,
        }
        async componentDidMount() {
            if (this.state.Component !== null) return
            try {
                const {default: Component} = await loadComponent()
                this.setState({ Component })
            }catch (err) {
                console.error(`Cannot load component in <AsyncComponent />`);
                throw err
            }
        }

        render() {
            const { Component } = this.state
            return (Component) ? <Component {...this.props} /> : null
        }
    }
)

复制代码

如下使用

import asyncComponent from './asyncComponent'
const Demo = asyncComponent(() => import(`views/demo.js`))
<Route path="/demo" component={Demo}/>
复制代码

路由设置

统一配置路由,及路由状态

import asyncComponent from './asyncComponent'
const _import_views = file => asyncComponent(() => import(`views/${file}`))
export const loyoutRouterMap = [
    { 
        path: '/', 
        name: '首页', 
        exact: true,
        component: _import_views('Home')
    },
    { 
        path: '/video', 
        name: '视频',
        component: _import_views('Video')
    },
    { 
        path: '/headline', 
        name: '微头条',
        component: _import_views('Headline')
    },
    { 
        path: '/system', 
        name: '系统设置',
        auth: true, 
        component: _import_views('System')
    }
] 
复制代码

登录拦截

通过路由配置中 auth 属性来判断是否需要登录 如以下配置

{ 
    path: '/system', 
    name: '系统设置',
    auth: true, 
    component: _import_views('System')
}
复制代码

登陆配置及判断

// authRoute.js
import React from 'react'
import store from '../store'
import { Route, Redirect } from 'react-router-dom'

export default class extends React.Component {
    render () {
        let {component: Component, ...rest} = this.props
        // 是否登录
        if (!store.getState().user.user.name) {
            return <Redirect to='/login' />
        }
        return <Route {...rest}  component={Component}/>
    }
}


// 生成route
const renderRouteComponent = routes => routes.map( (route, index) => {
    if (route.auth) { // 需要权限登录
        return <AuthRoute key={index} {...route}/>
    }
    return <Route key={index} {...route}/>
})
复制代码

路由动画

通过 react-router-transition 做的切换动画。

然后通过 history.slideStatus 来判断如何动画

react-router-transition 具体API

redux-thunk处理action异步

redux-actions 来书写 action 跟 reducer

// action.js
import { createAction } from 'redux-actions'
import axios from 'utils/axios'
export const getHeadlineList = (params) => dispatch => {
    return new Promise( (resolve, reject) => {
        axios.get('headline/list', params)
            .then( res => {
                const list = res.data.list
                dispatch(createAction('GET_HEADLINE_LIST')(list))
                resolve(list)
            }).catch( err => {
                reject(err)
            })
    })
}

// reducer.js
import { handleActions } from 'redux-actions'
import { combineReducers } from 'redux'
const state = {
    headlineList: []
}
const headline = handleActions({
    GET_HEADLINE_LIST: (state, action) => {
        let list = action.payload
        state.headlineList = state.headlineList.concat(list)
        return {...state}
    }
}, state)
export default combineReducers({
    headline
})

// store.js  
// redux-thunk配置
import { createStore, compose, applyMiddleware  } from 'redux'
import reducer from '../reducers'
import thunk from 'redux-thunk'
const configureStore => createStore(
    reducer,
    compose(
        applyMiddleware(thunk)
    ) 
)
export default configureStore()

复制代码

还有一些零零散散的知识点,就不介绍了,具体可以到 github 上查看。

github

个人博客

在线观看地址


作者:cd-dongzi
链接:https://juejin.im/post/5aca3be56fb9a028e46eeb69
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2017-09-18 11:56:45 y191114690 阅读数 2101
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57545 人正在学习 去看看 李宁

看了慕课网上实战课程React 模仿大众点评 webapp来学习React

1.webpack配置

这里写图片描述
绿色的选择压缩版,省事用msi安装一路next就好
安装好了在cmd中输入node -v查看版本
如果出现安装成功反之安装失败
npm在安装node的时候已经安装好了
输入npm -v查看
国内的话用淘宝的npm镜像
cnpm安装包的时候会快一点
安装webpack
这里写图片描述
安装React
这里写图片描述

–save 和 –save-dev 的区别

npm i时使用–save和–save-dev,可分别将依赖(插件)记录到package.json中的dependencies和devDependencies下面。

dependencies下记录的是项目在运行时必须依赖的插件,常见的例如react jquery等,即及时项目打包好了、上线了,这些也是需要用的,否则程序无法正常执行。

devDependencies下记录的是项目在开发过程中使用的插件,例如这里我们开发过程中需要使用webpack打包,而我在工作中使用fis3打包,但是一旦项目打包发布、上线了之后,webpack和fis3就都没有用了,可卸磨杀驴。

延伸一下,我们的项目有package.json,其他我们用的项目如webpack也有package.json,见./node_modules/webpack/package.json,其中也有devDependencies和dependencies。当我们使用npm i webpack时,./node_modules/webpack/package.json中的dependencies会被 npm 安装上,而devDependencies也没必要安装。

配置 webpack.config.js

为了提高学习效率,webpack 最最基础的用法,就不再挨个演示了(推荐一个非常好的入门文章,以及更多资料)这里我们把项目中的webpack.config.js这个配置文件详细的讲解一下,过程中也会照顾 0 基础的同学。

文件格式

webpack.config.js 就是一个普通的 js 文件,符合 commonJS 规范。最后输出一个对象,即module.exports = {…}

输入 & 输出

这个比较基础,不过需要新建./app/index.jsx作为入口文件,目前项目中只有这一个入口文件。不过 webpack 支持多个入口文件,可查阅文档。
输出就是一个bundle.js,js 和 css 都在里面,不过只有在开发环境下才用,发布代码的时候,肯定不能只有这么一个文件,接下来会讲到。

module

针对不同类型的文件,使用不同的loader,当然使用之前要安装,例如npm i style-loader css-loader –save-dev。该项目代码中,我们用到的文件格式有:js/jsx 代码、css/less 代码、图片、字体文件。
less 是 css 的语法糖,可以更高效低冗余的写 css,不熟悉的朋友可去官网看看,非常简单。
在加载 css/less 时用到了postcss,主要使用autoprefixer功能,帮助自动加 css3 的浏览器前缀,非常好用。
编译 es6 和 jsx 语法时,用到家喻户晓的babel,另外还需增加一个.babelrc的配置文件。

plugins

使用 html 模板(需要npm i html-webpack-plugin –save-dev),这样可以将输出的文件名(如./bundle.js)自动注入到 html 中,不用我们自己手写。手写的话,一旦修改就需要改两个地方。
使用热加载和自动打开浏览器插件

devServer

对 webpack-dev-server 的配置

npm start

在 package.json 中,输入以下代码,将这一串命令封装为npm start,这样就可以运行项目代码了。

  "scripts": {
    "start": "NODE_ENV=dev webpack-dev-server --progress --colors"
  }

代码中NODE_ENV=dev代表当前是开发环境下,这里的”dev”可被 js 代码中的process.env.NODE_ENV得到并做一些其他处理。

定义环境全局变量

以下定义,可使得代码通过DEV得到当前是不是开发模式。

    new webpack.DefinePlugin({
      __DEV__: JSON.stringify(JSON.parse((process.env.NODE_ENV == 'dev') || 'false'))
    })

打开./app/util/localStore.js可以看到if (DEV) { console.error(‘localStorage.getItem报错, ‘, ex.message) },即只有开发环境下才提示error,发布之后就不会提示了。(因为发布的命令中用到NODE_ENV=production)

配置 webpack.production.config.js

开发环境下,可以不用考虑系统的性能,更多考虑的是如何增加开发效率。而发布系统时,就需要考虑发布之后的系统的性能,包括加载速度、缓存等。下面介绍发布用配置代码和开发用的不一样的地方。
发布到 ./build 文件夹中
path: __dirname + “/build”,

vendor

将第三方依赖单独打包。即将 node_modules 文件夹中的代码打包为 vendor.js 将我们自己写的业务代码打包为 app.js。这样有助于缓存,因为在项目维护过程中,第三方依赖不经常变化,而业务代码会经常变化。

md5后缀

为每个打包出来的文件都加md5后缀,例如”/js/[name].[chunkhash:8].js”,可使文件强缓存。

分目录

打包出来的不同类型的文件,放在不同目录下,例如图片文件将放在img/目录下

自动为打包出来的代码增加 copyright 内容

分模块

new webpack.optimize.OccurenceOrderPlugin(),

压缩代码

使用 Uglify 压缩代码,其中warnings: false是去掉代码中的 warning

分离 css 和 js 文件

开发环境下,css 代码是放在整个打包出来的那个 bundle.js 文件中的,发布环境下当然不能混淆在一起,使用new ExtractTextPlugin(‘/css/[name].[chunkhash:8].css’),将 css 代码分离出来。

npm run build

打开package.json,查看以下代码。npm start和npm run build分别是运行代码和打包项目。另外,”start”、”test”可以不用run。

  "scripts": {
    "start": "NODE_ENV=dev webpack-dev-server --progress --colors",
    "build": "rm -rf ./build && NODE_ENV=production webpack --config ./webpack.production.config.js --progress --colors"
  },

这两个命令主要有以下区别:
前者中默认使用 webpack.config.js 作为配置文件,而后者中强制使用 webpack.production.config.js 作为配置文件
前者NODE_ENV=dev而后者NODE_ENV=production,标识不同的环境。而这个”dev” “production”可以在代码中通过process.env.NODE_ENV获取。

最小化压缩 React

以下配置可以告诉 React 当前是生产环境,请最小化压缩 js ,即把开发环境中的一些提示、警告、判断通通去掉,直流以下发布之后可用的代码。

    new webpack.DefinePlugin({
      'process.env':{
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
      }
    }),
2019-07-02 16:17:54 sinat_17775997 阅读数 168
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57545 人正在学习 去看看 李宁

用react模仿知乎的用户头像裁剪组件

前段时间刷知乎的时候,更换换了下头像,突然发现知乎头像编辑器很简洁酷炫,于是乎就用react尝试模仿做一个组件。

知乎上的这个是用canvas处理的,但是用div做也是可以,简单的布局一下,其实就是用几个div而已,但是呢,有个点我这里的。阴影层下的图片跟清晰的图片是两张图片,只是用top,left定位让这两张图片看起来像一张图片。

 

 

 

这个组件首先是要用到拖拽的功能,网上找的包感觉都不太合适,于是自己就简单封装了一个,现在已经发布到npm(react-simple-draggable),githup地址

由于我封装的拖拽组件可以限定的拖拽的区域,所以就可以很容易的动态设置,拖拽显示的无非就是图片大小的区域,初始化的时候,规定宽或者高是100%,高度或者宽度自适应,因为图片为长方形的时候,有横向的和竖向的,我们可以一开始获取图片的宽高,判断是横向的还是竖向的

 

 

 

除此之外,还要获取到图片的真实大小的size,因为要是提交的使用总不能把,‘100%’,‘auto’这些提交到后端。

 

 

 

完成初始化的逻辑并不太复杂,下面到放大缩小的逻辑了。放大缩小的逻辑其实也很简单,无非就是把放大缩小的比例乘于原始的宽度,但是放大缩小后的图片的可拖拽区域也要发生变化:

 

 

 

至于为什么加上要用80(图片的中点)去乘于比值的差(preRatio是前一次拖拽的比例)是为了让图片放大缩小是以图片中心的位置为原点,这样视觉效果会好看很多。此外,这里还处理了一些特殊的情况,比如说,缩放的时候,图片的位置可能会不在可视区的区域内,所以要做一些限制,当left的绝对值小于图片的宽度时,就是偏离了可视区域,这里要做一下修正。

如果想使用这个组件可以clone下来,参考demo中的例子,把lib下的文件复制到你的项目中就可以使用了(这个组件已经打包好了),但是出现问题作者概不负责- -!您也可以基于作者的基础再做修改(src文件夹下),每次修改记得npm run build(npm start 是打包demo) 打包下哦!

这个小组件已经上传到githup上了,这里是demo的地址,这里是githup的地址,欢迎提issue!路过希望帮忙点个star哦!

日积月累,一起成长!

原文https://zhuanlan.zhihu.com/p/67155526

今日头条血槽已空

阅读数 1038

没有更多推荐了,返回首页