Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WePY开发微信小程序 #9

Open
WangShuXian6 opened this issue Apr 30, 2018 · 19 comments
Open

WePY开发微信小程序 #9

WangShuXian6 opened this issue Apr 30, 2018 · 19 comments

Comments

@WangShuXian6
Copy link
Owner

WangShuXian6 commented Apr 30, 2018

安装

npm install wepy-cli -g
wepy init standard my-project

更新

wepy upgrade

初始化项目后的注意事项:

关闭ES6转ES5,由WePY自动处理
关闭样式自动补全,由WePY自动处理
关闭代码压缩

安装util

否则可能报错 module "npm/lodash/_nodeUtil.js" is not defined

npm i util --save-dev

安装wepy-compiler-typescript

https://www.npmjs.com/package/wepy-compiler-typescript

npm install wepy-compiler-typescript --save-dev
<script lang="typescript" src ="./index.ts"></script>

安装less autoprefix

npm install less-plugin-autoprefix --save-dev

wepy.config.js

const LessPluginAutoPrefix = require('less-plugin-autoprefix');

//...
//...

  compilers: {
    less: {
      compress: true,
      plugins: [new LessPluginAutoPrefix({browsers: ['Android >= 2.3', 'Chrome > 20', 'iOS >= 6']})]
    }

wepy-async-function

npm install wepy-async-function --save

wepy.config.js

babel: {
            "presets": [
                "env"
            ],
            "plugins": [
                "transform-export-extensions",
                "syntax-export-extensions"
            ]
        }

app.wpy

import 'wepy-async-function'

export default class extends wepy.app {

    constructor () {
        super();
        this.use('promisify');
    }

}
wepy build --no-cache

promise-polyfill

npm install promise-polyfill --save

app.wpy

import Promise from 'promise-polyfill'

export default class extends wepy.app {

    constructor () {
        super();
        this.use('promisify');
    }

}

详细说明 https://github.com/Tencent/wepy/wiki/升级指南

wepy 文件压缩插件

https://github.com/Tencent/wepy/tree/master/packages/wepy-plugin-filemin
支持css,xml,json的压缩

安装
npm install wepy-plugin-filemin --save-dev
配置wepy.config.js

module.exports.plugins = {
    'filemin': {
        filter: /\.(json|wxml|xml)$/
    }
};

wepy生产文件去注释

配置wepy.config.js

module.exports.plugins = {
    uglifyjs: {
      filter: /\.js$/,
      config: {
        comments: false // 去注释
      }
    },
    imagemin: {
      filter: /\.(jpg|png|jpeg)$/,
      config: {
        jpg: {
          quality: 80
        },
        png: {
          quality: 80
        }
      }
    },
    'filemin': {
      filter: /\.(json|wxml|xml)$/
    }
  }

快速开始配置

package.json

{
  "name": "news",
  "version": "0.0.2",
  "description": "A WePY project",
  "main": "dist/app.js",
  "scripts": {
    "dev": "wepy build --watch",
    "build": "cross-env NODE_ENV=production wepy build --no-cache",
    "dev:web": "wepy build --output web",
    "clean": "find ./dist -maxdepth 1 -not -name 'project.config.json' -not -name 'dist' | xargs rm -rf",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "wepy": {
    "module-a": false,
    "./src/components/list": "./src/components/wepy-list.wpy"
  },
  "author": "王树贤 <[email protected]>",
  "license": "MIT",
  "dependencies": {
    "crypto-js": "^3.1.9-1",
    "promise-polyfill": "^8.0.0",
    "redux": "^3.7.2",
    "redux-actions": "^2.2.1",
    "redux-promise": "^0.5.3",
    "wepy-redux": "^1.5.3",
    "wepy": "^1.6.0",
    "wepy-async-function": "^1.4.4",
    "wepy-com-toast": "^1.0.2"
  },
  "devDependencies": {
    "babel-eslint": "^7.2.1",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-export-extensions": "^6.22.0",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "cross-env": "^5.1.3",
    "eslint": "^3.18.0",
    "eslint-config-standard": "^7.1.0",
    "eslint-friendly-formatter": "^2.0.7",
    "eslint-plugin-html": "^2.0.1",
    "eslint-plugin-promise": "^3.5.0",
    "eslint-plugin-standard": "^2.0.1",
    "less-plugin-autoprefix": "^1.5.1",
    "util": "^0.11.0",
    "wepy-compiler-babel": "^1.5.1",
    "wepy-compiler-less": "^1.3.10",
    "wepy-compiler-typescript": "^1.5.9",
    "wepy-eslint": "^1.5.3",
    "wepy-plugin-imagemin": "^1.5.3",
    "wepy-plugin-uglifyjs": "^1.3.7"
  }
}

wepy.config.js

const path = require('path');
var prod = process.env.NODE_ENV === 'production';
const LessPluginAutoPrefix = require('less-plugin-autoprefix');

module.exports = {
  wpyExt: '.wpy',
  eslint: true,
  cliLogs: !prod,
  build: {
    web: {
      htmlTemplate: path.join('src', 'index.template.html'),
      htmlOutput: path.join('web', 'index.html'),
      jsOutput: path.join('web', 'index.js')
    }
  },
  resolve: {
    alias: {
      counter: path.join(__dirname, 'src/components/counter'),
      '@': path.join(__dirname, 'src')
    },
    aliasFields: ['wepy', 'weapp'],
    modules: ['node_modules']
  },
  compilers: {
    less: {
      compress: true,
      plugins: [new LessPluginAutoPrefix({browsers: ['Android >= 2.3', 'Chrome > 20', 'iOS >= 6']})]
    },
    /*sass: {
      outputStyle: 'compressed'
    },*/
    babel: {
      sourceMap: true,
      presets: [
        'env'
      ],
      plugins: [
        'transform-class-properties',
        'transform-decorators-legacy',
        'transform-object-rest-spread',
        'transform-export-extensions',
        "syntax-export-extensions",
      ]
    }
  },
  plugins: {
  },
  appConfig: {
    noPromiseAPI: ['createSelectorQuery']
  }
}

if (prod) {

  // 压缩sass
  // module.exports.compilers['sass'] = {outputStyle: 'compressed'}

  // 压缩js
  module.exports.plugins = {
    uglifyjs: {
      filter: /\.js$/,
      config: {
      }
    },
    imagemin: {
      filter: /\.(jpg|png|jpeg)$/,
      config: {
        jpg: {
          quality: 80
        },
        png: {
          quality: 80
        }
      }
    }
  }
}

app.wpy

<style lang="less">
  .container {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    box-sizing: border-box;
  }
</style>

<script>
  import wepy from 'wepy'
  import 'wepy-async-function'
  import Promise from 'promise-polyfill'

  import { setStore } from 'wepy-redux'
  import configStore from './store'

  const store = configStore()
  setStore(store)

  export default class extends wepy.app {
    config = {
      pages: [
        'pages/index'
      ],
      window: {
        backgroundTextStyle: 'light',
        navigationBarBackgroundColor: '#fff',
        navigationBarTitleText: 'WeChat',
        navigationBarTextStyle: 'black'
      }
    }

    globalData = {
      userInfo: null
    }

    constructor () {
      super()
      this.use('requestfix')
      this.use('promisify');
    }

    onLaunch() {

    }

    getUserInfo(cb) {
      const that = this
      if (this.globalData.userInfo) {
        return this.globalData.userInfo
      }
      wepy.getUserInfo({
        success (res) {
          that.globalData.userInfo = res.userInfo
          cb && cb(res.userInfo)
        }
      })
    }
  }
</script>


wepy d.ts 类型申明
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/wepy/index.d.ts

npm install --save-dev @types/wepy
@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented May 5, 2018

错误解决

1.6.0
module "npm/lodash/_nodeUtil.js" is not defined

npm i [email protected] --save
wepy build --no-cache
npm install autoprefixer --save-dev
npm install wepy-compiler-babel --save-dev

wepy命令失效
重新安装wepy-cli

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented May 10, 2018

解析

事件中默认传入事件对象,如果手动传入参数,则事件接受一个数组,数组前面位为参数,末位为事件对象

<view @tap="removeFromCart({{pid}})">-</view>

removeFromCart(arg)
arg为数组。


组件内事件传参
需要更新父页面以强制刷新子组件

<template>
  <repeat for="{{cates}}" key="key" index="index" item="item">
          <view class="cate-container" @tap="handleCategory({{index}})">
            <cateCard :info="item" class="cate-wrapper " />
          </view>
  </repeat>
</template>
import wepy from 'wepy'
import {connect} from 'wepy-redux'

@connect({},{})
export default class Card extends wepy.component {
  methods = {
    handleCategory(index,e){
      console.log('handleCategory-e--',e)
      console.log('handleCategory-index--',index)
    }
  }
}

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented May 16, 2018

状态和dispatch动作在js里的调用

混入

@connect({
    header(state){
      return state.header
    }
  },{
    select:SELECT_PERSON
  })

dispatch Action

this.methods.select(info)

状态

console.log(this.header)

@WangShuXian6
Copy link
Owner Author

vscode 插件

wpy-beautify

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Jun 22, 2018

小程序特殊情况处理

页面数据不实时更新

this.$apply()

引用组件时wx-if属性无效

<template>
  <switchTabLine wx-if="{{true}}" :switchTitleList.sync="switchTitleList" />
</template>

不应该在wepy中循环自定义组件, 应该在组件内循环从父组件获取的列表数据

<!-- 错误使用 -->
// list.wpy
<view>{{test.name}}</view>

// index.wpy
<repeat for="{{mylist}}">
   <List :test.sync="item"></List>
</repeat>

<!-- 推荐用法 -->
// list.wpy
<repeat for="{{mylist}}">
    <view>{{item.name}}</view>
</repeat>

// index.wpy
<List :mylist.sync="mylist"></List>

scroll外层元素为固定或绝对货粘性定位时,无法滚动
将固定定位设置在scroll元素上即可解决


input 的父元素不可以是固定定位,会使input无法使用

@WangShuXian6
Copy link
Owner Author

编辑器

VSCode

扩展插件
同vue

代码格式化插件
wpy-beautify
快捷键
windows :: cmd+shift+f
mac::windows键盘:Alt+shift+f


@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Jun 29, 2018

请求方式

需大写-有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
注意:没有PATCH

requestGet() {
    wepy
      .request({
        url: '',
        method: 'GET',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('GET api---', response.data);
      })
      .catch(error => {
        console.log('GET api error---', error);
      });
  }
  requestPost() {
    wepy
      .request({
        url: '',
        method: 'POST',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('POST api---', response.data);
      })
      .catch(error => {
        console.log('POST api error---', error);
      });
  }
  requestPut() {
    wepy
      .request({
        url: '',
        method: 'PUT',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('PUT api---', response.data);
      })
      .catch(error => {
        console.log('PUT api error---', error);
      });
  }
  // 小程序http请求没有Patch方法,此方法将返回错误
  requestPatch() {
    wepy
      .request({
        url: '',
        method: 'PATCH',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('PATCH api---', response.data);
      })
      .catch(error => {
        console.log('PATCH api error---', error);
      });
  }
  requestDelete() {
    wepy
      .request({
        url: '',
        method: 'DELETE',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('DELETE api---', response.data);
      })
      .catch(error => {
        console.log('DELETE api error---', error);
      });
  }
  requestOptions() {
    wepy
      .request({
        url: '',
        method: 'OPTIONS',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('OPTIONS api---', response.data);
      })
      .catch(error => {
        console.log('OPTIONS api error---', error);
      });
  }
  requestHead() {
    wepy
      .request({
        url: '',
        method: 'HEAD',
        data: {
          test: 'test'
        },
        header: {
          'Content-Type': 'Application/json;charset=UTF-8'
        }
      })
      .then(response => {
        console.log('HEAD api---', response.data);
      })
      .catch(error => {
        console.log('HEAD api error---', error);
      });
  }

data 数据说明:

最终发送给服务器的数据是 String 类型,如果传入的 data 不是 String 类型,会被转换成 String 。转换规则如下:

对于 GET 方法的数据,会将数据转换成 query string(encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)

对于 POST 方法且 header['content-type'] 为 application/json 的数据,会对数据进行 JSON 序列化

对于 POST 方法且 header['content-type'] 为 application/x-www-form-urlencoded 的数据,会将数据转换成 query string (encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Jun 29, 2018

组件

横向滚动tab
关键:.scroll{white-space: nowrap;}
关键:scroll直接子元素不能是flex

<style lang="less">
    .navigation {
        width: 100%;
        height: 62rpx;
    }
    .scroll {
        width: 100%;
        height: 62rpx;
        white-space: nowrap;
    }
    .item {
        display: inline-block;
        width: 124rpx;
        height: 62rpx;
        text-align: center;
        line-height: 62rpx;
    }
</style>

<template>
    <view class="navigation">
        <scroll-view scroll-x="true" class="scroll" scroll-with-animation="true">
            <repeat for="{{navigation}}" key="key" index="index" item="item">
                <view class="item">{{item.name}}</view>
            </repeat>
        </scroll-view>
    </view>
</template>

<script>
    import wepy from 'wepy'
    export default class Navigation extends wepy.component {
        data = {
            navigation: [{
                name: '全部'
            }, {
                name: '女装'
            }, {
                name: '男装'
            }, {
                name: '内衣'
            }, {
                name: '女婴'
            }, {
                name: '化妆品'
            }, {
                name: '全部'
            }, {
                name: '全部'
            }, {
                name: '全部'
            }, {
                name: '全部'
            }]
        }
    }
</script>

自定义swiper

<style lang="less">
    .carousel {
        width: 100%;
        height: 352rpx;
    }
    .swiper {
        width: 100%;
        height: 352rpx;
    }
    .slide-image {
        width: 632rpx;
        height: 352rpx;
        background-color: rgb(115, 192, 192);
        margin-left: 30rpx;
    }
    swiper-item {}
    .pre-image {
        background-color: rgb(192, 115, 188);
        transform: translate(20%, 0)
    }
    .next-image {
        background-color: rgb(192, 156, 115);
        transform: translate(-20%, 0)
    }
</style>

<template>
    <view class="carousel">
        <swiper previous-margin="30rpx" next-margin="30rpx" class="swiper" indicator-dots="true" autoplay="{{}}" interval="{{}}" duration="{{}}" current-item-id={{}} bindchange="changeItem">
            <repeat for="{{carousel}}" key="index" item="item">
                <swiper-item item-id="{{itemId}}">
                    <image mode="scaleToFill" src="{{}}" class="slide-image {{index===currentId-1 ? 'pre-image' : ''}} {{index===currentId+1 ? 'next-image' : ''}}" />
                </swiper-item>
            </repeat>
        </swiper>
    </view>
</template>

<script>
    import wepy from 'wepy'
    export default class Carousel extends wepy.component {
        data = {
            carousel: [1, 2, 3, 4, 5],
            itemId: 0,
            currentId: 0
        }
        methods = {
            changeItem(e) {
                console.log(e.detail.current)
                this.currentId = e.detail.current
            }
        }
    }
</script>

ca


滚动触底加载更多

<template>
  <view class="cost-effective">
    <scroll-view scroll-y class="cost-effective-scroll"
                 scroll-with-animation="true" @scrolltolower="loadMore">

    </scroll-view>
  </view>
</template>

清除input值

<style lang="less">
  
</style>

<template>
  <view class="search">
    <input placeholder="喵小吖" focus="{{true}}" adjust-position="{{false}}"
               bindinput="bindKeyInput" value="{{keyword}}"
               placeholder-class="input-placeholder" type="text" confirm-type="search"/>
    <view @tap="deleteSearchValue" class="delete"></view>
  </view>
</template>

<script>
  export default class Search extends wepy.page {
    config = {
      navigationBarTitleText: '搜索'
    }
    components = {}
    data = {
      keyword: '' // 搜索关键词,
    }
    computed = {}
    methods = {
      deleteSearchValue() {
        this.keyword = ''
        this.$apply()
      },
      bindKeyInput(e) {
        this.keyword = e.detail.value
        this.$apply()
      }
    }
    events = {}

    onLoad() {
    }
  }
</script>

tab切换,内容区域滑动视图

tab

<style lang="less">
  @import (reference) '../../style/color';
  @import '../../style/line';
  @import '../../style/text';

  @mainFont: 30rpx;
  @width: 702rpx;
  @widthL2: 620rpx;
  @height: 84rpx;

  @image: 60rpx;

  @cardWidth: 702rpx;
  @contentWidth: 622rpx;

  @mainFont: 30rpx;
  @detailFont: 28rpx;


  .container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: @wildSand;

    & > .tab-wrapper {
      z-index: 2;
      position: fixed;
      top: 0;
      left: 0;
      display: flex;
      align-items: center;
      justify-content: space-around;
      width: 100%;
      height: @height;
      background-color: @white;
      & > .tab {
        position: relative;
        font-size: @mainFont;
        color: @dustyGrayL1;
        transition: all 0.15s linear;
      }
      .tab:after {
        content: '';
        display: flex;
        position: absolute;
        left: 50%;
        transform: translate(-50%, 0);
        bottom: -12rpx;
        width: 0rpx;
        height: 6rpx;
        border-radius: 6rpx;
        background-color: @dodgerBlue;
        transition: all 0.15s linear;
      }
      .tab.active:after {
        width: 50rpx;
      }
      .tab.active {
        color: @dodgerBlue;
      }
    }

    .swiper {
      z-index: 1;
      height: 100vh;
      .header-blank {
        display: flex;
        width: 100%;
        height: 100rpx;
      }

      .swiper-item {
        height: 100vh;
        .scroll {
          width: 100%;
          height: 100vh;
          background-color: @wildSand;
          .main-wrapper {
            width: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            .card {
              display: flex;
              flex-direction: column;
              align-items: center;
              width: @cardWidth;
              margin-bottom: 30rpx;
              background-color: @white;
              border-radius: 10rpx;
              box-shadow: @boxShadowL2;
              & > .head,
              & > .main,
              & > .time-wrapper,
              & > .foot {
                display: flex;
                width: @contentWidth;
              }

              & > .head {
                align-items: center;
                position: relative;
                margin-top: 30rpx;
                & > .name {
                  font-size: @mainFont;
                  color: @mineShaft;
                  margin-right: 46rpx;
                }
                & > .phone {
                  font-size: @mainFont;
                  color: @mineShaft;
                }
                & > .air-logo {
                  position: absolute;
                  top: 0;
                  right: 0;
                }
              }
              & > .main {
                flex-direction: column;
                align-items: center;
                & > .top,
                & > .bottom {
                  display: flex;
                  width: @contentWidth;
                  margin-top: 20px;
                  & > image {
                    display: flex;
                    width: @image;
                    height: @image;
                    border-radius: 50%;
                    margin-right: 40rpx;
                  }
                  & > text {
                    font-size: @detailFont;
                    color: @mineShaft;
                    line-height: @detailFont*1.2;
                  }
                }
              }
              & > .time-wrapper {
                position: relative;
                justify-content: flex-end;
                align-items: center;
                margin-top: 54rpx;
                margin-bottom: 20rpx;
                & > .time {
                  position: absolute;
                  top: 0;
                  left: 0;
                  align-items: center;
                  color: @mineShaft;
                  font-size: @detailFont;
                }
                & > .expedited {
                  color: @pink;
                  font-size: 32rpx;
                }
                & > image {
                  display: flex;
                  width: 18rpx;
                  height: 30rpx;
                  margin-left: 16rpx;
                }
              }

              & > .foot {
                align-items: center;
                height: 100rpx;
                justify-content: space-between;
                border-top: 2rpx solid @galleryGray;
                & > .status {
                  color: @dodgerBlue;
                  font-size: 32rpx;
                }
                & > .air-evaluation {

                }
              }
            }
          }
        }
      }
    }
  }
</style>

<template>
  <view class="container">
    <view class="tab-wrapper">
      <text @tap="changeTab(0)" class="tab {{currentTab===0 ? 'active' : ''}}">全部</text>
      <text @tap="changeTab(1)" class="tab {{currentTab===1 ? 'active' : ''}}">待完成</text>
      <text @tap="changeTab(2)" class="tab {{currentTab===2 ? 'active' : ''}}">未评价</text>
      <text @tap="changeTab(3)" class="tab {{currentTab===3 ? 'active' : ''}}">已完成</text>
    </view>

    <swiper indicator-dots="{{false}}" autoplay="{{false}}" bindchange="changeSwiper"
            class="swiper" current="{{currentTab}}">
      <repeat for="{{tabList}}" key="key" item="item" index="index">
        <swiper-item class="swiper-item">
          <scroll-view scroll-y class="scroll"
                       scroll-with-animation="true" @scrolltolower="loadMore">
            <view class="main-wrapper">
              <view class="header-blank"></view>
              <repeat for="{{cardList}}" key="cardKey" item="cardItem" index="cardIndex">
                <view class="card">
                  <view class="head">
                    <text class="name">王力宏</text>
                    <text class="phone">15512345678</text>
                    <view class="air-logo">淘宝</view>
                  </view>
                  <view class="main">
                    <view class="top">
                      <image lazy-load="true" mode="scaleToFill" src="{{pickupAddressImage}}"/>
                      <text class="content">[取件地址] 石家庄职业技术学院西门菜鸟驿站</text>
                    </view>
                    <view class="bottom">
                      <image lazy-load="true" mode="scaleToFill" src="{{deliveryAddressImage}}"/>
                      <text class="content">[送件地址] 石家庄职业技术学院西门菜鸟驿站</text>
                    </view>
                  </view>
                  <view class="time-wrapper">
                    <text class="time">送件时间:9月3日 15:30~18:30</text>
                    <text class="expedited">加急</text>
                    <image lazy-load="true" mode="scaleToFill" src="{{expeditedImage}}"/>
                  </view>

                  <view class="foot">
                    <text class="status">已完成</text>
                    <text class="air-evaluation">评价</text>
                  </view>
                </view>
              </repeat>
            </view>
          </scroll-view>
        </swiper-item>
      </repeat>
    </swiper>
  </view>
</template>

<script>
  import wepy from 'wepy'
  import {connect} from 'wepy-redux'
  import commonMixin from '@/mixins/common'
  import {SUCCESS, FAIL} from '@/constant/request'

  @connect({}, {})
  export default class AllOrders extends wepy.page {
    config = {
      navigationBarTitleText: ''
    }
    components = {}
    mixins = [commonMixin]
    data = {
      weChatPaymentImage: '../../icon/delivery/weChatPayment.png',
      currentTab: 0,
      pickupAddressImage: '../../icon/delivery/pickupAddress.png',
      deliveryAddressImage: '../../icon/delivery/deliveryAddress.png',
      tabList: [
        {},
        {},
        {},
        {}
      ],
      cardList: [
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {}
      ]
    }
    computed = {}
    methods = {
      changeTab(tab) {
        this.currentTab = +tab
      },
      changeSwiper(e){
        this.currentTab=e.detail.current
      },
      loadMore(){

      }
    }
    events = {}

    async onLoad() {

    }

    onShow() {
    }

  }
</script>

通用滚动容器

<style lang="less">
  @import (reference) '../../style/color';
  @import '../../style/icon';

  @width: 702rpx;
  @widthL2: 444rpx;
  @image: 60rpx;

  @mainFont: 34rpx;
  @mainFontL2: 30rpx;
  @detailFont: 28rpx;
  @detailFontL2: 20rpx;

  .container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: @wildSand;
    color: @mineShaft;
    .release-order-scroll {
      z-index: 1;
      width: 100%;
      height: 100vh;
      background-color: @wildSand;
      .main-wrapper {
        width: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
      }
    }
  }
</style>

<template>
  <view class="container">
    <scroll-view scroll-y class="release-order-scroll"
                 scroll-with-animation="true" @scrolltolower="loadMore">
      <view class="main-wrapper">

      </view>

    </scroll-view>
  </view>
</template>

<script>
  import wepy from 'wepy'
  import {connect} from 'wepy-redux'
  import commonMixin from '@/mixins/common'
  import {SUCCESS, FAIL} from '@/constant/request'


  @connect({}, {})
  export default class Team extends wepy.page {
    config = {
      navigationBarTitleText: '我的团队'
    }
    components = {}
    mixins = [commonMixin]
    data = {
      pickupAddressImage: '../../icon/delivery/pickupAddress.png',
    }
    computed = {}
    methods = {}
    events = {}

    async onLoad() {

    }

    onShow() {
    }
  }
</script>

标签

jietu20181011-231528

cateCard.wpy

<style lang="less">
  @import (reference) '../../style/color';
  @import (reference) '../../style/size';

  @width:156rpx;
  @height:114rpx;

  .cate-card{
    overflow: hidden;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: @width;
    height: @height;
    border-radius: 6rpx;
    background-color: @bgColorL2;
    &>.cate-name{
      font-size: @mainSize;
      color: @mainColor;
    }
    &>.food-name{
      font-size: @detailSize;
      color: @regularColor;
    }
    &>.hot-label{
      position: absolute;
      top: 0rpx;
      right: -28rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100rpx;
      height: 40rpx;
      font-size: @mainSize;
      color: @white;
      transform: rotate(45deg);
      background-color: @dangerColor;
    }
  }
</style>
<template>
  <view class="cate-card">
    <text class="cate-name">{{info.name}}</text>
    <text class="food-name">{{info.food}}</text>
    <text wx:if="{{info.isHot}}" class="hot-label">HOT</text>
  </view>
</template>
<script lang="typescript" src="./cateCard.ts"></script>

color.less

@white: #fff;

/*阴影*/
@boxShadow: 0rpx 6rpx 6rpx 4rpx rgba(0, 0, 0, 0.05);
@boxShadowL2: 0rpx 4rpx 4rpx 6rpx rgba(0, 0, 0, 0.05);
@boxShadowTop: -6rpx 0rpx 6rpx 4rpx rgba(0, 0, 0, 0.05);
@boxShadowTopDark: -6rpx 0rpx 6rpx 4rpx rgba(0, 0, 0, 0.2);
@boxShadowBlue: 0rpx 0rpx 10rpx 8rpx rgba(68, 158, 255, 0.5);

/*主色 主要品牌颜色*/
@blue: #409EFF;
@yellow: #f4ea2a;

/*辅助色 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)*/
@successColor: #67C23A;
@warningColor: #E6A23C;
@dangerColor: #F56C6C;
@infoColor: #909399;

/*中性色 用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构*/

/*主要文字*/
@mainColor: #303133;

/*常规文字*/
@regularColor: #606266;

/*次要文字*/
@secondaryColor: #909399;

/*占位文字*/
@placeholderColor: #C0C4CC;

/*边框*/

/*一级边框*/
@borderL1: #DCDFE6;

/*二级边框*/
@borderL2: #E4E7ED;

/*三级边框*/
@borderL3: #EBEEF5;

/*四级边框*/
@borderL4: #F2F6FC;

/* 背景色 */
@bgColor: #F4F4F4;
@bgColorL2: #F5F6F8;

父子互动组件

父组件

<style lang="less">
  
</style>
<template>
  <view class="purchase-order">
    <tip :tipList="tipList" @tipSubmit.user="handleTipSubmit" class="tip-container"/>
  </view>
</template>

<script lang="typescript" src="./purchaseOrder.ts"></script>
import wepy from 'wepy'
import {connect} from 'wepy-redux'
import Content from '@/components/purchaseOrder/content'
import Tip from '@/components/common/tip'

@connect({
}, {
})

export default class PurchaseOrder extends wepy.page {
  config = {
    navigationBarTitleText: '填写订单',
    usingComponents: {
    }
  }


  components = {
    tip:Tip
  }

  mixins = []

  data = {
  }

  computed = {
  }


  methods = {
    handleTipSubmit(value,e){
      console.log('pa111-','su')
      console.log('value-',value)
    },
    toggleTip(){
      console.log('toggleTip')
      this.$invoke('tip', 'showTip', '');
    }
  }


  events = {
  }

  onLoad() {
  }
}

子组件

<style lang="less">
  @import (reference) '../../style/color';
  @import '../../style/size';

  @labelWidth:214rpx;
  @labelHeight:70rpx;

  @width:710rpx;

  .air-tip{
    position: fixed;
    left: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    background-color: @white;
    box-shadow: @boxShadowTop;
    padding-bottom:  50rpx;
    transition: all 0.2s linear;
    &>.title-wrapper{
      display: flex;
      align-items: center;
      justify-content: space-between;
      width: 100%;
      height: @regularHeight;
      border-bottom: 2rpx solid @borderL4;
      &>.label{
        display: flex;
        font-size: @mainSize;
        color: @regularColor;
      }
      &>.cancel{
        margin-left: @regularMargin;
      }
      &>.submit{
        margin-right: @regularMargin;
      }
    }

    &>.tip-wrapper-air{
      display: flex;
      flex-wrap: wrap;
      justify-content: space-around;
      width: 100%;
      padding-top: 50rpx;
      font-size: @mainSize;
      color: @mainColor;
      &>.tip-item{
        display: flex;
        align-items: center;
        justify-content: center;
        width:@labelWidth;
        height: @labelHeight;
        border: 2rpx solid @borderL4;
        border-radius: 6rpx;
        margin-bottom: @regularMargin;
      }
      &>.active{
        border: 2rpx solid @blue;
        color: @blue;
      }
    }

    &>.tip-other{
      display: flex;
      align-items: center;
      justify-content: center;
      width: @width;
      height: @labelHeight;
      border: 2rpx solid @borderL4;
      border-radius: 6rpx;
      font-size: @mainSize;
      color: @mainColor;
      &>.tip-label{
        display: flex;
        align-items: center;
      }
      &>.tip-input{
        width: 100rpx;
        font-size: @mainSize;
        color: @mainColor;
      }
    }
    &>.active{
      border: 2rpx solid @blue;
      color: @blue;
    }
  }
  .air-tip.hide{
    bottom: -50vh;
  }
</style>
<template>
  <view class="air-tip {{toggle ? '' : 'hide'}}">

    <view class="title-wrapper">
      <text class="label cancel" @tap="handleCancel">取消</text>
      <text class="label">小费</text>
      <text class="label submit" @tap="handleSubmit">确定</text>
    </view>

    <view class="tip-wrapper-air">

      <repeat for="{{tipList}}" key="key" index="index" item="item">
        <text wx:if="{{item.price!==0}}" class="tip-item">¥{{item.price}}</text>
        <text wx:if="{{item.price===0}}" class="tip-item">不加了</text>
      </repeat>

    </view>

    <view class="tip-other">
      <text class="tip-label">其他金额¥</text>
      <view class="tip-input">
        <input value="{{tipOther}}" bindinput="bindKeyInput" class=""/>
      </view>
    </view>
  </view>
</template>
<script lang="typescript" src="./tip.ts"></script>
import wepy from 'wepy'
import {connect} from 'wepy-redux'
import commonMixin from '@/mixins/common'

// 小费卡片
@connect({}, {})

export default class Tip extends wepy.component {

  components={

  }

  mixins = [commonMixin]

  props = {
    tipList:{
      type:Array,
      default:[
        {
          price:2
        }
      ]
    }
  }


  data = {
    tipOther:'',
    toggle:false
  }

  events = {}

  watch = {}

  methods = {
    bindKeyInput(e) {
      this.setData({
        inputValue: e.detail.value
      })
    },
    handleCancel(value,e){
      this.toggle=false
      console.log('pa-','ca')
      console.log('value-',value)
    },
    handleSubmit(value,e){
      this.$emit('tipSubmit')
      this.toggle=false
      console.log('pa-','su')
      console.log('value-',value)
    },
    showTip(){
      this.toggle=true
      console.log('this.toggle--',this.toggle)
    }
  }

}

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Jul 6, 2018

示例

多个动态class样式

<template>
 <image mode="scaleToFill" src=""
                 class="slide-image {{index===currentId-1 ? 'pre-image' : ''}} {{index===currentId+1 ? 'next-image' : ''}}"/>
</template>

input 输入框
input的父元素不可以是固定定位

<style lang="less">
@placeholderColor: #d9d9d9;
    .input-placeholder {
      font-size: 28rpx;
      color: @placeholderColor;
    }
  
</style>

<template>
      <input class="edit-name" placeholder="喵小吖" focus="{{true}}" adjust-position="{{false}}" placeholder-class="input-placeholder" />
  
</template>

<script>
 
</script>

左滑显示右侧隐藏按钮

<style lang="less">
  .test {
    width: 100%;
    & > .move-area {
      width: 200rpx;
      height: 50rpx;
      background-color: antiquewhite;
      & > .move-view {
        z-index: 5;
        width: 50rpx;
        height: 50rpx;
        background-color: aquamarine;
      }
      & > .delete {
        z-index: -1;
        position: absolute;
        right: 0;
        top: 0;
        width: 50rpx;
        height: 50rpx;
        background-color: blueviolet;
        opacity: 0;
        transition: all 0.2s linear;
      }
      .delete.active {
        z-index: 0;
        opacity: 1;
      }
    }

    & > .move-area-2 {
      width: 200rpx;
      height: 50rpx;
      background-color: antiquewhite;
      & > .move-view {
        z-index: 5;
        width: 250rpx;
        height: 50rpx;
        background-color: aquamarine;
      }
      & > .delete {
        z-index: -1;
        position: absolute;
        right: -50rpx;
        top: 0;
        width: 50rpx;
        height: 50rpx;
        background-color: blueviolet;
        opacity: 0;
        transition: all 0.2s linear;
      }
      .delete.active {
        z-index: 0;
        opacity: 1;
      }
    }
  }
</style>

<template>
  <view class="test">
    <view class="section__title">movable-view区域小于movable-area</view>
    <movable-area class="move-area">
      <movable-view inertia="true" direction="horizontal" friction="0.1" damping="20" bindchange="handleLeftmove"
                    animation="true" x="150rpx" y="" class="move-view">
      </movable-view>
      <view class="delete {{shouldShowDelete ? 'active' : ''}}"></view>
    </movable-area>

    <view class="section__title">movable-view区域大于movable-area</view>
    <movable-area class="move-area-2">
      <movable-view inertia="true" direction="horizontal" friction="0.1" damping="20" bindchange="handleLeftmoveBottom"
                    animation="true" x="" y="" class="move-view">
      </movable-view>
      <view class="delete {{shouldShowDeleteBottom ? 'active' : ''}}"></view>
    </movable-area>
  </view>
</template>

<script>
  import wepy from 'wepy'
  import {
    connect
  } from 'wepy-redux'

  @connect({}, {})
  export default class Test extends wepy.page {
    config = {
      navigationBarTitleText: 'test'
    }
    components = {}
    mixins = []
    data = {
      shouldShowDelete: false,
      shouldShowDeleteBottom: false
    }
    computed = {}
    methods = {
      handleLeftmove(e) {
        console.log('handleLeftmove---x--', e.detail.x)
        if (e.detail.x === 0) {
          this.shouldShowDelete = true
        } else {
          this.shouldShowDelete = false
        }
      },
      handleLeftmoveBottom(e) {
        console.log('handleLeftmove---x--', e.detail.x)
        if (e.detail.x === -25) {
          this.shouldShowDeleteBottom = true
        } else {
          this.shouldShowDeleteBottom = false
        }
      }
    }
    events = {}

    onLoad() {
    }
  }
</script>

wechatimg4
wechatimg5


懒加载

<image lazy-load="true" class="image" mode="scaleToFill" src="{{item.src}}" @tap="food({{index}},{{itemIndex}})"></image>

@WangShuXian6
Copy link
Owner Author

轮播图

<style lang="less">
  // 主轮播图,第一轮播图
  @bgColor: #F5F5F5;
  @boxShadow: 6rpx 8rpx 8rpx rgba(0, 0, 0, 0.16);
  @dotsBgColor: #DCDCDC;
  @dotActiveColor: #D94E4E;
  @defaultColor: rgb(115, 192, 192);
  .carousel {
    position: relative;
    width: 100%;
    height: 414rpx;
    background-color: @bgColor;
    padding-top: 36rpx;
  }

  .swiper {
    width: 100%;
    height: 352rpx;
  }

  .slide-image {
    width: 632rpx;
    height: 352rpx;
    transform: scale(0.95);
    background-color: @defaultColor;
    margin-left: 30rpx;
    border: none;
    border-radius: 8rpx;
    box-shadow: @boxShadow;
  }

  .pre-image {
    background-color: rgb(192, 115, 188);
    transform: translate(20%, 0) scale(0.9);
    border-radius: 8rpx;
  }

  .next-image {
    background-color: rgb(192, 156, 115);
    transform: translate(-20%, 0) scale(0.9);
    border-radius: 8rpx;
  }

  .dots {
    box-sizing: border-box;
    display: flex;
    position: absolute;
    top: 402rpx;
    left: 50%;
    transform: translate(-50%, 0);
    height: 24rpx;
    background-color: @dotsBgColor;
    border: none;
    border-radius: 24rpx;
  }

  .dot {
    display: inline-block;
    flex: 1;
    width: 10rpx;
    height: 10rpx;
    border: none;
    border-radius: 50%;
    margin-top: 7rpx;
    margin-left: 12rpx;
    background-color: #fff;
  }

  // .dot:first-child {}
  .dot:last-child {
    margin-right: 12rpx;
  }

  .active-dot {
    background-color: @dotActiveColor;
  }
</style>

<template>
  <view class="carousel">
    <swiper previous-margin="30rpx" next-margin="30rpx" class="swiper" indicator-dots="{{false}}" autoplay=""
            interval="" duration="" current-item-id="" bindchange="changeItem"
            indicator-active-color="#FE4777" indicator-color="#fff">
      <repeat for="{{carousel}}" key="index" item="item">
        <swiper-item item-id="{{itemId}}">
          <image mode="scaleToFill" src=""
                 class="slide-image {{index===currentId-1 ? 'pre-image' : ''}} {{index===currentId+1 ? 'next-image' : ''}}"/>
        </swiper-item>
      </repeat>
    </swiper>
    <view class='dots'>
      <repeat for="{{carousel}}" key="index" item="item">
        <view class="dot {{index===currentId ? 'active-dot' : ''}}"></view>
      </repeat>
    </view>
  </view>
</template>

<script>
  import wepy from 'wepy'

  export default class Carousel extends wepy.component {
    data = {
      carousel: [1, 2, 3, 4, 5],
      itemId: 0,
      currentId: 0
    }
    methods = {
      changeItem(e) {
        console.log(e.detail.current)
        this.currentId = e.detail.current
      }
    }
  }
</script>

@WangShuXian6
Copy link
Owner Author

事件

https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html
小程序不支持e.stopPropagation()用以阻止捕获或冒泡的进一步传播
小程序使用catch:tap="handleClickInner"代替e.stopPropagation()

<style lang="less">
  
</style>

<template>
  <view catch:tap="handleClickInner" class="detail-tao-password-card">
   
  </view>
</template>

<script>
  import wepy from 'wepy'
  import Button from '../common/button'

  export default class DetailTaoPasswordCard extends wepy.component {
    components = {
      button: Button
    }
    methods = {
      handleClickInner(e){
        console.log('事件-handleClickInner--',e)
        //e.stopPropagation()
      }
    }
  }
</script>

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Jul 13, 2018

wepy分包

截止2018-7-23 无分包:小程序限制大小为2MB。
有分包:主包限制2MB,单个分包限制2MB,整个小程序所有分包大小不超过 8M.
在src下建立分包目录
src/packageTest/pages/pTest.wpy
app.js配置的config字段为

config = {
      pages: [
        'pages/test'
      ],
      subPackages:[
        {
          root:'packageTest',
          pages:[
            'pages/pTest'
          ]
        }
      ],
      window: {
        backgroundTextStyle: 'light',
        navigationBarBackgroundColor: '#fff',
        navigationBarTitleText: 'WeChat',
        navigationBarTextStyle: 'black'
      }
    }

主包内点击按钮跳转到分包内的方法

navToPack(){
        wx.navigateTo({
          url:'../packageTest/pages/pTest' // 相对路径
          // url:'/packageTest/pages/pTest' // 绝对路径
        })
      }

@WangShuXian6
Copy link
Owner Author

小程序使用节流函数

methods = {
  handleLeftmove: debounce((key, e) => {
    
  }, 500, false)

@WangShuXian6
Copy link
Owner Author

tabBar

app.wpy
注意:pages数组的第一项必须是tabBar的list数组的一员

config = {
      pages: [
        'pages/index',
        'pages/get',
        'pages/tab',
        'pages/pageA',
        'pages/pageB'

      ],
      window: {
        backgroundTextStyle: 'light',
        navigationBarBackgroundColor: '#fff',
        navigationBarTitleText: 'WeChat',
        navigationBarTextStyle: 'black'
      },
      tabBar: {
        color: '#000',
        selectedColor: '#ff4777',
        backgroundColor: '#fff',
        borderStyle: 'white',
        position: 'bottom',
        list: [
          {
            pagePath: 'pages/index',
            text: '第0个',
            iconPath: './icon/a.jpg',
            selectedIconPath: './icon/s.jpg'
          },
          {
            pagePath: 'pages/pageA',
            text: '第一个',
            iconPath: './icon/a.jpg',
            selectedIconPath: './icon/s.jpg'
          },
          {
            pagePath: 'pages/pageB',
            text: '第二个',
            iconPath: './icon/b.jpg',
            selectedIconPath: './icon/s.jpg'
          }
        ]
      }
    }

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Oct 21, 2018

watch 监听器

import wepy from 'wepy'
import {connect} from 'wepy-redux'

@connect({}, {})

export default class ShippingAddress extends wepy.component {

  components = {}

  props = {
    info: {
      type: Object,
      default: {
        distance: '',
        title: '',
        detail: '',
        name: '',
        phone: ''
      }
    }
  }

  data = {
    hasAddress: false
  }

  events = {}

  watch = {
    info(newValue, oldValue) {
      if (newValue.title) {
        this.hasAddress = true
      } else {
        this.hasAddress = false
      }
      this.$apply()
    }
  }

  methods = {
    toggleAddress(toggleAddress) {
      this.toggleAddress = toggleAddress
    }
  }
}

@WangShuXian6
Copy link
Owner Author

wepy 重的页面跳转

// 跳转到指定页面,可以反回
  goPageCanBack = (url, params = {}) => {
    if (!url) {
      wx.navigateTo({
        url: '/pages/error'
      })
    } else if (typeof url !== 'string') {
      console.warn('页面地址应为字符串格式')
      return false
    } else if (params && !isEmptyObject(params)) {
      const paramsString = buildParamsString(params)
      wx.navigateTo({
        url: `${url}?${paramsString}`
      })
    } else if (!params || isEmptyObject(params)) {
      wx.navigateTo({
        url: url
      })
    }
  }

  // 跳转到指定页面,不可以反回
  goPage = (url, params = {}) => {
    if (!url) {
      wx.redirectTo({
        url: '/pages/error'
      })
    } else if (typeof url !== 'string') {
      console.warn('页面地址应为字符串格式')
      return false
    } else if (params && !isEmptyObject(params)) {
      const paramsString = buildParamsString(params)
      wx.redirectTo({
        url: `${url}?${paramsString}`
      })
    } else if (!params || isEmptyObject(params)) {
      wx.redirectTo({
        url: url
      })
    }
  }
this.goPage('/packageRider/pages/rider', {source: PURCHASE})
this.goPageCanBack('error', {source: PURCHASE})

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Oct 28, 2018

父子组件通信

父组件调用子组件方法


在子组件内读取自身属性值 props

this.props // 无有效值

@WangShuXian6
Copy link
Owner Author

WangShuXian6 commented Nov 3, 2018

页面内发起微信分享

注意:分享路径为
path: 'pages/index?member_id='+this.memberId
不同于原生小程序路径

<view class="share-wrapper">
      <text class="air-long-button blue invite-button">立即邀请</text>
      <button open-type="share" class="share"></button>
</view>
.air-long-button{
  display: flex;
  align-items: center;
  justify-content: center;
  width: @widthL3;
  height: @height;
  border-radius: @height;
  background-color: @white;
  box-shadow: @boxShadow;
  font-size: @mainSize;
  line-height: normal;
  color: @mainColor;
  border: 2rpx solid @borderL1;
}

.air-long-button.blue{
  background-color: @blue;
  border: 2rpx solid @blue;
}

&>.share-wrapper{
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      &>.share{
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        opacity: 0;
      }
    }
methods = {
    /**
     * 用户点击右上角或页面分享按钮分享
     */
    onShareAppMessage: function () {
      return {
        title: this.title,
        path: 'pages/index?member_id='+this.memberId
      }
    }
  }

@WangShuXian6
Copy link
Owner Author

wepy 小程序 使用富文本

wepy-html

https://github.com/beiliao-web-frontend/wepy-html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant