Vue手动快速移植小程序总结

Posted 嗡汤圆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue手动快速移植小程序总结相关的知识,希望对你有一定的参考价值。

1、前言

1.1 关于技术选型

这大半年精力从后端转移到前端开发,一下要同时弄ios + 安卓 + 小程序的研发,很自然选择了混合App的方案,这样可以在最小学习成本下快速实现功能,并且在遇到一些可能的风险的时候,不至于因为不懂OC, Swift或者android相关的东西导致无法处理。

前端技术框架早期Angular和Vue都接触过,Angular从1,到2,6都试过,技术架构变得太大,听说现在都到9了,以前的6又不兼容了,上生产的系统,还是不要依赖这种变化太大的技术了,不然后期重构和维护成本很大。反观vue,从早期1到现在的2, 和后来马上要出的3 语法变化都不大,况且,我还要兼顾小程序研发,而小程序的结构和vue很像,因此web部分我选用了Vue作为技术选型。

顺带推广一下自家小程序哈~~~

1.2 关于移植小程序需求

最近微信官方推Kbone了,打出的口号就是vue和小程序同时支持,本想多研究研究的,但是由于目前的项目的一些限制,我们并没有完全依赖Vue的所有特性和组件,中间有一些换为我们自己的实现方式,因此Kbone并不一定能很好支持这种方式的项目,就不去研究了。况且手动移植会更加可靠些,毕竟是两个独立项目,调试起来会更方便一些,而且小程序和App本身从界面设计和应用需求上就会有些不同。

以下举个简单例子:

App的界面:

小程序的界面:

这里的主要区别的原因在于Tab的支持, Vue里的Tab在任何地方都可以把Tab内容作为独立页面来看待,有完整的生命周期,但是小程序里,除非是App的根页面可以配置正儿八经的Tab外,其它子模块都只能靠自己绘制和Component实现,而小程序的Component的生命周期(lifetimes)仅支持attach和detach两种, 以及(pageLifetimes)仅支持show和hide两种,因此,若采用直接移植的话,对于页面生命周期的相关逻辑,改动较大。因此在小程序内若需要保持两个页面(首页、订单页)的逻辑独立性,我们在小程序内把订单入口作为按钮引入。

注意:这里这么改变的原因,仅仅在于我们是App先入为主,小程序是从App的逻辑迁移过来才这么设计的。如果一开始就是小程序先研发,则完全可以通过Component方式实现Tab的切换逻辑,并且Vue同样支持这样的结构。

 

由于是从后端Java研发转到的前端,不管是Vue还是小程序都是半路出家,因此里边可能有很多错误,欢迎指出。

 

2. 从Vue迁移到小程序的一些总结

由于我之前没有真正参与过完整的小程序开发,这也是我第一次自己上手迁移了一个模块后进行的总结,粗浅的了解了一些小程序的特性。因此可能小程序还有一些更好的特性我没有涉及到的,各位就根据自己的实际情况看看吧。

2.1 组件封装

这个在Vue和小程序里都有同样的需求,App本身包括了很多功能模块,每个模块都是独立的Vue项目,可能都是不同的人负责研发的,为了维持App的UI设计和交互逻辑一致,我们把UI元素(如:按钮,对话框,Toast,表单元素等)独立封装为一个项目(类似一个Vant等独立的UI库,但是比它们简单,轻量地多)。组件封装我的看法如下:

1)逻辑一致

比如一个按钮的封装,在逻辑设计上App和小程序保持一致:按钮的类型定义,是否可用定义,loading状态定义,点击事件定义等等……,保持一致的好处在于,具体应用在各个页面中时,按钮相关的所有逻辑输入、输出都是一样的。

2)具体实现根据App和小程序体现区别

  1. Vue的封装

可参考的例子很多,这里主要参考这个Vue组件封装(以封装一个button组件为例)。 

在使用的时候就是如

import XXXButton from "shared-components/XXXButton"

// 注册(可全局可局部)
Vue.use(XXXButton);


<template>
   <XXXButton @click="onButtonClick" :type="'primary'" :loading="loadingState">xxxxx</XXXButton>
</template>

// ..........

在Vue里 @代表事件输出, :代表参数输入,对应到组件内是 $emit() 输出事件, props 传入参数即可。

 

   2.小程序的封装

小程序的组件封装简单的多,在小程序的开发工具内,右键单击"新建Component"就行了~~~ 自动吧wxss, js, json, wxml四个文件都创建好了,按照正常的研发逻辑开发即可。

这里js文件承载逻辑,properties和Vue的props对应。事件输出则使用 this.triggerEvent("eventName",  eventDetail) 。使用的时候,在页面的.json文件中的usingComponents注册,然后正常使用即可。和Vue的例子类比则伪代码如下


// XXXPage.json

    "usingComponents": 
        "XXXButton": "../../../components/XXXButton/XXXButton"
    


// XXXPage.wxml

<view>
   <XXXButton bindclick="onButtonClick" type="'primary'" loading="loadingState">xxxxx</XXXButton>
</view>

// XXXPage.js
//....
data: 
  loadingState: false
,
methods: 
  onButtonClick(e)
    // e.detail是输出参数
    console.log("button clicked",e.detail);
  

2.2 页面

我所涉及的页面较简单,几乎是无脑操作,步骤大致如下:

1)元素

App的<template> , <div> …… 元素统统换成 <view> 

输入输出替换:

  • v-for  换成 wx:for(小程序的循环体内默认item, index) 
  • v-if 换成 wx:if
  • v-show 换成 wx:hidden(这里bool变量反一下)
  • 事件输出 @click 换成 bindtap, @click.stop 换成 catchtap ……
  • 参数输入 :xxxx 换成. xxxx (去掉冒号)

2) 样式

App直接CSS拷贝到wxss都行,尺寸换算如下:

这里仅对于我自己的实际项目前提: App统一采用rem单位,rootFont = 37.5像素, 设计人员使用2倍图。

假设一个元素在2倍图预览时候的长为 75px,宽度为 37.5px。 则对应app的长为 1rem, 宽为 0.5rem。对应小程序的长为75rpx,宽为 37.5rpx。

同理换算即可。

3)逻辑

A.数据方面

// 无需刷新页面的数据变化
// -> Vue
this.xxx = yyy;
// -> 小程序
this.data.xxx = yyy;


// 需要页面刷新的数据变化
// -> Vue
this.xxx = yyy;
// -> 小程序
this.setData(
  xxx: yyy
);


// **** 注意,如果数据操作之间有先后要求的,setData应该在回调函数进行下一步操作,因为setData是异步的
this.setData(
  xxx: yyy
, () => 
  nextOperate();
)

B.生命周期

小程序页面和组件有不同的生命周期

主要把Vue中常用的onCreate, onMount, beforeDestroy 和 小程序的 onLoad, onShow, onHide, onUnload 等对应起来即可。

对于小程序的组件由于生命周期选项有限: onAttach 和 onDetach, 因此,需要若不能频繁创建,但是要控制组件显示和隐藏行为的时候,就得靠外部父组件的调用了。

this.selectComponent('someSelector').show();
this.selectComponent('someSelector').hide();

C. 类的动态绑定

根据数据变化样式一般是通过class的动态变化做到的,这里语法稍有不同

<!-- 小程序 -->
<view class="static-class condition ? 'dynamic-class':''"></view>

<!-- Vue -->
<div class="static-class" :class="'dynamic-class':condition"></view>

D. 关于Vue中Computed的移植

这里Vue的Computed在 html模板中可以直接当做变量使用,在小程序里不行,但是可以借助 WXS  实现,官方文档见: WXS文档

wxs的语法像javascript但是和Javascript不太一样(不太能理解为啥要这样设计),这里举一个例子,把当前时间戳显示出来:

<!-- Vue -->
<template>
  <div> now </div>
</template>
<script>
export default 
  name: "demo",
  computed: 
    now()
      return new Date();  
    
  

</script>

在小程序内 new Date()会被认为是语法错误,得用getTime()函数替代

// wsx
var now = function() 
  // 错误
  // return new Date();
  // 正确
   return getTime();


module.exports = 
  now: now

在wxml中使用时候,如下:

<wxs src="./wxs-util.wxs" module="util" />
<view>
  <view> util.now() </view>
</view>

同理正则表达式用法也不一样,这个各位用的时候再留意就行。

E.  关于Vue中watch的移植

虽然Computed在很多场景下已经可以代替watch做计算了,但是某些时候我仍然需要监听变量变化做一些事的时候,我还是得用watch来实现,这个在小程序内我就简单变为set方法就好了。。。貌似目前也没有遇到什么问题。

// Vue
watch: 
  someVar(val)
    console.log("var change to", val);
  



// 小程序
setVal(val) 
  this.data.val = val;
  console.log("var change to", val);


4)页面参数传递

向下一个页面传递参数,这个在项目初期我们就定死了用url传值的方式了

// Vue的参数获取
let xxx = this.$route.query.xxx;

// 小程序的参数获取
onLoad(options) 
let xxx = options.xxx;

参数传回上一个页面,这里我们Vue采用了自己封装的页面方法,并监听回调,小程序用了页面路由

// Vue
let that = this;
MyCustomAppUtil.push(
  url: 'xxxxx',
  onResume: data => 
    that.yyy = data.yyy
  
);

// 小程序
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2];

prevPage.setData(
  yyy:this.data.yyy
);

 

以上就是我目前迁移业务所涉及的几个关键点了,以后遇到更多需求再更新咯。

以上是关于Vue手动快速移植小程序总结的主要内容,如果未能解决你的问题,请参考以下文章

vue快速上手

快速上手教程PC WebUni-App小程序集成环信IM都在这里了

干货 | LuatOS BSP移植教程,简单到复制粘贴!!!

vuex 快速上手,具体使用方法总结(含使用例子)

程序员小姐姐的烦恼_快速上手大数据ETL神器Kettle(xls导入mysql)

微信小程序快速开发上手