Vue/React 坑收藏

2020-09-27  本文已影响0人  G_console

Vue BUG记录

1、自定义组件的slot绑定点击方法,触发事件混乱

//自定义弹窗子组件
<template>
  <div v-if="show" class="alertBox">
    <div class="overlay"></div>
    <div class="alert">
      <div class="title" v-if="title">{{title}}</div>
      <slot></slot>
      <div class="btns" v-if="!hideCancel || !hideConfirm">
        <div class="btn" 
          v-if="!hideCancel"
          @tap="handleCancel()"
        >{{cancelText || '取消'}}</div>
        <div class="btn btn1" 
          v-if="!hideConfirm"
          @tap="handleConfirm($event)"
        >{{confirmText || '确定'}}</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "modal-box",
  props: {
    show: Boolean,
    title: String,
    hideCancel: Boolean,
    hideConfirm: Boolean,
    cancelText: String,
    confirmText: String,
    onCancel: {
      type: Function
    },
    onOk: {
      type: Function
    }
  },
  data () {
    return {
      
    }
  },
  computed:{},
  methods: {
    handleCancel() {
      if(this.onCancel){
        this.onCancel()
      }
    },
    handleConfirm(e) {
      console.log('确认', e, e.target)
      if(this.onOk){
        this.onOk()
      }
    },
    test(){
      console.log('子组件test')
    }
  },
  onLoad(option){
    console.log('slotttt', this.$slots)
  }
}
</script>
//父级引用
<template>
  <modal-box
    :show="showBox"
    title="苹果手机用户购买置顶"
    confirmText="点此发送短信"
    :onCancel="handleCancel"
    :onOk="handleConfirm"
  >
    
      <div class="sendMsg" >
          <div @click="ddd()">测试</div>
          <div @click="ddd()">测试1</div>
          <div @click="ddd()">测试2</div>
      </div>
    
  </modal-box>
</template>

<script>
import ModalBox from "c/Modal/index.vue";
export default {
  components: {
    ModalBox
  },
  data () {
    return {
        showBox: true,
    }
  },
  computed:{
  },
  methods: {
    showModal(){
      this.showBox= true
    },
    handleCancel(){
      console.log('取消')
      // this.showBox= false
    },
    handleConfirm(){
      console.log('确定')
    },
    ddd(){
      console.log('clearddd')
    }
  },
  onLoad(option){
    
  },
  onShow () {
   
  },
  onHide(){
  }
}
</script>

期望点击“测试”按钮,只执行ddd()方法,但是奇葩表现是:点“测试”不仅执行了ddd() 还触发了onCancel;点“测试1”不仅执行了ddd() 还触发了onOk;点“测试2”只执行了ddd() ;
为什么父级slot绑定的方法会触发到自定义组件中的其他方法···
然后我用mpvue2.0版本测试,也是同样的问题
但是我用vue测试,没问题···
mpvue坑还是很多的 导致官方都更不下去了 233333

解决方法: 子组件两个@tap改成@touchstart,也可以用@ touchend,这只能暂时解决绑定事件的问题,组件再复杂点就不行了。

其实这里面还有一个问题 slot内容中如果绑定了父组件的状态,状态改变时,slot是不会跟着渲染的··· 这个问题的处理方法点这里。但是!渲染可以了,动态改变还是不行

参考:slot中组件数据无法渲染 #409组件嵌套slot问题 #427

最后,我决定不用slot了 辣子鸡里面全是辣鸡

2、mpvue的computed不能正常渲染

正常vue可以通过computed传参的方式 渲染不同内容 如:

<div 
  class="item" 
  :class="'item'+index"
  v-for="(item, index) in list"
>
  {{getTheData(item.val)}}
</div>

computed: {
  getTheData() {
    return function(name){
        console.log(name, this[`${name}`])
        return this[`${name}`];    
    }           
  } 
}

但是在mpvue中执行以上代码,console正常,但是页面渲染没有内容!什么👻!
所以只能迂回了 真滴是操碎了心

<div 
  class="item" 
  :class="'item'+index"
  v-for="(item, index) in list"
>
  {{getTheData[index].name}}
</div>

computed: {
  getTheData() {
    let _this = this
    let result = [];
    _this.list.map(res => {
      result.push(_this[`${res.val}`])
    })
    return result;
  }
}

辣子鸡里面全是辣鸡

3、封装input用了v-model就不能用动态type

<input :type="type || 'text'" v-model="value" />

上面这样写报错:v-model does not support dynamic input types. Use v-if branches instead.
意思就是用了v-model就不能用动态的type,只能用v-if代替

<input type="number" v-if="type == 'number'" v-model="value" />
<input type="text" v-else v-model="value" />

4、mpvue同一组件再一个页面被多次调用,slot渲染出错

<template>
  <modal-box>
    <div>111</div>
  </modal-box>
  <modal-box>
    <div>222</div>
  </modal-box>
</template>

<script>
import ModalBox from "c/Modal/index.vue";
export default {
  components: {
    ModalBox,
  },
  //...
}
</script>

像上面这样同一组件被调用多次,slot内容就不对了,用具名slot分发也不行,只调用1个是正常的。奇葩的是,我重新编译一下显示就没问题了。。。。。。 但是!如果要在slot内容中绑定data,还是不行!也就是只能显示<div>111</div>这种,不能显示<div>{{val}}</div>这种。 反正老项目,也不想浪费时间纠结了,第二个就不用组件了。 哎~ react真香!

Taro 问题记录

1、自定义组件createSelectorQuery获取不到元素

const query = this.interface.createSelectorQuery()
query.select('#dom-id').boundingClientRect((res) => {
  console.log('info', res)   //res为null
}).exec()
const query = this.interface.createSelectorQuery().in(this)
query.select('#dom-id').boundingClientRect((res) => {
  console.log('info', res)
}).exec()
/**
没有console,系统报警告:
An SelectorQuery call is ignored because no proper page or component is found. Please considering using `SelectorQuery.in` to specify a proper one.
意思是因为找不到页面或组件,所以请求被忽略了
**/

正确写法:

const query = this.interface.createSelectorQuery().in(this.$scope)
query.select('#dom-id').boundingClientRect((res) => {
  console.log('info', res)
}).exec()

React 问题记录

1、reverse后遍历,总会出错

//根据给定的数字判断属于哪个区间
let arr = [
    { name: '学徒', value: 0 },
    { name: '1-3年', value: 1 },
    { name: '3-5年', value: 3 },
    { name: '5-10年', value: 5 },
    { name: '10-15年', value: 10 },
    { name: '15年以上', value: 15 }
]
private findName = e =>{
    let result = arr.reverse().find(res => res.value <= e)
    return result? result.name : ''
}

2、微信小程序 支付完成后,从系统支付成功页返回,显示feedback组件失效

    const res = await this.interface.requestPayment(response.body);

    if (res.errMsg !== 'requestPayment:ok') {
      return;
    }

    let that= this
    setTimeout(() => {
      //安卓,支付页面返回后,第一时间显示会无效。。。。。加个延时就好了。。。。
      //可能是需要dom渲染的原因?
      that.feedback.showFeedback('giftAlert')
    },500)
    
    this.feedback.showToast('充值成功');  //这个是可以正常触发的

3、A页面执行setTimeout,中途切页面后,setTimeout会继续执行,但是里面的this方法无效

  private handleShowPullDownNoticebar = () => {
      this.setState({
        showPulldownNoticebar: true
      })
  }

  private hidePullDownNoticebar = () => {
    this.setState({
      showPulldownNoticebar: false
    })
    
    setTimeout(() => {
      console.log("timeout")  //可以正常console;
      this.handleShowPullDownNoticebar()  //跳页后不执行
      //feedbackObservable.trigger('showIndexPulldownNotice', 1)  //迂回
    }, 8000)
  }

因为切换页面后,A页面组件已经被销毁,定时器虽然会正常执行,但其中的方法执行的时候已经是不存在了。
解决方法:可以迂回一下,使用发布订阅trigger一下

4、使用antDesign Pro时,自定义了一个组件,使用Link报错

报错:Uncaught Error: Invariant failed: You should not use <Link> outside a <Router>
Link外面要有BrowserRouter包裹

import Link from 'umi/link';
import { BrowserRouter, Route } from 'react-router-dom';

<BrowserRouter>
  <Link to={'/index/main'}>跳转</Link>
</BrowserRouter>

5、使用input上传文件时,onChange拿不到内容

<input type="file" onChange={this.handleFileChange}/>

private handleFileChange = e => {
  console.log(e)  //直接这样写,拿到的e没有target等内容
}

private handleFileChange = e => {
  e.persist()    //要加这个东西
  console.log(e)  //正常
}

6、react-app iphone打开H5页面空白

问题描述:一个react开发的H5页面,页面加了一些正则匹配,打包后安卓、PC打开都正常。但是iphone上不论微信端还是浏览器,页面打开都是空白,title内容都没有。而且这种情况根本不能用vconsole调试。所以只能用safari内置开发功能连接mac调试,调试发现控制台报错SyntaxError: Invalid regular expression: invalid group specifier name
百度查到:如果正则表达式中包含零宽断言的话 , 在安卓手机上正常 , 但是在ios上会报以下错误;常用零宽断言:?<=、?<!、?!、?=;
我代码中使用了rep = rep.replace(/(?<!(\.|\w))p ?{/g, '.p {'); 这样的写法;NO!!!
要改成rep = rep.replace(new RegExp("(?<!(\.|\w))p ?{","g"), '.p {'); 这样才OK!!

7、多维数组循环渲染,onClick拿到的数据错乱

{(parsedData && parsedData.length > 0) && parsedData.map(item => (
  <View className={styles.sec} key={item.date}>
    <View>{item.date}</View>
    <View className={styles.lists}>
      {item.list && item.list.map(res => (
        <View className={styles.albumItem} key={res.id} onClick={() => {
          console.log('???', res.id)
          this.navigator.push('albumDetail', {id: res.id})
        }}>
          {res.id}
        </View>
      ))}
    </View>  
  </View>
))}

//{res.id}渲染显示是正确的,但是onClick中的res.id是错误的!!!

上面这个二位数组渲染,页面打印没问题,但是onClick拿的数据不对。
像是第一层循环,每次都会覆盖之前的onClick绑定。所以改成用bind写法

//改成: 
onClick={this.handleItemClick.bind(this, res)}

private handleItemClick = (res) => {
    console.log('e', res)   //console正确
    this.navigator.push('albumDetail', {id: res.id})
}
//这样就可以了
还有一种情况:二维数组循环渲染自定义组件,组件的props值也会被覆盖,例:
{(parsedData && parsedData.length > 0) && parsedData.map(item => (
  <View className={styles.sec} key={item.date}>
    <View>{item.date}</View>
    <View className={styles.lists}>
      {item.list && item.list.map(res => (
        <JobItem 
          key={res.id}
          data={res} 
        />
      ))}
    </View>  
  </View>
))}

//自定义组件JobItem所渲染的数据都是重复的!!!
//改成这样:JobItem渲染拎出来就行了。。。
{(parsedData && parsedData.length > 0) && parsedData.map(item => (
  <View className={styles.sec} key={item.date}>
    <View>{item.date}</View>
    <View className={styles.lists}>
      {item.list && item.list.map(res => 
        <View>{this.renderJobItem(res)}</View>
      )}
    </View>  
  </View>
))}

/** -------  **/
private renderJobItem = (res) => {
  return <JobItem 
    key={res.id}
    data={res} 
  />
}

8、externalClasses里只有'css-class'有效

子组件里的externalClasses别的名字都无效,例如InputTextareaFormTextarea里的第二个'css-placeholder-class'就不起作用:

interface Props extends Omit<TextareaProps, 'className' | 'placeholderClass'> {
  cssClass?: string;
  cssPlaceholderClass?: string;
}
export default class FormTextarea extends Taro.Component<Props> {
  externalClasses = ['css-class', 'css-placeholder-class'];
  /** 省略 **/
  className={cx(styles.input, 'css-class')}   //有效
  className={cx(styles.textarea, 'css-placeholder-class')}   //无效
  /** 省略 **/
}

原因是/config/index.js里面有一个配置jsxAttributeNameReplace

jsxAttributeNameReplace: {
      cssClass: 'css-class',
      cssPlaceholderClass: 'css-placeholder-class',  //这里加上就行

      //额外加的externalClasses 都要在这里先配置,PS:新版本的Taro已移除这个配置。
}

9、无状态函数组件中直接调用get函数无效

private get isVip() {
    const { userinfo } = this.state
    return !!(userinfo && userinfo.is_vip)
}

private renderFooter = () => {
    return (
      <View className={styles.btns}>
        {this.isVip? (
          <View>1</View>
        ): (
          <View>2</View>
        )}
      </View>
    )
}  //这样写无效,下面这样写才有效
private renderFooter = () => {
    const isvip = this.isVip;
    return (
      <View className={styles.btns}>
        {isvip? (
          <View>1</View>
        ): (
          <View>2</View>
        )}
      </View>
    )
}

10、打包报错

TypeError: ctx.modifyWebpackChain is not a function
检查发现是@tarojs/plugin-stylus跟当前taro/cli版本不一致,安装对应版本就行了

别的坑记录

1、配置目录别名正确,但编辑器报错

配置目录别名时,tsconfig.json里正确配置了path,但编辑器还是显示引用错误。
重启编辑器就好··· PS:我用的VS Code

2、decodeURI无效,但复制测试没问题

从接口获取了一个unicode,需要转换成中文。但是接口获取的unicode字符串代入下面方法后,并不能转换成中文。
这是接口返回数据:{name: "\u4e2d\u56fd", price: 1000, status: 1},取其中的name直接代入decodeURI转换失败!
但是通过复制接口返回的unicode字符串,然后进行测试,是可以正常转换的。。。目测应该是有转义问题,可这种问题肉眼实在是看不出来啊

private getDecodeUri = (str) => {
    console.log('decodeURI:', str, decodeURI(str))   //如果str是接口获取的,控制台打印无效;
    console.log('test: ', '\u4e2d\u56fd', decodeURI('\u4e2d\u56fd'))  //控制台打印有效
    return decodeURI(str) 
}

然后网上找到一个偏方,下面这样就可以了!!!???

private getDecodeUri = (str) => {
    let test = JSON.stringify(str)
    test = test.replace(/\\\\/g, '\\')
    return JSON.parse(test)
}

3、State里面的字段要避免特殊名称的命名

taro里的this.setState 遇到一些特殊名称可能会抽风,例如info,data,private等特殊含义的单次都不要用。有的时候还需要setTimeout一下才行

Taro3体验记录

1、每个页面必须要import React from 'react'

2、子组件不会触发onReady, onShow, onHide

上一篇下一篇

猜你喜欢

热点阅读