Taro是京东凹凸实验室推出的一个框架,设计目的是多端统一开发解决方案,一次开发,多端运行
Taro可以使用React/Vue等前端框架开发的,当然typescript肯定是支持
Taro官方文档:https://taro-docs.jd.com/taro/docs/README
Taro官方组件库:https://taro-ui.jd.com/
Taro支持微信小程序,百度小程序,支付宝小程序,字节小程序,QQ轻应用,ReactNatvie等等
Taro 1.2支持将已有的微信小程序进行转换,只需要在项目根目录运行taro convert命令就可以在将现有的小程序项目转换到taroConvert目录下,转换成jsx代码,并且可以直接使用这个代码来进行taro build来编译成taro支持的平台应用
安装Taro框架
npm install -g @tarojs/cli
或者
yarn global add @tarojs/cli
升级框架
taro update self
创建项目
taro init hallo
创建h5项目
yarn dev:h5
创建微信小程序项目
yarn dev:weapp
创建完毕会在dist目录下生成小程序程序
支付宝小程序 yarn dev:alipay
百度小程序 yarn dev:swan
ReactNative yarn dev:rn
编译完成的端源码在dist目录下
作为一个可以使用react规范开发的框架,React Hooks和jsx也是支持的
Taro组件化(Taro可以使用react开发,因此也具备react的组件化功能)
import Taro, { useState } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import './index.less'
function Main(){
const [count ,setUserName] = useState("hallo word")
return (
<View>
<Text>{count}</Text>
</View>
)
}
export default Main
子组件
import { View, Text } from '@tarojs/components'
function Data(){
return (
<View><Text>hallo word</Text></View>
)
}
export default Data
如果使用类组件的话,需要导入Component基础类,并且类组件需要继承该基础类,例如:
import Taro, { Component } from '@tarojs/taro'
class Data extends Component{
config = {
navigationBarTitleText: 'hallo word'
}
render(){
return (
<View><Text>hallo word</Text></View>
)
}
}
export default Data
导入
import Data from ‘./data.jsx’
直接在父组件中使用就好
父组件传递参数给子组件
学过react都知道,父组件传递参数给子组件要通过props接收,因此子组件要加props参数
function Data(props){
return (
<View><Text>{props.count}</Text></View>
)
}
export default Data
Taro路由(通过app.jsx的pages,谁在第一个数组的值,那么该就是默认打开的首页)
taro路由是自带的,只需要在app.js入口文件配置config.pages(pages是数组),就可以使用taro的api来访问路由,例如:
pages: [
'pages/main/main',
'pages/data/data'
],
注意,不需要导入页面,Taro可以自动化完成
Taro 提供了6个路由api,分别是
navigateTo:记录上级页面,可以返回上级页面
redirectTo:不记录上级页面
switchTab:Tab之间进行切换
navigateBack:返回上一级页面
getCurrentPages:获取当前页面信息(页面栈),注意h5不支持
relaunch:销毁所有页面(关闭)
注意:微信小程序存在五层页面限制,要合理使用navigateTo和redirectTo
路由配合页面之间传递参数
发送参数
例如:
import Taro ,{useState} from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Main(){
const [data,setData] = useState("hallo")
const UrlIndex=()=>{
Taro.navigateTo({url:'/pages/index/index'+data})
}
return (
<View>
<Text>hallo word</Text>
<Button onClick={UrlIndex}>GO</Button>
</View>
)
}
export default Main
只需要在Index.jsx下接收就可,例如:
import Taro, { useState ,useEffect } from '@tarojs/taro'
...
const [data,setData] = useState('')
useEffect(()=>{
setData(this.$router.params.data)
},[])
...
<Text>{data}</Text>
多参数传递也是可以
const [data,setData] = useState("hallo")
const [name,setName] = useState("root")
const [pass,setPass] = useState("123")
const UrlIndex=()=>{
Taro.navigateTo({url:'/pages/index/index?data='+data+'&name='+name+'&pass='+pass})
}
接收多参数
const [data,setData] = useState('')
const [name,setName] = useState('')
const [pass,setPass] = useState('')
useEffect(()=>{
setData(this.$router.params.data)
setName(this.$router.params.name)
setPass(this.$router.params.pass)
},[])
...
<Text>{data}</Text>
<Text>{name}</Text>
<Text>{pass}</Text>
导入静态资源
import Taro ,{useState ,useEffect}from '@tarojs/taro'
import {View , Text ,Button, Image} from '@tarojs/components'
import {imgdata,cssdata} from '../../data' // 导入方法(函数)
import logo from '../../img/1.jpg' // 导入静态资源
useEffect(()=>{
imgdata()
cssdata()
},[])
...
<Image src={newbbd} width="300px" height="300px" />
或者
<Image src={require('../../img/1.jpg')} width="300px" height="300px" />
请求远程端口
const testData= ()=>{
Taro.request({
url:'https://xxx.xxx/xxx'
}).then(mainData=>{
console.log(mainData.data)
})
}
url是目标接口,then()是请求完毕获取到的数据
生命周期与state
Taro支持react的生命周期,另外Taro还为小程序补充了一些react不存在的生命周期,方便Taro开发小程序时使用
组件的生命周期
class Test extends Component{
constructor (props) {
// constructor会在组件挂载(组件渲染到Taro虚拟DOM之前)之前被执行
super(props)
this.state = {
data: 'admin'
}
}
componentWillMount (){
console.log('第一次渲染之前执行') // 组件被装载渲染之前执行
}
componentDidMount(){
console.log('第一次渲染之后执行') // 组件被装载渲染之后执行
this.setState({ data: 'root' }) // 修改state状态,需要通过setState方法来修改,而不是直接修改
}
componentWillUnmount(){
console.log('组件被销毁或者被卸载时执行')
}
componentWillUpdate(){
console.log('state数据更新前执行') // 当组件接收到新的state或者props,该钩子会在渲染之前执行,其中也可以接收2个参数,nextProps, nextState
}
componentDidUpdate(){
console.log('state数据更新后执行') // 当发送更新时执行。第一次渲染不会被触发
}
shouldComponentUpdate(nextProps, nextState){
// 表示该组件不受state状态或者props影响,通过返回值来表示是否在每次state状态更新时重新渲染,默认返回true
// 该钩子函数接收2个参数,分别是nextProps, nextState,分别表示最新的props和state
console.log(nextProps, nextState)
return false
}
componentWillReceiveProps(nextProps){
console.log('Props参数发生改变之前执行') // 当已被装载渲染的组件接收到新的props属性之前执行,nextProps参数表示最新的props属性
}
getSnapshotBeforeUpdate(){
console.log('在最近一次渲染之前执行') // 可用来组件渲染之前捕获数据
}
render(){
return(
<View>
<Text>hallo word {this.state.data}</Text>
</View>
)
}
}
Taro Props(父子组件通信)
子组件
export default class DataTest extends Component{
render(){
let {data} = this.props
return(
<View>
hallo {data}
</View>
)
}
}
父组件
import DataTest from './datatest'
export default class Test extends Component{
constructor (props) {
super(props)
this.state = {
data: 'admin'
}
}
render(){
let {data} = this.state.data
return(
<View>
<Text>hallo word</Text>
<DataTest data={data}/>
</View>
)
}
}
props默认值
DataTest.defaultProps = {
data: 'user'
}
注意:当props为undefined时,才将读取defaultProps的值作为props
条件渲染
三元表达式
{
true?<div>hallo wrod</div:<div>hhh</div>
}
短路表达式
{
!true||<div>hallo wrod</div>
}
列表渲染
state = {
list: [
{id:1,name:'root'},
{id:2,name:'abc'},
{id:3,name:'test'}
]
}
...
let {list} = this.state
...
{
list.map((item, index) =>{
return(<div key={index}>{item.name}</div>)
})
}
children传入组件
export default class Test extends Component{
render(){
return(
<View>
{
this.props.texts
}
{
this.props.children
}
</View>
)
}
}
调用的时候,直接在父组件使用就可以
return(
<View>
<Test texts={<div>hallo wrod</div>}></Test>
<Test>hallo 123</Test>
<Test>hallo 666</Test>
</View>
)
注意:不要对this.props.children进行任何操作,taro在小程序实现这个功能是利用了插槽Slot功能,而且this.props.children不能使用defaultProps进行设置默认,也不能拆分成变量进行使用,但是允许通过props自定义属性的方式传入组件
事件处理
state = {
name: 'root'
}
test(){
console.log(this.state.name)
}
render(){
return(
<View>
<Button onClick={this.test.bind(this)></Button>
</View>
)
}
taro事件函数有个默认参数,event,它指向该事件的具体,可通过event.stopPagenation()来阻止当前事件的事件冒泡
注意:taro的全部事件需要用on开头(而且组件传入参数是函数,这个函数也必须是on开头命名的),是为了小程序(因为小程序会认为是字符串),如果不做小程序可以忽略
taro判断当前环境是h5还是小程序(只限制开发环境,生产环境是无效的)
const ish5 = process.env.TARO_ENV == 'h5'
if(ish5){
require('./h5.less')
}else{
require('./noh5.less')
}
布局推荐使用flex布局
在taro应用typescript
为非ts项目安装ts依赖
npm install typescript –save
还需要配置tsconfig.json
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"removeComments": false,
"preserveConstEnums": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"jsxFactory": "Taro.createElement",
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
"outDir": "lib",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"sourceMap": true,
"baseUrl": ".",
"rootDir": ".",
"jsx": "preserve",
"typeRoots": [
"node_modules/@types",
"global.d.ts"
]
},
"compileOnSave": false
}
如果是新建项目,可以在初始化时指定需要使用typescript
编译ts文件完成,也是放到dist目录下