微信小程序

tabber配置

  "tabBar": {
    "color": "#a9b7b7",
    "selectedColor": "#11cd6e",
    "borderStyle": "black" ,
    "list": [
        {
        "selectedIconPath": "icon/home-o.png",
        "iconPath": "icon/home.png",
        "pagePath": "pages/index/index",
        "text": "首页"
      },
      {
        "selectedIconPath": "icon/category-o.png",
        "iconPath": "icon/category.png",
        "pagePath": "pages/category/category",
        "text": "一元投"
      }
    ]
  },

运算

运算符 => 表达式
1.可以在花括号里面加入表达式语句
2.表达式
指的是一些简单的 数组运算 字符串拼接 逻辑运算
1. 数字的加减
2. 字符串拼接
3. 三元表达式

<view>{{ 1 + 1}}</view>
<view>{{ 1 + '2'}}</view>
<view>{{ 10 % 2 === 0 ? '偶数' : '基数'}}</view>
<view>{{ false || 1 }}</view>
<view>{{ true || 1 }}</view>
<view>{{ true && 1 }}</view>

循环

<!-- wx:for循环 -->
<!-- 
  1.wx:for='{{数组或者对象}}' wx:for-item="循环的名称" wx:for-index="循环的索引"
  2.wx:key="唯一的值" 用来提高性能
    1. wx:key 绑定一个普通的字符串的时候 那么这个字符串名称 肯定是数组中的对象的唯一属性
    2. wx:key = "*this" 这种表示循环一个数组的时候用这个
  3. 当出现循环嵌套时候 要注意绑定名称不要重复

-->
<view 
wx:for="{{list}}" 
wx:for-item="item" 
wx:for-index="index" 
wx:key="id">
  {{index}} - {{item.name}}
</view>

<!-- 
    默认情况下 我们不写
      wx:for="{{list}}" 
      wx:for-item="item" 
      wx:for-index="index" 

      item 和 index 也是生效的
      只有一层的话 wx:for-item="item" wx:for-index="index" 可以省略
-->

<view wx:for="{{list}}" wx:key='*this'>{{item.name}}</view>

<!--  
  对象循环
  1.wx:for='{{对象}}' wx:for-item="对象的值" wx:for-index="对象的属性"
  2. 循环对象的时候 最好把item 和 index 的名称改一下
      wx-for-item = 'value' wx:for-index = 'key'
  -->
  <view wx:for="{{obj}}" wx:for-item="value" wx:for-index='key'>
    {{key}} - {{value}}
  </view>

blck

  1. 占位符
  2. 写代码的时候 可以看到整个标签的存在
  3. 页面的渲染小程序会把他移除掉

条件渲染

    条件渲染
    1. wx:if="{{true / false}}"
       wx:if
       wx:elif
       wx:else
    2. hidden
       在标签上直接加入属性hidden
       hidden="{{true}}"
    3. 什么场景使用哪个
      1. 当标签不是频繁切换显示 优先使用 wx:if (直接把标签从页面中移除掉)
      2. 当标签频繁切换显示 优先使用 hidden (通过添加样式方法来切换显示)    

事件绑定

  1. 需要给input标签绑定 input事件
     绑定关键字 bindinput 
  2. 如果获取输入框的值
     通过事件源对象来获取
     e.detail.value
  3. 把输入框的值赋值给data当中
     不能直接用vue中的方法
     this.num = e.detail.value
     正确写法
     this.setData({
       num: e.detail.value
     })
     在js中拿到data的值
     this.data.num
  4. 点击事件 bindtap
     1. 无法在小程序中直接通过函数传参 bindtap='readletap(1)'
     2. 通过自定义属性传递参数 data-num='{{1}}' js中通过e.currentTarget.dataset.num

wxml

<input type="text" value="{{num}}" bindinput="gbInput" />
<button size="mini" bindtap='readletap' data-num='{{1}}'>+</button>
<button size="mini" bindtap='readletap' data-num='{{-1}}'>-</button>
<view>{{num}}</view>

js

// pages/demo1/demo1.js
Page({
  data: {
    num: 0
  },
  gbInput(e) {
    this.setData({
      num: parseInt(e.detail.value)
    })
  },
  readletap(e) {
    this.setData({
      num: e.currentTarget.dataset.num + this.data.num
    })
  }
})

尺寸单位

rpx 可以根据屏幕进行自适应,规定屏幕为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375rpx物理像素,1rpx = 0.5px = 1物理像素。
设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)


image.png

建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

需要把页面中的某些元素的单位 由 px 改成prx

1 设计稿 750 px
    750 px = 750 rpx
    1 px = 1 rpx
2 把屏幕高度改成 375
    375 px = 750 rpx
    1 px = 2rpx
    1rpx = 0.5px
3 如果存在一个设计稿 宽度 414 或者 未知 page
   1 设计稿 page 存在一个元素 宽度 100px
   2 拿以上的需求 去实现 不同宽度的页面适配

    page px = 750rpx
    1 px = 750rpx / page
    100 px = 750 rpx * 100 / page

样式导入

通过@ import 来引入
路径只能写相对路径

@ import “../../styles/common.wxss”;

选择器和使用less

小程序不知此通配符 *{}


image.png

常见标签

常用 view, text, rich-text, button, image, navigator, icon, swiper, radio, checkbox。 等等

text

text的decode可以解析的有 &nbsp; &lt; &gt; &amp; &apos; &ensp; &emsp;

image

   image 图片标签
   1 src 指定要加载的图片路径
     图片存在默认的宽度和高度 320 * 240 不设置宽高,就会默认320 * 240
   2 mode 决定 图片内容 如何 和 图片标签 宽高 适配 列举一些常用的
      1. scaleToFill 默认值 不保持丛横比缩放图片,使用图片的宽高完全拉伸填满 image 元素
      2 aspectFit 保持宽高比 确保图片的长边 显示出来 适合页面轮播图 (常用)   
      3 aspectFill 保持纵横比缩放图片, 只保证图片的 短 边能完全显示出来。 (少用)
      4 widthFix 以前web图片的 宽度指定后 高度会自己安装比例来调整 (常用)
      5 bottom。。 类似以前的background-position
   3. 小程序中的image 直接支持 懒加载 lazy-load
      1. lazy-load会自己判断 当 图片 出现在视口 上下 三屏的时候 自己开始加载图片

Swiper

    swiper 标签 存在默认样式
      width:100%
      height: 150px image 存在默认宽度和高度 320 * 240
      swiper高度无法实现由内容撑开
    先找出 原图的宽度和高度 等比例 给swiper 定 宽度和高度
      原图的宽度和高度 750 * 310
      swiper 宽度 / swiper 宽度 = 原图的宽度 / 原图的高度
      swiper 高度 = swiper 宽度 * 原图的高度 / 原图的宽度
      height:
       * 310 / 750  
      窗口固定宽度为100vw,将窗口宽度平均分为100份,每一份是1vw。
      窗口固定高度为100vh,将窗口高度平均分为100份,每一份是1vh。
<swiper>
  <swiper-item>
    <image mode="widthFix" src="//pic50.t8tcdn.com/adcms/ad/201909/25/c8cad7f58fd875d5d3ef020f11c7886d6696.jpg" />
  </swiper-item>
  <swiper-item>
    <image mode="widthFix" src="//pic50.t8tcdn.com/adcms/ad/202001/17/938f8f2dbb8e1c30bd47cda9ca65f5cb83269.jpg" />
  </swiper-item>
</swiper>

wxss

swiper{
  width: 100%;
  /* height: calc(750rpx * 310 / 750); */
  height: calc(100vw * 310 / 750);
  /*height: 图片的高度也可以*/
}
image {
  width: 100%;
}

navigator

  导航组件 navigator
  块级元素 默认会换行 可以直接加宽度高度
  1 参数 url 要跳转的页面路径 可以绝对路径 相对路径
  2 参数 target 要跳转到当前的小程序 还是其他的小程序
    target = 'self' 默认值 自己小程序页面
    miniprogram 其他小程序页面
  3 open-type 跳转方式 
    1 navigator 默认值 保留当前页面,跳转到应用内的某个页面,但不能跳到tabbar页面
    2 redirect 关闭当前页面,跳转到应用内的某个页面,但不允许跳转tabber
    3 switchTab 跳转到 tabber 页面,并关闭所有非 tabBer 页面
    4 reLaunch 关闭所有页面 打开到应用中
 
 <!-- navigator 默认值 跳转到pages/demo/demo 顶部显示可以返回箭头 可返回当前页面 -->
<navigator url="/pages/demo/demo">跳转</navigator>
<!-- redirect 跳转到pages/demo/demo 顶部左上角显示返回首页 关闭当前页面 不能返回当前页面 -->
<navigator url="/pages/demo/demo" open-type="redirect">跳转</navigator>
<!-- 跳转到 tabber 页面,不能返回非tabber的页面 -->
<navigator open-type="switchTab" url="/pages/index/index"></navigator>
<!-- reLaunch 可以随便跳转哪个页面 左上角返回首页 关闭当前页面 -->
<navigator open-type="reLaunch" url="/pages/demo/demo">reLaunch 跳转</navigator>

rich-text 富文本标签

可以解决服务端传过来的富文本编辑的文章
wxml

<rich-text nodes="{{html}}"></rich-text>

js

// pages/demo3/demo3.js
Page({
  data: {
    html: '<div style="color: red">哈哈哈</div>'
  },
})

button外观样式

  button
  外观的属性
    1 size 控制按钮的大小 默认是大尺寸
      sizr='mini' 小尺寸
    2 type 用来控制按钮的颜色
      type='default' 灰色
      type='primary' 绿色
      type='warn' 红色  
    3 plain 镂空  
    4 loading 在按钮前面会有一个loading
<button size='mini'>按钮</button>
<button>default按钮</button>
<button type='primary'>primary按钮</button>
<button type='warn'>warn按钮</button>
<button type='warn' plain>plain按钮</button>
<button type='primary' loading>loading</button>

button 开放能力

 button
   open-type:
    1 contact 直接打开 客服对话功能 需要在微信小程序的后台配置
    2 share 转发当前的小程序 到微信朋友中 不能把小程序 分享到朋友圈
    3 getPhoneNumber 获取当前用户手机号码信息 结合一个事件来使用 不是企业的小程序账号 没有权限来获取用户手机号码
      1 绑定一个事件bindgetphonenumber
      2 在事件的回调函数中 通过参数来获取信息
      3 获取到的信息 已经加密过了
        需要搭建小程序后台,在后台服务器中进行解析,然后再传到小程序页面中 就可以看到用户的手机号码了
    4 getUserInfo 获取当前用户的个人信息
      使用方法 类似 获取当前用户的手机号码
      可以直接获取 不存在加密的字段
      通过 回调 bindgetuserinfo = 'getInfo'
      getInfo(e) {}
    5 launchApp 在小程序当前直接打开app 页面
      需要 在app中 通过app的某个链接打开小程序
      在小程序中在通过这个功能重新打开app
    6 openSetting 打开小程序的内置 授权页面
      授权页面中 只会出现用户曾经授权过的权限
    7 feedback 打开小程序 内置的 用户意见反馈页面
      只能通过真机来打开
<button open-type='contact'>contact</button>
<button open-type='share'>share</button>
<button open-type='getPhoneNumber' bindgetphonenumber="getPhone">getPhoneNumber</button>
<button open-type="getUserInfo" bindgetuserinfo="getInfo">getUserInfo</button>
<button open-type="openSetting">openSetting</button>
<button open-type="feedback">feedback</button>
<image src="{{userInfo.avatarUrl}}"></image>

icon

image.png

单选框

  radio 单选框
  1 radio标签 必须和父元素 radio-group 来使用
  2 value 选中的单选框的值
  3 需要给radio-group 绑定bindchange事件
  4 需要在页面中显示选中的值
  5 color 改变单元框的颜色
  <radio-group bindchange='getGender'>
    <radio value='男' checked="{{true}}"  color='red'>男</radio>
    <radio value='女'>女</radio>
  </radio-group>
  <view>选中的信息:{{gender}}</view>
// pages/demo5/demo5.js
Page({
  data: {
    gender: '男',
    current: 0
  },
  getGender(e) {
    let gender = e.detail.value
    this.setData({
      gender
    })
  },
  nextFn() {
    let _this = this.data;
    if(_this.current === 2) {
      this.setData({
        current: 0
      })
    }else {
      this.setData({
        //前加加  先加在赋值
        current: ++ this.data.current
        //不起作用是因为 后加加 先赋值后加价
        // current: this.data.current++
      })
    }
  }
})

checkbox

<view>
  <checkbox-group bindchange='getValue'>
    <checkbox wx:for="{{list}}" value="{{item.value}}" wx:key="id">
      {{item.name}}
    </checkbox>
  </checkbox-group>
</view>
// pages/demo6/demo6.js
Page({
  data: {
    list: [
      {
        id: 1,
        name: '苹果',
        value: 'apply'
      },
      {
        id: 2,
        name: '葡萄',
        value: 'grape'
      },
      {
        id: 3,
        name: '香蕉',
        value: 'banana'
      }
    ],
    checkList: []
  },
  getValue(e) {
    this.setData({
      checkList: e.detail.value
    })
    console.log(e);
  }
})

小程序自定义组件初体验

第一步 创建components文件夹,在components文件夹中建一个组件


image.png

第二步 在想用组件的地方,打开json修改 组件路径

{
  "usingComponents": {
    "Tabs1": "../../components/Tabs/Tabs"
  }
}

第三步 在wxml 中使用

<Tabs1></Tabs1>

自定义组件-父向子传递数据

父组件wxml

<!--pages/demo1/demo1.wxml-->
<Tabs1 abc="abc123"></Tabs1>

子组件js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    //要接受父组件的名称,子组件直接用{{abc}} 即可
    abc: {
      type: String, //要接受的数据类型
      value: ' ' //默认值,如果父组件不传值,就以value值为准
    }
  },
})

子组件wxml

<view>
    //页面上的值 就是 abc123
    {{abc}}  
</view>

父向子传递数据demo

父组件wxml

<Tabs1 tabs="{{tabs}}"></Tabs1>

父组件js

// pages/demo1/demo1.js
Page({
  data: {
    tabs: [
      {
        id: 1,
        name: '首页',
        active: true
      },
      {
        id: 2,
        name: '原创',
        active: false
      },
      {
        id: 3,
        name: '分类',
        active: false
      },
      {
        id: 4,
        name: '关于',
        active: false
      }
    ]
  }
})

子组件js

// components/Tabs.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    //要接受父组件的名称,子组件直接用{{abc}} 即可
    tabs: {
      type: Array, //要接受的数据类型
      value: [] //默认值,如果父组件不传值,就以value值为准
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
    eventTabs(e) {
      let { index } = e.target.dataset;
      let { tabs } = this.data;
      //forEach 改变原数组
      tabs.forEach((v, i) => i === index ? v.active = true : v.active = false);
      this.setData({
        tabs
      })
    }
  }
})

子组件wxml

<view class="tabs">
    <view class="tabs_title">
        <!-- wx:for 循环默认 又 wx:for-item = 'item' 可以拿到循环的内容  wx:for-index = "index" 可以拿到循环的索引      -->
        <view
                bindtap="eventTabs"
                wx:for="{{tabs}}"
                wx:key="id"
                data-index = '{{index}}'
                class="tabs-item {{item.active ? 'active' : ''}}">
            {{item.name}}
        </view>
    </view>
</view>

子元素向父元素传递数据

子向父传递数据 通过事件的方式传递
在子组件的标签中加入一个自定义组件

  • 子组件js
  methods: {
    eventTabs(e) {
      let { index } = e.target.dataset;
      //向父组件传递值
      // 触发父组件中的自定义组件 同时传递数据 给 父组件
      // this.triggerEvent('父组件自定义的事件名称', { 要传递的参数 })
      this.triggerEvent('changeItem', { index });
    }
  }
  • 父组件wxml
//bindchangeItem 是子组件自定义的事件
<Tabs1 tabs="{{tabs}}" bind:changeItem="handleItemChange"></Tabs1>

父组件js

  handleItemChange(e) {
    let { index } = e.detail;  // 1
    //上面代码等价于
    //let index = e.detail.index
  }

slot 插槽

    slot 标签 其实就是一个占位符 插槽
    等到 父组件 调用 子组件的时候 再传递 标签过来 最终这些被传递的标签
    就会替换slot插槽位置

子组件wxml

<view>
        <!--
            slot 标签 其实就是一个占位符 插槽
            等到 父组件 调用 子组件的时候 再传递 标签过来 最终这些被传递的标签
            就会替换slot插槽位置
        -->
        <slot></slot>
</view>

父组件wxml

<Tabs1>
    父组件传过来的值
</Tabs1>

组件的其他属性

image.png

app.js 应用生命周期

App({
  // 应用第一次启动的就会触发的事件
  onLaunch() {
    // 在应用第一次启动时候, 获取个人信息
    console.log('onLaunch');
  },
  // 应用 被用户看见 触发事件
  onShow() {
    // 对应用的数据或者页面效果重置
    console.log('onShow');
  },
  // 应用隐藏 触发事件
  onHide() {
    //暂停或者清除定时器
    console.log('onHide');
  },
  // 应用的代码发生报错的时候 就触发
  onError (err) {
    // 在应用发生代码报错的时候,收集用户的错误信息。通过异步请求 将错误信息发送到后台去
    console.log('onError');
  },
  // 页面找不到j就会触发
  // 应用第一次启动的时候,如果找不到第一个入口页面 才会触发 类似404页面 找不到页面 就跳到其他页
  onPageNotFound() {
    console.log('onPageNotFound');
    wx.navigateTo({
      url: 'pages/demo1/demo1',
    })
  }
})

页面生命周期

/**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    //发送一些异步请求来初始化页面数据
    console.log('onLoad');
  },


  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    console.log('onShow');
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    console.log('onReady');
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
    console.log('onHide');
  },

  /**
   * 生命周期函数--监听页面卸载 就是跳转链接 左上角没有返回箭头
   */
  onUnload: function () {
    console.log('onUnload');
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   * 要在app.json中配置
   * "enablePullDownRefresh": true,
     "backgroundColor": "#ccc",
      更新一些数据接口
   */
  onPullDownRefresh: function () {
    console.log('onPullDownRefresh')
  },

  /**
   * 页面上拉触底事件的处理函数
   * 页面上拉底部触发事件
   * 需要让页面 上线上下滚动才行
   */
  onReachBottom: function () {
    console.log('onReachBottom');
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
    console.log('onShareAppMessage');
  },

  /**
   * 只有页面一滚动就会触发
   * */
  onPageScroll() {
    console.log('onPageScroll');
  },
  /**
   * 当前是tab页面时候,点击tab触发
   * */
  onTabitemTap() {

  }

request 网络请求

image.png

GET

wx.request({
    url: 'con.theme_user',
    method: 'GET',
    data: {
        act: 'getUserInfo',
        wxappid: confirm.wyy_user_wxappid,
        openid: resizeBy.data.openid
    },
    header: {
        "Content-Type": "application/json"
    },
    success: (res) => {
        console.log(res.data);
        // 存放用户基本信息
        this.setData({
            userInfo: res.data.userInfo,
            hasUserInfo: true,
            canIUse: true
        })
    }
})
wx.request({
    header: {
        "content-type": "application/json"
    },
    method: "POST",
    url: `${this.globalData.api}login/token`,
    data: {
        code: code
    },
    success: res => {
        var token = res.data.data
        console.log(token);
        wx.setStorageSync('token', token);
        // 设置完token之后获取首页数据
        // resolve()
    }
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容