整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

html5迁移到微信小程序的 方法 亲测可用

图网习惯于在做小程序之前先做成html5+vuejs的形式,因为html5切图是我们比较熟悉的方式,而且有专业的工具 以及浏览器调试也会更加的方便 灵活,效率高,而且html5的方式可以方便预览看效果,方便调整,当html5页面做好确认没问题以后 再转成小程序或者官方出品wepy的方式,这个时候就需要找到html5和小程序之间的微妙不同,需要做以下调整,亲测可用。

css需要调整的

把css中的px改为rpx,可以借助工具批量替换,如果使用的工具是 vscode 可以用插件 px to rpx,如果是hbuilder可以执行批量替换。

html需要调整的

  1. p 改为 view
  2. span、i 改为 label
  3. @click 改为 @tap
  4. img 改为 image
  5. a href 改
  6. :style=”” 改为 style=”{{}}”

js需要调整的

this.$router.push({
path: ‘/course-detail’,
query: {
caseCode: ‘123’
}
})

挑战30天在头条写日记#

WePY (发音: /'wepi/)是一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。框架的细节优化,Promise,Async Functions 的引入都是为了能让开发小程序项目变得更加简单,高效。




同时 WePY 也是一款成长中的框架,大量吸收借鉴了一些优化前端工具以及框架的设计理念和思想。如果 WePY 有不足地方,或者你有更好的想法,欢迎提交 ISSUE 或者 PR。

特性:

  • 类 Vue 开发风格
  • 支持自定义组件开发
  • 支持引入 NPM 包
  • 支持 Promise
  • 支持 ES2015+ 特性,如 Async Functions
  • 支持多种编译器,Less/Sass/Stylus/PostCSS、Babel/Typescript、Pug
  • 支持多种插件处理,文件压缩,图片压缩,内容替换等
  • 支持 Sourcemap,ESLint 等
  • 小程序细节优化,如请求列队,事件优化等

Demo

<style lang="less">
@color: #4D926F;
  .num {
  color: @color;
  }
</style>
<template>
  <div class="container">
    <div class="num" @tap="num++">
      {{num}}
    </div>
    <custom-component></custom-component>
    <vendor-component></vendor-component>
    <div>{{text}}</div>
    <input v-model="text"/>
  </div>
</template>
<config>
{
  usingComponents: {
    customComponent: '@/components/customComponent',
    vendorComponent: 'module:vendorComponent'
  }
}
</config>

<script>
  import wepy from '@wepy/core';

  wepy.page({
    data: {
      num: 0,
      text: 'Hello World',
    },
  });
</script>

安装使用

安装(更新) wepy 命令行工具。

npm install @wepy/cli@next -g

生成开发示例

wepy init standard myproject

安装依赖

cd myproject
npm install

开发实时编译

wepy build --watch

开发者工具导入项目

使用微信开发者工具新建项目,本地开发选择项目根目录,会自动导入项目配置。

WePY 实例

宿主环境


我们称微信客户端给小程序所提供的环境为宿主环境。小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能。 更多小程序原理的相关知识可参考小程序官方文档。

程序与页面

原生小程序中,每个页面拥有独自的一个页面实例 Page,整个小程序只有一个 App 实例,是全部页面共享的。

同样的,在 WePY 的环境当中,每个 WePY 页面拥有独自的 WepyPage 实例。小程序也会有 WepyApp 实例。它们并非是继承自原生的 Page 和 App。WePY 提供 wepy.appwepy.pagewepy.component 等入口 方法注册程序、页面、以及组件。注册后在组件的生命周期事件(onLaunch/onLoad/created)里,会自动创建相对应的 WePY 实例。

入口


注册 App

  1. 在指定位置新建 app.wpy,默认位置:src/app.wpy,具体配置可参考 编译器配置文件
  2. <script> 块内使用 wepy.app 方法注册
<!-- app.wpy -->

<script>
import wepy from '@wepy/core'

wepy.app({
  // 选项
})
</script>

使用入口方法注册 App 时,可以传入一个参数对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。

注册页面

  1. app.wpy<config> 代码块中注册页面信息
<!-- app.wpy -->

<config>
{
  "pages": [
    "pages/example"
  ]
}
</config>
  1. 新建 pages/example.wpy 文件
  2. <script> 块内添加 Page 注册方法
<!-- pages/example.wpy -->

<script>
import wepy from '@wepy/core'

wepy.page({
  // 选项
})
</script>

注册 Page 时,可以传入一个参数对象。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。

WePY 2.0 中,Page 同样是使用小程序原生的 Component 方法进行注册的。

注册组件

  1. 新建 components/comA.wpy 文件
  2. <script> 块内添加 component 实例
<!-- components/comA.wpy -->

<script>
import wepy from '@wepy/core'

wepy.component({
  // 选项
})
</script>
  1. 在需要引用组件的页面配置中添加组件信息,如需要在 pages/example.wpy 页面中新增 comA 组件,则在 pages/example.wpy<config> 块中添加如下信息:
<!-- pages/example.wpy -->

<config>
{
  "usingComponents": {
    "comA": "components/comA"
  }
}
</config>

与 WePY 1 或者 Vue 不同的是,组件的引用方式保留了原生的 usingComponents 方式。不可以使用 import 的方式导入。

数据与方法


使用 wepy.page 或者 wepy.component 注册页面或者组件时,它将 data 对象中的所有的属性加入到 wepy 的 响应式系统 中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

wepy.page({
  data: {
    a: 1
  },
  plus: function () {
    // 点击 “+“ 按钮式触发
    this.a++
  }
})

当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时 data 中存在的属性才是响应式的。也就是说如果你添加一个新的属性,比如:

wepy.page({
  data: {
    a: 1
  },
  plus: function () {
    // 点击 “+“ 按钮式触发
    this.a++
  },
  sayHi: function () {
    this.b = 'hi'
  }
})

那么对 b 的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:

wepy.page({
  data: {
    newTodoText: '',
    visitCount: 0,
    hideCompletedTodos: false,
    todos: [],
    error: null
  }
})

生命周期回调函数

WePY 单文件组件

WePY 单文件组件主要由 <script><template><style><config> 四部分组成(也包括小程序 <wxs> 标签)。

App 生命周期

wepy.app 注册 App 是直接调用原生 App 方法进行 App 注册,生命周期与原生一致。可参见官方文档 App

页面生命周期

wepy.page 本质上也是调用原生方法 Component 注册页面,因此它包含了 Component 的完整生命周期。同时,为了兼容对原有 Page 的使用习惯,也保留了所有 Page 特有的生命周期事件。

通过 Page({}) 注册页面

通过 wepy.page({}) 注册页面

说明

onLoad

onLoad

参看官方文档 Page

onShow

onShow

同上

onReady

onReady

同上

onHide

onHide

同上

onUnload

onUnload

同上

onPullDownRefresh

onPullDownRefresh

同上

onReachBottom

onReachBottom

同上

onShareAppMessage

onShareAppMessage

同上

onPageScroll

onPageScroll

同上

onResize

onResize

同上

onTabItemTap

onTabItemTap

同上

onAddToFavorites

onAddToFavorites

同上

-

created

参看官方文档 Component

-

attached

同上

-

ready

同上

-

moved

同上

-

detached

同上

-

error

同上

组件生命周期

wepy component 实例生命周期与原生小程序的 组件生命周期 一致,在 wepy component 实例中,您可以使用如下生命周期钩子:

wepy.component 注册组件除了原生的 Component 生命周期外,还定义了某些其它生命周期。

通过 Component({}) 注册页面

通过 wepy.component({}) 注册页面

说明

-

beforeCreate

本质上与wepy.created 一样都是在 Component.created 阶段触发,但 wepy.beforeCreate 在 Component.created 刚进入时触发,然后进行 WePY 的 data, props, methods 等等初始化,完成后再触发 wepy.created

created

created

参看官方文档 Component

attached

attached

同上

ready

ready

同上

moved

moved

同上

detached

detached

同上

error

error

同上

生命周期函数补充与修改

不排除一些情况,小程序进行版本库升级后,添加或者删除了新的生命周期函数,而且 WePY 并没有及时的进行更新,而且导致无法使用最新的生命周期函数。在这种情况下,开发者通过参数自行添加最新的生命周期函数。使用方法如下:

wepy.app({ ... }, {
  lifecycle: {
    // 定义要添加生命周期到 app 或者 page 或者 component
    // 值类型为:String 或者 Array 或者 Function
    // 值为需要添加的生命周期一个或者多个函数名,或者返回生命周期的函数数组的方法
    app: 'onSomeTime', // 给 App 添加一个 `onSomeTime` 生命周期函数
    page: ['onTime1', 'onTime2'], // 给 Page 添加两个生命周期函数
    component: function (lifecycles) {  // 删除 Component 最后一个生命周期函数
      lifecycles.pop();
      retrun lifecycles;
    }
  }
})

生命周期图示

下图展示了 页面/组件 实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

模板语法

WePY 继承了 WXML 的基本模板语法,并支持大部分 Vue 模板语法。

WXML(WeiXin Markup Language)是框架设计的一套标签语言,用来描述小程序页面的结构

同时,WePY 允许你使用大部分 HTML 模板标签,经编译器编译后,会将模板标签的转换成标准的 WXML 模板语法。

模板标签


转换流程

HTML 模板标签映射表

标签

转换后

select

picker

datalist

picker

img

image

source

audio

video

video

track

video

a

navigator

span

label

其它

view

数据绑定


以下案例均使用 HTML 模板标签作为参考

文本

数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:

<div>hello, {{ name }}</div>

Mustache 标签将会被替代为对应数据对象上 name 属性的值。无论何时,绑定的数据对象上 name 属性发生了改变,插值处的内容都会更新。

组件属性

  • 使用 v-bind 指令
<div v-bind:id="id"></div>

此时不能使用 Mustache 语法

  • 使用 原生小程序 的方式
<div id="{{ id }}"></div>

此时必须使用 Mustache 语法

控制属性

  • 使用 v-if 指令
<div v-if="condition"></div>

此时不能使用 Mustache 语法

  • 使用 原生小程序 的方式
<div wx:if="{{ condition }}"></div>

此时必须使用 Mustache 语法

事件

两种方式均不能使用 Mustache 语法

  • 使用 v-on 指令
<div v-on:tap="tapHandler"></div>

<!-- or -->
<div @tap="tapHandler"></div>
  • 使用 原生小程序 的方式
<div bindtap="tapHandler"></div>

运算

可以在 {{}} 内进行简单的运算,目前支持原生小程序的所有运算方式,如下:

三元运算

{{ ok ? 'YES' : 'NO' }}

算数运算

{{ a + b }}

逻辑判断

{{ length > 5 }}

字符串运算

{{ "hello" + name }}

数据路径运算

{{ object.key }}
{{ array[0] }}

组合

也可以在 Mustache 内直接进行组合,构成新的对象或者数组,详情请阅读 小程序官方文档

条件渲染

WePY 推荐使用 v-showv-if 控制条件渲染


  • wx:if
// example 01
<div wx:if="{{ condition }}"></div>

// example 02
<div wx:if="{{ condition2 }}"></div>
<div wx:else></div>

// example 03
<div wx:if="{{ condition3 }}"></div>
<div wx:elif="{{ condition4 }}"></div>
<div wx:else></div>
  • hidden
<div hidden="{{ condition }}"></div>

Vue 绑定语法


  • v-if
// example 01
<div v-if="condition"></div>

// example 02
<div v-if="condition2"></div>
<div v-else></div>

// example 03
<div v-if="condition3"></div>
<div v-else-if="condition4"></div>
<div v-else></div>

编译后:

// example 01
<view wx:if="{{ condition }}"></view>

// example 02
<view wx:if="{{ condition2 }}"></view>
<view wx:else></view>

// example 03
<view wx:if="{{ condition3 }}"></view>
<view wx:elif="{{ condition4 }}"></view>
<view wx:else></view>
  • v-show
<div v-show="condition"></div>

编译后:

<view hidden="{{ !condition }}"></view>

列表渲染

WePY 2 推荐使用 Vue v-for 指令进行列表渲染


编译前:

// example 01
<div v-for="item in array">{{index}}: {{item.message}}</div>

// example 02
<div v-for="(item, idx) in array">
  {{idx}}: {{itemName.message}}
</div>

编译后:

// example 01
<view wx:for="{{array}}">{{index}}: {{item.message}}</view>

// example 02
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
</view>

事件处理

未特殊提及的信息可优先参考 vue官方文档

原理

小程序原生的事件系统 使用bindcatch 等关键字进行事件监听。 而在 WePY 中,事件沿用了 Vue 的风格,使用 v-on 或者是 @ 操作符进行事件监听。同时 WePY 中会有一个统一的事件分发器接管原生事件。大致如下图:

WePY 在编译过程中,会找到所有监听事件,并为其分配事件 ID。同时将事件代码(可以是一个方法,也可以是一个简单的代码片段)注入至 JS 代码中。 然后当事件分发器接收到原生事件时,会通过事件 ID,分发到相应的事件逻辑当中。

这样做的好处主要是:

  1. 可控性更强。用户可利用相关钩子函数从而处理全局的用户事件。(典型场景:为页面全部按钮统一增加一个点击上报功能)
  2. 灵活度更高。相对于原生只能使用函数名的方式来说,还可使用简单代码片段。(典型场景:@tap="num++")

事件监听

WePY 不仅可以支持到响应事件监听,也可以支持到像 Web 原生,或者 Vue 的那种,使用简单代码片段的监听方式,示例如下:

<template>
  <!-- 使用代码片段响应事件 -->
  <button @tap="num =+ 1">Counter - {{num}}</button> 

  <!-- 类原生方式,使用事件函数响应事件 -->
  <button @tap="handler">Handle my event</button>

  <!-- 类Vue方式,原生不支持携带参数 -->
  <button @tap="handlerWithArgs(1, 2)">Handle my event with arguments</button>
</template>
<script>
import wepy from '@wepy/core';

wepy.page({
  data: {
    num: 0,
  },
  methods: {
    handler() {
      // do something
    },
    handlerWithArgs(a, b) {
      console.log(a, b);
    }
  }
})
</script>

注: 原生小程序中使用 <div data-hi="1"></div> 的方式传递参数,然后使用 event.currentTarget.dataset.hi 的方式获取参数。 在 WePY 中请尽量使用携带参数响应事件去完成参数的传递与获取。WePY 会在编译时为你绑定 data-xxx 并且在事件分发器中贴心的为你处理好参数的。

特殊参数支持

小程序原生事件会传递一个 event 参数。而 WePY 的事件分发器在处理事件时会有一个 $event 参数。 $event 参数是对 event 进行了一层包装,目地是为了无侵入地对齐 Web Event 标准属性。而其中 $event.$wx === event。 因此,WePY 中响应事件获得的事件参数均是指 $event。如果想拿到原生事件参数,请使用 $event.$wx

当使用类原生方式,使用响应事件方法名进行事件监听时,响应事件会接收到一个 $event 参数。 当使用带参函数进行事件监听时,默认不会拿到事件的 $event。 该行为与 Vue 行为是一致的。此时若想拿到 $event 需要指定 $event 参数。

示例:

<!-- click 会接收到一个 $event 参数 -->
<button @tap="click">Click</button>

<!-- click 会接收一个为 1 的参数 -->
<button @tap="click(1)">Click</button>

<!-- click 会接受两个参数: 1, $event -->
<button @tap="click(1, $event)"

事件修饰符

小程序的事件系统中,可以使用 bind, catch, capture-bind, capture-catch 等来处理事件的冒泡与捕获,其中区别请参考官方文档。

在 WePY 中,使用修饰符来完成这一动作,相对来说更加灵活与易读。示例:

<!-- 等同于 bind:tap -->
<div @tap="myclick"></div>

<!-- 等同于 catch:tap -->
<div @tap.stop="myclickStop"></div>

<!-- 等同于 capture-bind:tap -->
<div @tap.capture="myclickCapture"></div>

<!-- 等同于 capture-catch:tap -->
<div @tap.stop.capture="myclickCaptureStop"></div>

<!-- 等同于 capture-catch:tap 修饰符中无先后关系 -->
<div @tap.capture.stop="myClickCaptureStopWithParams"></div>

stop 修饰符

作用:标识取消事件冒泡,对应原生事件中的 catch

在下边这个例子中,点击 inner view 会先后调用 handleTap3handleTap2 (因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发 handleTap2,点击 outer view 会触发 handleTap1

<div id="outer" @tap="handleTap1">
  outer view
  <div id="middle" @tap.stop="handleTap2">
    middle view
    <div id="inner" @tap="handleTap3">
      inner view
    </div>
  </div>
</div>

capture 修饰符

作用:标识事件捕获阶段,对应原生事件中的 capture-xxxx

捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用 .capture.capture.catch 修饰符,后者将中断捕获阶段和取消冒泡阶段。

在下面的代码中,点击 inner view 会先后调用 handleTap2handleTap4handleTap3handleTap1

<div id="outer" @touchstart="handleTap1" @touchstart.capture="handleTap2">
  outer view
  <div id="inner" @touchstart="handleTap3" @touchstart.capture="handleTap4">
    inner view
  </div>
</div>

如果将上面代码中的第一个 capture 后面加一个 catch 修饰符,将只触发 handleTap2

<div id="outer" @touchstart="handleTap1" @touchstart.capture.catch="handleTap2">
  outer view
  <div id="inner" @touchstart="handleTap3" @touchstart.capture="handleTap4">
    inner view
  </div>
</div>

wxs 修饰符


作用:标识使用WXS函数响应事件

小程序基础库 2.4.4 开始支持,低版本需做兼容处理

wxs 响应事件的背景及实现方案,参考 小程序官方文档

<wxs module="test" src="./test.wxs"></wxs>
<div change:prop="{{test.propObserver}}" :prop="propValue" @touchmove.wxs="test.touchmove" class="movable"></div>

上面的 change:prop(属性前面带 change: 前缀)是在 prop 属性被设置的时候触发 WXS 函数,值必须用{{}}括起来。在 propValue 值发生变化之后会触发。

当 prop 属性的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次 WXS 中 propObserver 的函数。

WXS 文件 test.wxs 里面定义并导出事件处理函数和属性改变触发的函数:

module.exports = {
  touchmove: function(event, instance) {
    console.log('log event', JSON.stringify(event))
  },
  propObserver: function(newValue, oldValue, ownerInstance, instance) {
    console.log('prop observer', newValue, oldValue)
  }
}

mut 修饰符


作用:标识使用互斥事件

小程序基础库 2.8.2 开始支持,低版本需做兼容处理 该修饰符 WePY 暂不支持

表单输入绑定

v-model 本质上是语法糖,它会根据控件类型自动选取正确的方法来更新元素

  • input 和 textarea 元素使用 value 作为 prop ,并通过 input 事件触发 v-model 属性值的更新。
  • picker,checkbox-group,radio-group 元素将使用 value 作为 prop ,并通过 change 事件触发 v-model 属性值的更新。
  • switch 元素将使用 checked 作为 prop ,并通过 change 事件触发 v-model 属性值的更新。

基础用法

输入框 input

<input v-model="inputmodel" />
<script>
import wepy from '@wepy/core';

wepy.page({
    data: {
        inputmodel: ''
    }
})
</script>

多行文本 textarea

<textarea v-model="inputmodel" />
<script>
import wepy from '@wepy/core';

wepy.page({
    data: {
        inputmodel: ''
    }
})
</script>

picker

<picker v-model="pickermodel" range="{{array}}">
    <div class="picker">
        当前选择:{{pickermodel}}
    </div>
</picker>
<script>
import wepy from '@wepy/core';

wepy.page({
    data: {
        array: ['美国', '中国', '巴西', '日本'],
        pickermodel: ''
    }
})
</script>

switch

<switch v-model="switchmodel" />
<script>
import wepy from '@wepy/core';

wepy.page({
    data: {
        switchmodel: ''
    }
})
</script>

radio

小程序的radio目前不支持 change 事件, 请使用radio-group标签

<radio-group v-model="radiomodel">
    <label>
        <div>
            <radio value="美国"></radio>
        </div>
    </label>
</radio-group>
<script>
import wepy from '@wepy/core';

wepy.page({
    data: {
        radiomodel: ''
    }
})
</script>

checkbox

小程序的checkbox目前不支持 change 事件, 请使用checkbox-group标签

<checkbox-group v-model="checkboxmodel">
    <label>
        <div>
            <checkbox value="美国"></checkbox>
        </div>
    </label>
</checkbox-group>
<script>
import wepy from '@wepy/core';

wepy.page({
    data: {
        checkboxmodel: ''
    }
})
</script>

项目地址:

https://github.com/Tencent/wepy

ublime下代码高亮

文件后缀为.wpy,可共用vue高亮,但需要手动安装。

  1. 打开Sublime->Preferences->Browse Packages..进入用户包文件夹。

  2. 在此文件夹下打开cmd,运行

    git clone git@github.com:vuejs/vue-syntax-highlight.git,无GIT用户可以直接下载zip包解压至当前文件夹。

  3. 关闭.wpy文件重新打开即可高亮。

WebStorm下代码高亮

打开Preferences,搜索Plugins,搜索Vue.js插件并安装。

打开Preferences,搜索File Types,找到Vue.js Template,在Registered Patterns添加*.wpy,即可高亮。

Atom下代码高亮

在Atom里先安装vue的语法高亮 - language-vue,如果装过了就忽略这一步。

打开Atom -> Config菜单。在core键下添加:

customFileTypes:

"text.html.vue": [

"wpy"

]

Vscode下代码高亮

在vscode里先安装vue的语法高亮 - language-vue,如果装过了就忽略这一步。

在项目根目录下,建立.vscode目录

在.vscode里建立settings.json文件,内容如下:

{

"git.ignoreLimitWarning": true,

"files.associations": {

"*.wxml": "html",

"*.wxss": "css",

"*.wpy": "vue"

}

}