美文网首页程序员
uniapp坑点(支付宝小程序)

uniapp坑点(支付宝小程序)

作者: xuelulu | 来源:发表于2020-09-30 15:16 被阅读0次

    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变成空对象。
    解决:

    • 对于正则表达式:可传递字符串后,在目标位置new RegExp(regexpStr)
    // parent.vue
    pattern: "\\d"
    
    // test.vue
    let regexp = new RegExp(this.pattern)
    console.log(this.getValue, regexp, regexp.test('abc')) // 已可以正常使用正则的方法
    
    打印
    • 对于函数:new Function('return '+funcStr)无效;可通过其余方法绕行调用如父子组件$emit
      替换办法:
    // 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代码执行。

    报错

    相关文章

      网友评论

        本文标题:uniapp坑点(支付宝小程序)

        本文链接:https://www.haomeiwen.com/subject/ibwxyktx.html