wepy一些问题和解决方案

wepy一些问题和解决方案

小程序开发和传统的web开发有相识的地方,可是也有不一样的地方,要区分。html

computed属性名和props属性名重复

  • 若是那个组件的渲染值是重名的computed属性,每次点击都是以前的计算加上最新计算的值
  • 定义computed属性名的时候避免和props属性名重复

父子组件传值和Vue中的区别

  • Vue中的prop传值默认是只要父组件的数据改变,子组件同时改变,可是这种模式在wepy中是静态的 也即 :name="name"是静态的,父组件改变name子组件仍是不会变,子组件仍是父组件第一次传进来的值
  • wepy要作到父组件数据变的同时,子组件也跟着变,要加个修饰符.sync,也即:name.sync="name"
  • 还有一个是双向绑定的问题,Vue中能够经过$emit事件的方式实现,这里wepy能够在子组件中的props配置类型、默认值、以及是否双向中的twoWaytrue,就实现了双向数据流
  • 默认twoWay的值是false,若是不是特别须要,请按单向数据的方式传递数据最好,再配合$emit、$broadcast、$invoke,尽可能少用,除非是表单这种

如何给当前自定义组件或者页面类添加静态属性

  • 能够在constructor构造函数中添加静态属性,可是要添加super(),才可使用this来添加静态属性
  • 因为constructor执行时间比较早,全部在这里面的变量,能够直接用于wepy组件,也就是能够和data的数据同样用于数据绑定,可是原生组件只能放在data
  • 若是有些数据是一次性的,不会改变的(静态),最好在constructor中定义,不要都放到data中,data中的数据都会被转换成Observable数据的

组件与组件通讯$broadcast、$emit、$invoke

  • 这些方法不能够在constructor调用,能够在onLoad中调用
  • events用于定义事件,用于接收用的
  • 若是想传数据给子组件,可使用$broadcast('eventName', ...args),可是全部的后代组件都会触发该事件,若是后代组件的events.eventName有定义到,会调用其函数,并将args传给其函数
  • 若是想传数据给父组件可使用$emit,同理,父组件(到根组件)的events要事先定义好事件
  • $broadcast和$emit都会一次触发多个事件,定义events的时候要注意
  • $invoke('./componentName', 'methodName', args)能够直接调用指定组件的方法methods中定义的方法,若是是调用父组件能够用../往上层走,若是要调用下层的./oneLevelComponentName/twoLevelComponentName
  • 若是有不少组件都公用一个方法methods或者events,还可使用mixins

区分Page、App、Component、Mixin这些实例

  • 有些生命周期钩子是那个实例特有的,有些生命周期是全部都共享的

components不一样于Vue或React的组件

  • 小程序的组件和Vue和React组件是有区别的
  • 在wepy中引入组件在components中,和Vue的同样,可是使用的时候是不一样的,一个组件对应一个id,若是在同一个模板中使用同一组件超过2次,它们会共享数据
  • 共享数据指的是props等,能够测试一下,同一个组件传入的props名同样,值不同,最终全部组件那的那个props值是最后一个值
  • 由于它们共享同一个props,多个组件一块儿使用,相似定义多个同名的函数同样,最后使用的是最后一个函数
  • 为了不这种状况下能够用同一个组件去定义多个组件名{ coma: Button, comb: Button },实际上就是new多一个Button
  • 也就是说小程序中的组件在使用的时候,不会自动地new一个新的组件,而是同一个组件,而像Vue和React这样的组件,它们会new一个新的Button实例
  • 还有一种状况是,在循环体<repeat>中,在小程序中就会去new一个新的组件实例,若是你的内容重复,又不想定义多个组件名(new 多个组件),可使用循环体<repeat>
  • 还有一种状况是slot,若是那个组件和数据无关,只是单纯的用于slot模板,它们最终生成的标签是不一样的,由于这些生成的模板和数据无关,若是生成的模板中包含数据,那生成那部分关联数据的元素都是同样的
  • 这里说的数据是<view class='{{ className }}' >{{ data }}</view>这些花括号中的数据classNamedata,它们是共享的,因此它们最终生成的视图是如出一辙的
  • 小程序的组件和目前流行的web组件有很大的区别,不能老用web组件传值得思惟思考(不少莫名的bug),多从广播(订阅)的角度思考

repeat注意点

  • 分两种状况
//repeat包着元素view text等
<repeat for="{{mylist}}">
  <view>{{item.name}}</view>
</repeat>

//repeat包着自定义组件
<repeat for='{{myList}}'>
  <List :mylist.sync="mylist"></List>
  <Item :item='item'></Item>
</repeat>
  • 不支持在repeat的组件中使用propscomputedwatch等特性
  • 在使用repeat的时候,尽可能使用纯文本渲染的组件,纯组件
  • 原生组件的状况下,可使用.或者[]的方式选择想传的数据,可是自定义组件不能够,要整个数据传入,或者传入item([{}, {}]这种格式的数据),item就是wx:item
  • 数据源要在data中,才有效果,静态属性不行
  • 尽可能只包含一个组件,出现多个组件,会出现莫名的bug,其它的功能再在这一个组件内部处理,而后组件间的通讯经过$broadcast、$emit、$invoke
  • 使用组件多使用$broadcast、$emit、$invoke的方式传值,别老想着使用props,会有不少莫名的bug
  • 关于$broadcast、$emit、$invoke,能够经过mixins拯救一下,惟一没什么莫名bug的

Object.create(null)

  • 上面返回的对象不带原型链,也即不包含Object原生对象的信息
  • 小程序中一些数据,像data须要的对象要带原型链,不能用这个,不然在绑定数据到模板的时候会报错

字符串双引号""和单引号''

  • 在模板中务必使用"",别用''(想杀人)
  • :age='2':age="2",前面的''是传不了2age的,除非使用"2",哈哈哈哈哈哈哈哈
  • 在模板中最外层字符串最好用""不要使用'',好比定义事件函数的时候'handlerTap("123")',这里是不成功的给handlerTap传递参数"123",可是"handlerTap('123')"就能够???
  • 正确用法:@tap="handlerTap('love')",最外层用"",最内层''

mixins的computed顺序问题

  • mixins中的computed执行顺序和vue的相反,也即先执行component或者页面的定义的,而后再执行mixins中的
  • 还有就是延迟的问题,mixins的慢于组件或者当前页面定义的,若是想在当前页面获取mixins的一些值,会获取不到

组件传值和模板绑定问题

  • 一个是上面提到的字符串要用双引号
  • 而后就是要区分原生组件和自定义组件

原生组件:就是小程序自带的组件<view>、<text>、<image>等等,这些原生组件绑定数据,要求数据必须在data中,若是绑定的数据不在data中将不会渲染vue

<template>
  <view class="{{className}}">{{text}}</view>
</template>

<script>
import wepy from 'wepy'

// 注意:这个是组件实例
export default class Test extends wepy.component {
  data = {
    text: 123,
    className: 'hahah'
  }
  
  // 因为computed最后返回值会成为data中一部分,computed也能够用于原生组件数据绑定
  // 可是在repeat的时候,不可使用这个,repeat的时候不可使用computed和watch
  computed = {
    text () {
      return this.text + 1
    }
  }
}
</script>

自定义组件:绑定数据能够是data中,也能够用自定义函数,或者静态变量来绑定数据,且绑定数据的方式要和原生小程序的同样,不能用vue的方式react

<template>
  <UserComponent :fn="fn()" :staticV="staticVar" :text="text"/>
</template>

<script>
import wepy from 'wepy'

// 注意:这个是页面实例
export default class Index extends wepy.page {
  constructor () {
    super()
    this.staticVar = 123
  }

  data = {
    text: 123
  }
  
  // 自定义函数
  fn () {
    return '123'
  }
  
  // 因为computed最后返回值会成为data中一部分,computed也能够用于原生组件数据绑定,若是和data中的属性重名,优先使用computed的
  computed = {
    text () {
      return this.text + 1
    }
  }
}
</script>

原生组件的绑定只能是data中的数据,不能够像vue中的那样绑定数据,可是若是是自定义的组件就能够像vue那样绑定数据。还有methods自能用于定义事件处理程序,不能把自定义函数定义在里面web

也就是碰到原生组件的时候,请用原生小程序的方式处理,碰到自定义组件的时候才考虑用你vue的方式处理,也就是区分原生组件和自定义组件很是重要canvas

图片和导航的路径问题

  • 不要在组件中使用相对定位,如../这种,由于当组件被引入到某个页面时,会相对哪一个页面,致使路径没法复用
  • 使用绝对定位,/,在小程序中,/是指的当前项目的文件夹,例如:/pages/index,这里的首个字符/就至关于@/都是指向/src目录
  • 若是是图片,如@/assets/icons/logo.png能够用/assets/icons/logo.png,由于第一个字符是/就至关于@/,表示/src目录之下
  • 若是是导航wx.navigateTo,若是导航到/pages/user,不要使用/或者../,直接user,最终会自动拼成/pages/user,也就是说微信默认/pages/+user

canvas中的canvas-id不能动态赋值

  • 能够经过slot来实现一个组件,不一样canvas-id
<component-name sid="canvas">
    <canvas canvas-id="canvas"></canvas>
  </component-name>
  • component-name是一个组件,接收sid只要是为了能够wx.createCanvasContext(this.sid)
  • 其实咱们在组件的内部只须要知道canvas的id,而且调用wx.createCanvasContext(this.sid),因此咱们能够把canvas独立成slot

在一个组件中引入另外一个组件做为子组件,子组件的样式<style>不起做用

  • 是由于父组件没有<style>标签,致使子组件不编译<style>标签的内容
  • 最好仍是每一个组件都添加<style>标签,即便里面没有内容
相关文章
相关标签/搜索