Taro与React的本质区别:

React中:一切皆组件
Taro中:小程序端区分页面与组件。配上页面路由的是页面,页面中被引用的自定义组件是组件

一、安装及使用:

参照官方文档 https://nervjs.github.io/taro/docs/GETTING-STARTED.html
视频学习 https://www.imooc.com/learn/1084

安装:

npm install -g @tarojs/cli
使用:
  1. 初始化系项目 taro init myApp

项目构建配置:

webp - Taro框架

  1. Taro可以在多个环境下dev项目
    webp - Taro框架
  2. 项目结构:
    webp - Taro框架
  • package.json 是依赖包
  • package.config.json 是给微信小程序单独提供的
  • config 是项目启动编译的配置文件的目录
  • dist 是编译好的目录
  • src 是原代码
    src目录下:
    1). index.html是为h5准备的
    2). app.js 即是小程序的入口,又是为h5做路由编译的路由文件(react本身是不需要配置路由的,但是需要在app.js里面配置页面地址)
    3). 在pages/index/index.js下编写纯h5标签也可以生效。但是在小程序中不适用。如果只做h5端可以把taro当成react用。如果适配多端,必须按照taro规范写代码
    webp - Taro框架
    webp - Taro框架
  1. 更改视图:Taro的数据更新,一定是异步的
    写法1:数据直接写成一个对象
    写法2:数据写在componentDidMount中用this.setState({})设置
    webp - Taro框架

import Taro, { Component } from '@tarojs/taro'
import { View, Text, Button } from '@tarojs/components'
import './index.less'

export default class Index extends Component {

  config = {
    navigationBarTitleText: '首页'
  }
  // 更改视图:数据写法1
  state = {
    name: 'Lida'
  }

  componentWillMount () { }

  componentDidMount () { 
    // 更改视图:数据写法2
    // this.setState({name: 'Lida'})
  }

  componentWillUnmount () { }

  componentDidShow () { }

  componentDidHide () { }

  click () {
    this.setState({name: 'Nazi'});
  }
 
  render () {
    return (
      <View className='index'>
        <Text>Hello world!</Text>
        <Text class="name">{this.state.name}</Text>
        <Button onClick={this.click}>Change_name</Button>
      </View>
    )
  }
}

同步更新数据写法:
更新数据之后,执行回调

webp - Taro框架
webp - Taro框架

  1. props 由父组件传给子组件的属性:
    props是只读属性,想要修改必须在父组件通过事件修改
    1). 首先定义子组件

import Taro, { Component } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'

// 定义class,继承Component
class Child extends Component {
    // render函数是必须实现的
    render () {
        return (
            <View>
                <Text>{this.props.name}</Text>
            </View>
        )
    }
}

// 给子组件一个默认值
Child.defaultProps = {
    name: ''
}
export default Child;

2). 在父组件中引入

import Child from './child'

<Child name="Child-Grey"></Child> 

给子组件<Child></Child>传一个name属性
3). 修改props

webp - Taro框架

子组件:

import Taro, { Component } from '@tarojs/taro'
import { View, Text, Button } from '@tarojs/components'
// import './index.less'

// 定义class,继承Component
class Child extends Component {
    clickHandler () {
        this.props.onchange();
    }

    // render函数是必须实现的
    render () {
        return (
            <View>
                <Text>{this.props.name}</Text>
                <Button onClick={this.clickHandler}>调用上层事件</Button>
            </View>
        )
    }
}

// 给子组件一个默认值
Child.defaultProps = {
    name: ''
}
export default Child;

父组件:

  change () {
    this.setState({name: '改变name值,起个中文名'})
  }

<Child name={this.state.name} onchange={this.change.bind(this)}></Child>
  1. Taro提供的UI框架——Taro UI
    cnpm install taro-ui@1.5.0 -D
    最新版本有bug,组件不能正常使用,文档未说明。
    npm安装这个框架会停滞
    官方文档 https://taro-ui.aotu.io/#/docs/introduction

注意事项:

  1. PX要大写,如果不大写会被转换成rem

二、其他(个人学习用)

值得记忆:

  1. 解构 赋值写法let {activity: [firstItem]} = this.state;
  2. Class类的概念Activity

class Activity extends Component {
    constructor () {
        // super() 作为函数调用。继承父函数以后必须要执行super(),super的this指向子函数Activity
        super(...arguments);
        this.state = {
            activity: [
                {
                    type: "cut",
                    info: [
                        {total: 48, cut: 10},
                        {total: 58, cut: 20},
                        {total: 100, cut: 30}
                    ]
                }
            ]
        }
    }
    render () {
        // 相当于取this.state中的activity中的数组中的第一个元素,命名为firstItem
        let {activity: [firstItem]} = this.state;

        return (
            <View className="activity">
                <Text className="type">{this.getTextByType(firstItem.type)}</Text>
                <Text>{this.getLine(firstItem.info)}</Text>
                <Text className="length">{this.state.activity.length}个活动</Text>
            </View>
        )
    }
}

  1. react中写法:

// cata.js
import Taro, { Component } from '@tarojs/taro'
import { View, Text, Image } from '@tarojs/components'
import './cata.less'

class Cata extends Component {
    constructor () {
        super(...arguments);
        this.state = {
            selectCata: null,  // 选中的分类
            cata: [
                {id: 1, name: '专场'},
                {id: 2, name: '热销'},
                {id: 3, name: '折扣'},
                {id: 4, name: '汉堡'},
                {id: 5, name: '炸鸡'},
                {id: 6, name: '饮品'}
            ]
        }
    }

    handlerClick (item) {
        if (this.state.selectCata && this.state.selectCata.id != item.id) {
            this.setState({ selectCata: item });
            console.log(this.state);
        } else if (!this.state.selectCata) {
            this.setState({ selectCata: item });
        }
    }

    render () {
        let {cata, selectCata} = this.state;

        return (
            <View className="cata">
                {/* 
                    1. .map()循环<Text></Text>
                    2. 把每一项的id传给key -> key={item.id}
                    3. 绑定class -> 如果selectCata存在 同时 selectCata.id == item.id,就添加class="select"
                    4. 对每一项添加点击事件 -> 将每一项的item传给回调函数
                    5. 回调函数内部逻辑:如果selectCata存在 同时 selectCata.id != item.id,就将当前项的item 传给 selectCata; 如果selectCata不存在就直接赋值。
                */}
                {
                    cata.map((item, index) => {
                        return <Text onclick={this.handlerClick.bind(this, item)} className={"cata-name " + ((selectCata && selectCata.id == item.id) ? 'select' : null)} key={item.id}>{item.name}</Text>
                    })
                }
            </View>
        )
    }
}

export default Cata;
  1. 兄弟组件间数据传递解决方案:
    1). 通过上级(父)的View组件
    webp - Taro框架

2). 通过事件监听,在组件1定义事件,在组件2监听事件执行事件函数
3). Redux

Taro框架