程序员

uniapp坑点(支付宝小程序)

2020-09-30  本文已影响0人  xuelulu

1. pageInstance不能挂载在data上 => 扩展:Function对象不能挂载在data上

let pages = getCurrentPages();
this.pageInstance = pages[pages.length - 1]; // 会报错
let pageInstance = pages[pages.length - 1]; // 不报错
报错

解决:用的时候重新调用一遍获取。

2. 在父组件里对引用的自定义组件及组件内部设置样式无效果

<template>
  <view class="test">
    <tabbar-item
      v-for="item in tabbars"
      :key="item.name"
      :class="{ 'no-border-button': fullPath === item.path }"
    >
      ...
    </tabbar-item>
  </view>
<template>
<style lang="scss">
.test { // 有效,.tabbar-item,.tabbar-item-content是自定义组件内部的class
  .tabbar-item {...}
  .tabbar-item-content {...}
} 
</style>
<style lang="scss" scoped>
.no-border-button {...} // 无效
</style>

解决:用全局样式,不用scoped

3. 对自定义组件设置普通监听事件无效,需内部触发事件

<cell
  class="cell"
  title="合规商户"
  is-link
  @click="handleMarketClick(item, 0)" // 单方面设置无效
>
  ...
</cell>

解决:

// cell.vue
<view class="cell" @click="$emit('click')"> // 需要内部触发
...
</view>

4. scroll-view的upper-threshold设为0的话不触发scrolltoupper

<scroll-view
  class="scroll-view"
  :scroll-y="true"
  :upper-threshold="0"
  :lower-threshold="300"
  @scroll="handleScroll"
  @scrolltoupper="handleScrolltoupper"
  @scrolltolower="handleScrolltolower"
>

解决:设置为不为0的小数字

5. mixins的components不能混入

// 会报错找不到mixins里面定义的组件<testComponent>
<template>
  <view>
    ...
    <testComponent />
    ...
  </view>
</template>
<script>
export default {
  mixins: [test],
  ...
}
</script>
// test.js
import test from '...'
export default {
  components: { test },
  ...
}

扩展:与template有关系的用components作复用,与script有关系的用mixins复用 或者 抽取成为公共js使用
解决:components及其引入放在组件里做

// 可正常使用components和mixins里面的js
<template>
  <view>
    ...
    <testComponent />
    ...
  </view>
</template>
<script>
import test from '...'
export default {
  mixins: [test],
  components: { test },
  ...
}
</script>

6. this.$refs获取不到设置了ref的元素

官方解读:

image.png

尝试:(1) 内置组件如官方所示,获取了undefined。
(2) 对自定义组件使用$refs,在mounted和onReady时机下可以获取到值。

<test ref="textArea">
  <text class="title">{{title}}111</text>
</test>
...
import test from '@/components/test/test.vue'
  export default {
    components: {
      test
    },
...

打印:Router是子组件内部的打印

打印$refs

(3)子组件slot中自定义组件的$refs,直接this.$refs获取不到,需经过子组件的一层$refs才能获取到内部的$refs,如下

<test>
  <titleBox class="title" ref="childTitle">{{title}}111</titleBox>
</test>
...
import titleBox from '@/components/cell.vue'
import test from '@/components/test/test.vue'
export default {
  components: {
    test,
    titleBox
  },
  mounted() {
    console.log('mounted: ', this.$refs.childTitle) // 输出 mounted: undefined
  },
  onReady() {
    console.log('onReady: ', this.$refs.childTitle) // 输出 onReady: undefined
  },
...

此时是获取不到this.$refs.childTitle的,它是属于子组件底下的$refs
解决:

<test  ref="textArea">
  <titleBox class="title" ref="childTitle">{{title}}111</titleBox>
</test>
...
import titleBox from '@/components/cell.vue'
import test from '@/components/test/test.vue'
export default {
  components: {
    test,
    titleBox
  },
  mounted() {
    console.log('mounted: ', this.$refs.textArea, this.$refs.textArea.$refs.childTitle)
  },
  onReady() {
    console.log('onReady: ', this.$refs.textArea, this.$refs.textArea.$refs.childTitle)
  },
...
打印

参考:https://www.lervor.com/archives/121/

7. 一些基础组件如icon无监听点击事件

解决:可在外层包一个view作事件监听

<view class="clear-icon" @click="onClear">
  <icon v-if="showClear" type="clear" size="16"></icon>
</view>

8. class绑定里,如果一个对象里有多个属性值,渲染出来的class会带英文逗号 ,

<view
  :class="[
    styleType === 'text'
      ? 'segmented-control__item--text'
      : 'segmented-control__item--button',
    {
      'segmented-control__item--button--active':
        index === currentIndex && styleType === 'button',
      'segmented-control__item--button--first':
        index === 0 && styleType === 'button',
      'segmented-control__item--button--last':
        index === values.length - 1 && styleType === 'button',
      disabled: item.disabled
    }
  ]"
  >

class渲染的结果:

segmented-control__item data-v-5311d210 segmented-control__item--text ,,,disabled

此时disabled就失效了。
解决:拆开来赋值。

styleType === 'text'
  ? 'segmented-control__item--text'
  : 'segmented-control__item--button',
{
  'segmented-control__item--button--active':
    index === currentIndex && styleType === 'button'
},
{
  'segmented-control__item--button--first':
    index === 0 && styleType === 'button'
},
{
  'segmented-control__item--button--last':
    index === values.length - 1 && styleType === 'button'
},
{ disabled: item.disabled }

class渲染的结果:

segmented-control__item data-v-5311d210 segmented-control__item--text    disabled

9. 不能在template里直接写js方法(也不美观),编辑器不会报错,但模拟器会报错编译失败,build error => 扩展:不可在template中写js代码

<van-field
...
@input="
  isX(form.shopIdcard, () => {
    form.shopIdcard = form.shopIdcard + 'X';
  })
"
/>
模拟器报错

解决:把这种方法放在methods里

<van-field
...
@input="handleInput"
/>
...
methods: {
  handleInput () {
    isX(form.shopIdcard, () => {
      form.shopIdcard = form.shopIdcard + 'X';
    })
  }
}

10. picker-view的注意点:

(1)注意要加<picker-view-column>,否则会报错。必须有一层元素包住内容。
(2)在初始为空内容(如此处的areaList初始为[])时渲染则会出现不可滑动的情况。因为在渲染时会根据初始内容确定每一项高度,后续无法动态确定高度。必须加上v-if="showPicker"

<view v-if="showPicker" class="picker-box">
  <picker-view :value="currentPick" @change="handlePickerChange">
    <picker-view-column>
      <view
        v-for="(item, index) in areaList"
        :key="index"
        >{{ item.text }}</view>
    </picker-view-column>
  </picker-view>
  <view class="picker-view mask"></view>
  <button class="button" @click="onConfirmSearchArea">
    确认
  </button>
</view>

11. 在checkbox或radio外包一层label就可以点击文字部分也能控制checkbox或radio的选中了(文档中未讲但示例中有此写法)

 <checkbox-group @change="handleManageModeChange">
  <label
    class="checkbox-item"
    v-for="item in manageModeSelection"
    :key="item.dictCode"
  >
    <p
    >
      {{ item.dictName }}
    </p>
    <checkbox
      class="checkbox"
      :value="item.dictCode"
      :checked="item.checked"
      color="#1989fa"
    />
  </label>
</checkbox-group>

12. 数组的深层监听无效

watch: {
  arr: {
    handler(val){
      ...
    }, deep: true
  }
}

13. 不支持new Function()和eval()

(1) new Function()

mounted() {
  let funcStr = this.checkIDCard.toString();
  let func = new Function('return ' + funcStr);
  console.log(funcStr, func, Object.prototype.toString.apply(func)); 
  // 运行func()会报错TypeError: func is not a function
},
methods: {
  checkIDCard() { ... }
}
打印

(2)eval()

mounted() {
  let funcStr = this.checkIDCard.toString(); // 转函数为字符串,可作为参数传递至别的方法或组件中;
  // 或this.checkIDCard + ''或String(this.checkIDCard)
  let func = eval("(false || "+funcStr+")"); // 报错
},
methods: {
  checkIDCard(params) { ... }
}
控制台报错

14. regexp和function无法参与到组件间参数props传递

// parent.vue
<test ref="textArea" :getValue="getValue" :pattern="pattern">
</test>
...
components: {
  test
},
data() {
  return {
    pattern: /\d/ 
  }
},
methods: {
  getValue(params) {
    console.log(params)
  }
}
// test.vue
props: ['getValue', 'pattern'],
mounted() {
  console.log(this.getValue, this.pattern)
},
打印

如图,经过props传递的两个参数,function变成未定义,regExp变成空对象。
解决:

// parent.vue
pattern: "\\d"
// test.vue
let regexp = new RegExp(this.pattern)
console.log(this.getValue, regexp, regexp.test('abc')) // 已可以正常使用正则的方法
打印
// parent.vue
<test ref="textArea" :getValue="funcName" :pattern="pattern">
</test>
...
components: {
  test
},
data() {
  return {
    pattern: "\\d",
    funcName: "getValue"
  }
},
methods: {
  getValue(params) {
    console.log(params)
  }
}
// test.vue
props: ['getValue', 'pattern'],
mounted() {
  console.log(this.$parent[this.getValue], regexp, regexp.test('abc'))
},
打印

拓展:在h5中,函数字符串转函数的方法有
参考:js字符串转函数
(1) new Function()

function checkIDCard(params) { ... }
export default { ...
  mounted() {
    let funcStr = checkIDCard.toString(); // 转函数为字符串,可作为参数传递至别的方法或组件中;
    // 或checkIDCard + ''或String(checkIDCard)
    let func = new Function('return ' + funcStr)(); // 转字符串为函数
    let params=...
    func(params); // 运行函数
  },
  methods: {
    checkIDCard(params) { ... }
  }
}

(2)eval()

function checkIDCard(params) { ... }
export default { ...
  mounted() {
    let funcStr = checkIDCard.toString(); // 转函数为字符串,可作为参数传递至别的方法或组件中;
    // 或checkIDCard + ''或String(checkIDCard)
    let func = eval("(false || "+funcStr+")"); // 转字符串为函数
    let params=...
    func(params); // 运行函数
  },
  methods: {
    checkIDCard(params) { ... }
  }
}

注:若使用this.checkIDCard会出错,因为this.checkIDCard.toString() => "function () { [native code] }",这种字符串无法作为js代码执行。

报错
上一篇下一篇

猜你喜欢

热点阅读