taro使用教程(详细版)
Taro框架的简介和开篇介绍
Taro是由京东凹凸实验室推出的框架,目的就是解决多端混乱的局面,也是当下比较新兴的一个框架。
当我们按照一种模式一种代码进行开发,开发完成后,项目就有了在任何终端显示的能力,这是一种想想都很爽的。那具体Taro有那些优点,请看下面的图片。
目前Taro支持的终端
- 微信小程序
- H5 移动端Web页面
- 百度小程序
- 支付宝小程序
- 快应用
- ReactNative
- 字节跳动小程序
- QQ轻应用
是目前支持小程序最多的前端框架,并且支持ReactNatvie,说明我们可以轻易的生成媲美原生的APP应用。所以公司的应用如果想全网推广,占用最多的流量入口的话,使用Taro就完全没有问题。
有熟悉uni的同学会讲uni也有这样类似的功能,生成多端应用的功能,而且还有专属的编辑器,调试很方便,下边就放一个taro与uni-app以及其他例如mpvue等的对比图
由此可见,Taro 的强大之处,以及Taro框架在前端的技术的占比会越来越高。而且用统一的框架、统一的API、统一的代码规范以及统一的代码结构,是多么棒的开发体验。
一次开发就可以完成所有主流平台的布局,人力和时间成本压缩到最低,感觉节省了一个亿哦。
下边我们就一起来揭秘Taro这神奇的面纱把
Taro的环境搭建和Hello World
前置知识
学习这个前端框架,你需要一些前置知识:
- HTML、CSS,JavaScript这三个是基础知识,最起码要了解能作出简单的静态页面
- 理解MVVM框架,如果会React框架是最好的
- 了解ES6相关语法,作为一个当下流行的框架以及2020年的前端开发用ES6让代码规范起来,对项目开发和管理更加的方便
Taro编译工具的介绍
Taro是一套遵循React语法规范的多端开发解决方案,使用Taro,只书写一套代码,再通过Taro的编译工具,讲源代码分别编译出可以再不同端(微信小程序,H5,RN等)运行代码。
所以说这里的Taro编译工具是非常重要的,这里附带一张图。
Taro开发环境的安装
1.第一步是安装@tarojs/cli(脚手架工具),也有教开发工具的。
这个你可以使用npm或者yarn进行全局安装,命令如下:
npm的安装方式
npm install -g @tarojs/cli
yarn的安装方式
yarn global add @tarojs/cli
打开命令行后,输入上边的命令。
2.安装完成后,就可以用脚手架创建项目,命令如下:
taro init taro-dome
这里有个小坑就是如果你使用npm来安装脚手架的时候,有很大机率会失败,这些失败多是因为国内网络环境限制的。有两种解决方案,第一是"fangqiang"来进行安装,第二种是使用yarn来进行暗转,我这里就使用了yarn。
Hello World程序
通过上边的创建项目,我们的项目已经建立好了,然后就是运行项目,命令如下:
cd taro-dome
npm run dev:h5
在这里运行的是h5模式的,如果要运行小程序的根据package.json中的script设置可知相应的运行方式。
运行后页面会在浏览器显示Hello World,默认的端口为10086,如图:
Taro生成小程序代码并预览
Taro可以生成多端代码,在上一节只生成了h5的显示,这次我们就先来进行生成小程序代码,并进行预览。
生成微信小程序的代码
npm run dev:weapp
输入完命令后,taro编译器自动为我们生成小程序代码到dist目录中。
这里边的app.js、app.json以及app.wxss 这都是微信小程序所对应的文件,有过微信小程序开发的肯定觉得很熟悉,这就是Taro的强大之处,也是Taro框架的开发者肯定是个webpack开发的大牛,编译生成对应的终端的代码,而不是一个壳子嵌套。
在微信开发者工具中预览项目
开发小程序的肯定知道微信开发者工具,如果你是初学的这里给你一个下载的链接,方便下载学习:
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
下载后安装步骤很简单,跟安装QQ几乎一样。
安装完成后,你需要注册一个账号,这个自己按照提示注册就可以了。
注册后导入一个小程序项目
需要注意的是这不是新建,而是导入一个项目。目录选择的是你的taro项目刚才编译后生成的dist目录
AppId如果有在公众平台注册可以填,没有默认是一个测试号直接导入即可。
导入后你就可以看到在微信开发者工具中显示Hello World!了。
注意坑点
千万不要在微信开发者工具中修改dist目录,因为这个文件是由taro编译而来的;
如果要修改在taro的原项目修改,然后通过编译将修改的内容编译到dist文件中
Taro的目录介绍
在目录介绍前肯定会有疑惑,Taro是多端统一框架,前边我们利用编译工具生成了h5和微信小程序的代码,那么其他的支付宝小程序、百度小程序等又是如何生成?
这些的答案都在项目的package.json文件中的scripts部分当中:
"scripts": {
"build:weapp": "taro build --type weapp",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt",
"build:h5": "taro build --type h5",
"build:rn": "taro build --type rn",
"build:qq": "taro build --type qq",
"build:quickapp": "taro build --type quickapp",
"dev:weapp": "npm run build:weapp -- --watch",
"dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch",
"dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch"
},
我们就以dev为例解释下dev: 后边的都是哪一个平台的
- weapp 微信小程序
- h5 手机web用于公众号和浏览器等
- swan 百度小程序
- alipay 支付宝小程序
- tt 字节跳动小程序
- qq QQ小程序
- jd 京东小程序
- quickapp 快应用
- rn React Native
这些类型执行都和微信小程序的一样,都是将: 后的改成相对应的模式即可
npm run dev:weapp
或
yarn dev:weapp
下边就介绍下Taro的项目目录结构
dist目录
这个目录在上边生成微信小程序代码时已经见到了,是我们在预览时自动生成的,每次进行预览都会根据我们预览的终端不同,编译成不同代码。
每次编译时都会删除以前的代码,这个小伙伴么要注意一下。
config目录
这个就是项目的一些配置,这些配置以后会不断深入学习,但是现在还不了解,可以先不进行配置。否则会影响项目的运行。
node_modules
项目所需的依赖包,就是使用npm install进行安装的包,一般不需要修改。
src目录
这个是最重要的,这个是我们的源码目录,开发的所有代码都在这个里边。
下边给一个官方的目录结构说明
├── dist 编译结果目录
├── config 配置目录
| ├── dev.js 开发时配置
| ├── index.js 默认配置
| └── prod.js 打包时配置
├── src 源码目录
| ├── pages 页面文件目录
| | ├── index index 页面目录
| | | ├── index.js index 页面逻辑
| | | └── index.css index 页面样式
| ├── app.css 项目总通用样式
| └── app.js 项目入口文件
└── package.json
Taro使用Hooks的新特性
React Hooks的优缺点
既然我们要用Hooks来写,我们就要了解React Hooks的优缺点,为什么要用Hooks,那么我们就来看下Hooks的优缺点吧!
这个优缺点是通过和传统的React.Component进行对比得出的。
React Hooks的优点
- 更容易复用代码
- 清爽的代码风格
- 代码量更少
- 更容易发现无用的状态和函数
- 更容易拆分组件
React Hooks的缺点
- 状态不同步
- 副作用代码从主动式变成响应式
如何避免React Hooks的常见问题
- 不要在useEffect里面写太多的依赖项,划分这些依赖项成多个useEffect,这样更好维护
- 如果你碰到状态不同步的问题,可以考虑下手动传递参数到函数。如:
// showCount的count来自父级作用域
const [count,setCount] = useState(xxx);
function showCount(){ console.log(count) }
// showCount的count来自参数
const [count,setCount] = useState(xxx);
function showCount(c){ console.log(c) }
- 一定要加入eslint-plugin-react-hooks这个插件,并且重视它的警告
- 使用useRef来保存你的引用并在re-render的时候主动更新ref的对应属性,这样可以避免“引用是旧”的这个烦人的问题,但这种方式hack味道浓郁。
使用Hooks来改写Index组件
在src/pages/index/index.jsx文件:
原文件:
import Taro, { Component } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import './index.less'
export default class Index extends Component {
componentWillMount () { }
componentDidMount () { }
componentWillUnmount () { }
componentDidShow () { }
componentDidHide () { }
config = {
navigationBarTitleText: '首页'
}
render () {
return (
<View className='index'>
<Text>Hello world!</Text>
</View>
)
}
}
修改成hooks方式:
import Taro, { useState } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import './index.less'
function Index(){
const [userName] = useState('Hello Taro!')
return (
<View>
<Text>{userName}</Text>
</View>
)
}
export default Index
如果你对React Hooks不熟悉的话,这里有一套免费的Hooks学习视频教程:https://www.jspang.com/detailed?id=59
如果您对React也不太熟悉的话,没关系这边有一整套的React学习视频,学习完后上手项目没有问题的:https://jspang.com/detailed?id=56
Taro中组件传值
使用Taro 的一个好处就是要可以用组件化的方式进行编程,所以编写组件在Taro中是每天都需要作的工作。
下边我们先来创建一个自组件,然后进行组件的传值,Taro的组件传值跟React的一样利用props,因此如果你对React的组件传值比较熟悉的化,这里很容易理解。
在Taro项目中的src/pages/index文件夹下面建立一个Child组件
child.jsx组件
import { View, Text } from '@tarojs/components'
function Child(){
return (
<View><Text>我是子组件</Text></View>
)
}
然后在Index组件中引入,这里给出全部代码方便学习
import Taro, { useState } from '@tarojs/taro' import { View, Text } from '@tarojs/components' import './index.less' import Child from "./child" function Index(){ const [userName] = useState('Hello Taro!') return ( <View> <Text>{userName}</Text> <Child></Child> </View> ) } export default Index
父组件向子组件传值
在上边说过,Taro的传值跟React的一样,父组件向子组件传值是通过props进行;
在Taro中也是可以这样传值的,现在修改index.jsx代码,把userName传递给子组件。
import Taro, { useState } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import './index.less'
import Child from "./child"
function Index(){
const [userName] = useState('Hello Taro!')
return (
<View>
<Text>{userName}</Text>
<Child userInfo={userName} ></Child>
</View>
)
}
export default Index
传递后,子组件要增加props参数,然后才能用props进行接收。
import { View, Text } from '@tarojs/components'
function Child(props){
return (
<View>
<Text>我是子组件</Text>
<View><Text>接收来自父组件的值:{props.userInfo}</Text></View>
</View>
)
}
export default Child
这个组件间的传值非常的简单,当我们会用组件的形式编写页面和组件时,你就可以作一些小东西了。
但现在你可以看到,我们把页面和组件放到了一个文件夹下,并且都使用了jsx扩展名。
那Taro时如何区分那些是组件,那些是页面的?
其实它是通过自身的路由来区分的,只要配置路由的,就是页面,没配置的就默认是组件。
下边我们来看下Taro中的路由吧!
Taro 路由配置和介绍
Taro中的路由和React 的路由不同,它是通过app.jsx中的pages来配置的,并且谁配置在第一个数组位置,谁就是默认打开的首页。
首先配置路由
新建一个页面
在/src/pages/文件夹下,建立一个/blog文件夹,在文件夹下面建立一个blog.jsx文件,写入下面的代码:
import {View , Text} from '@tarojs/components'
function Blog(){
return (
<View>
<Text>Blog Page</Text>
</View>
)
}
export default Blog
路由配置
有了页面之后就可以到/src/app.jsx下,然后在pages的数组里面加入代码。
pages: [
'pages/blog/blog',
'pages/index/index'
],
这里需要注意一点,就是你不需要用import引入Blog页面,这个Taro为我们自动做好了。修改完成后,可以到浏览器中看一下,可以看到默认页面已经变成了Blog页面了。
页面间的跳转
页面跳转的方法
Taro提供了6个相关的导航API,我们可以使用这些API进行跳转,需要注意的是这些有些是小程序专用的。
- navigateTo: 最基本的跳转方式,可以返回上级页面。三端都支持的,小程序、H5、React Native。
- redirectTo:不记录上集页面,直接跳转。三端都支持的,小程序、H5、* React Native。
- switchTab: Tab之间进行切换,这个要配合Taro的导航栏一起使用,三端都支持的,小程序、H5、React Native。
- navigateBack: 返回上一级页面,这个在小程序中常使用,三端都支持的,小程序、H5、React Native。
- relaunch:关闭所有额面,打开到应用内某个页面。三端都支持的,小程序、H5、React Native。
- getCurrentPages: 获取当前页面信息所用,这个H5是不支持的。(注意)
页面跳转Demo
做个Demo,我们从Blog页面,跳转到Index页面,我们的程序如何来编写。
为了方便学习这里给出blog.jsx的全部代码:
import Taro from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Blog(){
const gotoIndex=()=>{
Taro.navigateTo({url:'/pages/index/index'})
}
return (
<View>
<Text>Blog Page</Text>
<Button onClick={gotoIndex}>我要去Index页面</Button>
</View>
)
}
export default Blog
这样我们就实现了Taro中路由的跳转。
Taro路由传参
Taro的路由传参利用查询字符串的形式
Taro中进行传参,一般会使用查询字符串的形式,也就是在跳转的url上,加一个?问号的形式,然后后边跟上参数。
现在我们就在Blog.jsx页面用,useState的形式声明一个变量,再通过跳转把值带到Index.jsx页面。
import Taro ,{useState}from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Blog(){
const [blogTitle,setBlogTitle]=useState('JSPang Blog')
const gotoIndex=()=>{
Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle})
}
return (
<View>
<Text>Blog Page</Text>
<Button onClick={gotoIndex}>我要去Index页面</Button>
</View>
)
}
export default Blog
接收传递参数并显示在页面上
在参数已经可以传递了,那如何在Index.jsx进行接收那,其实也非常简单。只要使用this.$router.params就可以进行接收。
当然我们要接收参数,可以在useEffect()中进行(useEffect是React Hooks的方法,不了解的同学请去了解下),
useEffect(()=>{
setBlogTitle(this.$router.params.blogTitle)
},[])
为了更好的学习,这给出接收的全部代码,
index.jsx的代码:
import Taro, { useState ,useEffect} from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import Child from './child.jsx'
import './index.less'
function Index(props){
const [userName ,setUserName] = useState('Hello World!!!!')
const [blogTitle,setBlogTitle] = useState('')
useEffect(()=>{
setBlogTitle(this.$router.params.blogTitle)
},[])
return (
<View>
<Text>{userName}</Text>
<Child userName={userName}></Child>
<View>{blogTitle}</View>
</View>
)
}
export default Index
多参数的传递和接收
多个参数和多个参数的接收,传递的时候只要用&进行链接就可以了,比如下面这样。(有前端开发经验的同学,对这个肯定不会陌生)
Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})
为了学习方便,这里给出blog,jsx的全部代码:
import Taro ,{useState}from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Blog(){
introduce
const [blogTitle,setBlogTitle]=useState('JSPangBlog')
const [introduce,setIntroduce]=useState('111111')
const gotoIndex=()=>{
Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})
}
return (
<View>
<Text>Blog Page</Text>
<Button onClick={gotoIndex}>我要去Index页面</Button>
</View>
)
}
export default Blog
接收参数跟单参数接收方法一样,不作过多介绍,直接给出代码,
index.jsx代码:
import Taro, { useState ,useEffect} from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import Child from './child.jsx'
import './index.less'
function Index(props){
const [userName ,setUserName] = useState('Hello World!!!!')
const [blogTitle,setBlogTitle] = useState('')
const [introduce,setIntroduce]=useState('')
useEffect(()=>{
setBlogTitle(this.$router.params.blogTitle)
setIntroduce(this.$router.params.introduce)
},[])
return (
<View>
<Text>{userName}</Text>
<Child userName={userName}></Child>
<View>{blogTitle}</View>
<View>{introduce}</View>
</View>
)
}
export default Index
JavaScript资源引入的方法
JavaScript的引入和React的引入方式差不多,比如现在我们定义了一个方法叫做XieDaJiao(谢大脚),然后再定义一个方法叫liuying(刘英)。
在/src目录下,新建一个/tools文件夹,然后在文件夹下边建立一个index.js文件,输入下面的代码。
export function xiedajiao(){
console.log('我是谢大脚')
}
export function liuying(){
console.log('我是刘英')
}
建立完成后,我们在blog.jsx文件中引入这个,需要用ES的解构的方式引入:
import {xiedajiao,liuying} from '../../tools'
然后使用的方法,也是利用在useEffect中运行,如下:
useEffect(()=>{
xiedajiao()
liuying()
},[])
引入图片的方式
Taro引入图片的方式有两种: import xxx from ‘…’ 然后用将xxx放到相应的src的方式和直接在src中用require方式
下方是blog.jsx的代码,是用import的方式:
import Taro ,{useState ,useEffect}from '@tarojs/taro'
import {View , Text ,Button,Image} from '@tarojs/components'
import {xiedajiao,liuying} from '../../tools'
import newbbd from '../../static/newbbd0001.jpg'
function Blog(){
useEffect(()=>{
xiedajiao()
liuying()
},[])
const [blogTitle,setBlogTitle]=useState('JSPangBlog')
const [introduce,setIntroduce]=useState('111111')
const gotoIndex=()=>{
Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})
}
return (
<View>
<Text>Blog Page111</Text>
<Button onClick={gotoIndex}>我要去Index页面</Button>
<View>
<Image src={newbbd} width="100px" height="100px" />
</View>
</View>
)
}
如果想用require的方式,将Image组件的src属性改为:
<Image src={require('../../static/newbbd0001.jpg')} width="100px" height="100px" />
更多资源的引入方式,可以来看下Taro资源引入的文档:http://taro-docs.jd.com/taro/docs/static-reference.html
JSX的列表渲染
在开始介绍远程数据请求前,先对JSX的列表渲染做下介绍,给JSX不熟悉的朋友提供便利。
构建数组对象
先使用JS的基本语法,打开blog.jsx文件然后再blog方法里编写代码:
const girls = [
{id:1,name:'胡一菲'},
{id:2,name:'陈美嘉'},
{id:3,name:'诸葛大力'},
{id:4,name:'咖喱酱'}
]
在JSX代码中渲染列表
blog.jsx的全部代码
import Taro ,{useState ,useEffect}from '@tarojs/taro'
import {View , Text ,Button,Image} from '@tarojs/components'
import {xiedajiao,liuying} from '../../tools'
function Blog(){
useEffect(()=>{
xiedajiao()
liuying()
},[])
·
const girls = [
{id:1,name:'胡一菲'},
{id:2,name:'陈美嘉'},
{id:3,name:'诸葛大力'},
{id:4,name:'咖喱酱'}
]
const [blogTitle,setBlogTitle]=useState('JSPangBlog')
const [introduce,setIntroduce]=useState('111111')
const gotoIndex=()=>{
Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})
}
return (
<View>
<Text>Blog Page111</Text>
<Button onClick={gotoIndex}>我要去Index页面</Button>
<View>
{ girls.map((item,index)=>{
return (
<View>{item.name}</View>
)
}) }
</View>
</View>
)
}
在JSX中使用逻辑判断
在JSX中使用逻辑判断,不能像下边这样用判断:
<view>
{
if(zhujueNum===1){
return ('张伟')
}else{
return('吕子乔')
}
}
</view>
需要使用判断要用三目运算符:
<view>
男主角是:{zhujueNum==1?'张伟':'吕子乔'}
</view>
或者也可以使用,短路运算符:
<view>
男主角是:{zhujueNum==1 && '张伟' || '吕子乔'}
</view>
请求远程数据
Taro的远程数据请求,利用Taro的request的方式,这里给出request的参数文档:
```javascript
https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html
```
下边我们在blog.jsx文件中,编写一个testHandler方法,方法中使用Taro.request后去远端数据,这里数据请求的路径url,你可以去mockJs网站,也可以自己用node等方式创建一个数据请求路径,或者你项目开发时候的路径
const getData= ()=>{
Taro.request({
url:'...'
}).then(res=>{
console.log(res.data)
})
}
然后在JSX中编写一个按钮,加上onClick事件,代码如下:
<Button onClick={getData}>获取数据</Button>
遍历渲染获取到的数据
先用useState声明一个articleList,代码如下:
const [articleList,setArticleList] = useState([])
然后在return中使用map进行遍历,如下:
{
articleList.map((item,index)=>{
return (<View key={index}>- {item.title} </View>)
})
}
blog.jsx完整的代码:
import Taro, { useState } from '@tarojs/taro'
import { View, Text, Button } from '@tarojs/components'
function Blog2(){
const [dataList, setDataList] = useState([])
const getData = () => {
Taro.request({
url: 'https://apiblog.jspang.com/default/getArticleList'
})
.then((res)=>{
console.log(res.data)
setDataList(res.data.list)
})
}
return (
<View>
<View><Text>数据请求</Text></View>
<Button onClick={getData} >获取数据</Button>
<View>
{
dataList.map((item, index)=>{
return (
<View key={index} >{item.title}</View>
)
})
}
</View>
</View>
)
}
export default Blog2