第一次使用Taro,把遇到的坑罗列一遍,给后继踩坑者做参考吧。
开发环境
- taro版本:v1.3.0-beta.5
- nodejs版本:v8.11.4
使用铁律
- 静态资源404,
检查静态资源引用是否使用ES6的import引入
检查访问文件有没有使用下划线连接多个单词 - 路径不对,找不到Js文件,
删除dist文件夹,重新编译
踩过的坑
- 1. 实现小程序的slot的功能,开发工具翻译的wxml结果是slot内容和组件是同级,而非嵌套关系。
- 2. 使用externalClasses,为组件定义外部样式失效。
- 3. 在component文件内使用“函数式组件”出错了
- 4. 编译后,静态资源图片总是404, 没有被复制到dist目录
- 5. ‘生成类函数式组件的函数’内部再次调用‘生成类函数式组件的函数’出错了
- 6. 父组件通过props传递函数给子组件,子组件触发函数后,this指向了子组件的props
1. 实现小程序的slot的功能,开发工具翻译的wxml结果是slot内容和组件是同级,而非嵌套关系。《Children 与组合》Taro官方文档
这是小程序开发工具的bug, 最后视图窗口显示是正确的,实际是正确的,github.com/NervJS/taro…
编译前组件代码
// component.js
<View className={'must-login-btn ' + className} hoverClass='btn-hover' onClick={this.onClick}>
{
!userToken
? <Button className='user-info-btn' openType='getUserInfo' onGetuserinfo={handleGetUserInfo} />
: ''
}
{ this.props.children }
</View>
// page.js
<MustLoginBtn className='scan-btn' onClick={this.doScan}>
<View className='scan-btn-inner'>
<View className='scan-icon' />
<Text className='btn-text'>扫小程序码</Text>
</View>
</MustLoginBtn>
开发工具中看到的wxml如下:
2. 使用externalClasses,为组件定义外部样式失效。《组件模板和样式》小程序官方文档,《组件的外部样式和全局样式》Taro官方文档
使用全局样式类,放弃使用externalClasses。
在component文件内设置addGlobalClass: true
, 同时使用props获取外部定义的className
在page.js文件内使用自定义组件式时,设置className
属性
在page.scss样式文件设置外部样式 在组件内调用组件的情况,外部样式也需要写在page的样式文件才有效(想哭)
/* CustomComp.js */
export default class CustomComp extends Component {
// 设置全局样式
static options = {
addGlobalClass: true
}
// 使用prop设置自定义className
static defaultProps = {
className: ''
}
render () {
return <View className={this.props.className}>这段文本的颜色不会由组件外的 class 决定</View>
}
}
/* MyPage.js */
import './MyPage.scss';
export default class MyPage extends Component {
render () {
return <CustomComp className="red-text" />
}
}
/* MyPage.scss */
.red-text {
color: red;
}
3. 在component文件内使用“函数式组件”出错了
函数的命名必须以 render 开头,render 后的第一个字母需要大写。《类函数组件》Taro官方文档
- 错误表现:
这个不应该算是坑,是阅读文档不够深刻。
4. 编译后,静态资源图片总是404, 没有被复制到dist目录
taro中静态资源引入需要直接通过ES6的import语法引入《静态资源引用》Taro官方文档
以下引入方式被直接忽略资源引入:
<Image className='comp-checkbox__icon-inner' src='./assets/checked_icon.png' />
5.‘生成类函数式组件的函数’内部再次调用‘生成类函数式组件的函数’出错了
官方给出的限制:
函数的命名必须以 render 开头,render 后的第一个字母需要大写
函数的参数不得传入 JSX 元素或 JSX 元素引用
函数不能递归地调用自身
虽然我没有哦调用自身,但是显然也是不能调用其他的‘生成类函数式组件的函数’
解决办法:
方法1:新建独立的组件文件ComponentA 和 ComponentB,然后在ComponentA中引入ComponentB,并render函数中使用
方法2:把jsx尽量写在一个类函数式组件内
错误的写法
class MainPage extends Component {
renderB () {
return <View>B</View>
}
renderA () {
return (
<View>
{this.renderB()}
</View>
)
}
render () {
...
return (
...
{this.renderA()}
...
)
}
}
TypeError: Property right of Ass ignnent Expression expected node to be of a type[ "Expression"] but instead got null
正确写法
class MainPage extends Component {
renderA () {
return (
<View>
{/* renderB 内容 start */}
<View>B</View>
{/* renderB 内容 end */}
</View>
)
}
render () {
...
return (
...
{this.renderA()}
...
)
}
}
6. 父组件通过props传递函数给子组件,子组件触发函数后,this指向了子组件的props
被传递的函数,在jsx代码中做绑定
出现错误的代码:
// Parent
class Parent extends Component {
constructor (props) {
super(props)
this.onTabClick.bind(this); // 绑定this
}
onTabClick () {
console.log(this) // this指向child.props,而不是指向Parent的实例
}
render () {
return <Child onClick={this.onTabClick}/>
}
}
// Child
class Child extends Component {
constructor (props) {
super(props)
this.handleClick.bind(this); // 绑定this指向
}
handleClick () {
...
this.props.onClick();
}
render () {
return (
...
<View onClick={this.handleClick}></View>
...
)
}
}
this指向正确的代码:
// 仅仅修改的父组件onTabClick.bind(this)的位置
// Parent
class Parent extends Component {
constructor (props) {
super(props)
/*修改 start*/
// this.onTabClick.bind(this); // 绑定this
/*修改 end*/
}
onTabClick () {
console.log(this) // this指向Parent的实例
}
render () {
/*修改 start*/
return <Child onClick={this.onTabClick.bind(this)}/>
/*修改 end*/
}
}
原因:还没有找出来,正在学习中,请指教