微信⼩程序 mpvue

🌙
手机阅读
本文目录结构

问题

微信⼩程序 mpvue

答案

mpvue

Vue.js ⼩程序版, fork ⾃ vuejs/vue@2.4.1 ,保留了 vue runtime 能⼒,添加了⼩程序平台的⽀持。 mpvue 是⼀个使⽤ Vue.js 开发⼩程序的前端框架。框架基于 Vue.js 核⼼, mpvue 修改了 Vue.js 的 runtime 和 compiler 实现,使其可以运⾏在⼩程序环境中,从⽽为⼩程序开发引⼊了整套 Vue.js 开发体验

框架原理

两个⼤⽅向

  • 通过 mpvue 提供 mp 的 runtime 适配⼩程序
  • 通过 mpvue-loader 产出微信⼩程序所需要的⽂件结构和模块内容

七个具体问题

  • 要了解 mpvue 原理必然要了解 Vue 原理,这是⼤前提

现在假设您对 Vue 原理有个⼤概的了解

由于 Vue 使⽤了 Virtual DOM ,所以 Virtual DOM 可以在任何⽀持 JavaScript 语⾔的平台上操作,譬如说⽬前 Vue ⽀持浏览器平台或 weex ,也可以是 mp (⼩程 序)。那么最后 Virtual DOM 如何映射到真实的 DOM 节点上呢? vue 为平台做了⼀层 适配层,浏览器平台⻅ runtime/node-ops.js 、 weex 平台⻅ runtime/node- ops.js ,⼩程序⻅ runtime/node-ops.js 。不同平台之间通过适配层对外提供相同的接 ⼝, Virtual DOM 进⾏操作 Real DOM 节点的时候,只需要调⽤这些适配层的接⼝即 可,⽽内部实现则不需要关⼼,它会根据平台的改变⽽改变

所以思路肯定是往增加⼀个 mp 平台的 runtime ⽅向⾛。但问题是⼩程序不能操作 DOM ,所以 mp 下的 node-ops.js ⾥⾯的实现都是直接 return obj

新 Virtual DOM 和旧 Virtual DOM 之间需要做⼀个 patch ,找出 diff 。 patch 完了之后的 diff 怎么更新视图,也就是如何给这些 DOM 加⼊ attr 、 class 、 style 等 DOM 属性呢? Vue 中有 nextTick 的概念⽤以更新视图, mpvue 这块对于 ⼩程序的 setData 应该怎么处理呢?

另外个问题在于⼩程序的 Virtual DOM 怎么⽣成?也就是怎么将 template 编译成 render function 。这当中还涉及到运⾏时-编译器-vs-只包含运⾏时,显然如果要提⾼ 性能、减少包⼤⼩、输出 wxml 、 mpvue 也要提供预编译的能⼒。因为要预输出 wxml 且没法动态改变 DOM ,所以动态组件,⾃定义 render ,和 <script type="text/x-template"> 字符串模版等都不⽀持

另外还有⼀些其他问题,最后总结⼀下

  • 1.如何预编译⽣成 render function
  • 2.如何预编译⽣成 wxml , wxss , wxs
  • 3.如何 p atch 出 diff
  • 4.如何更新视图
  • 5.如何建⽴⼩程序事件代理机制,在事件代理函数中触发与之对应的 vue 组件事件响应
  • 6.如何建⽴ vue 实例与⼩程序 Page 实例关联
  • 7.如何建⽴⼩程序和 vue ⽣命周期映射关系,能在⼩程序⽣命周期中触发 vue ⽣命周期

platform/mp 的⽬录结构

.
├── compiler //解决问题1,mpvue-template-compiler源码部分
├── runtime //解决问题3 4 5 6 7
├── util //⼯具⽅法
├── entry-compiler.js //mpvue-template-compiler的⼊⼝。package.json相关命令会⾃
├── entry-runtime.js //对外提供Vue对象,当然是mpvue
└── join-code-in-build.js //编译出SDK时的修复

mpvue-loader

mpvue-loader 是 vue-loader 的⼀个扩展延伸版,类似于超集的关系, 除了 vue-loader 本身所具备的能⼒之外,它还会利⽤ mpvue-template- compiler ⽣成 render function

entry

它会从 webpack 的配置中的 entry 开始,分析依赖模块,并分别打包。在 entry 中 app 属性及其内容会被打包为微信⼩程序所需要的 app.js/app.json/app.wxss ,其 余的会⽣成对应的

⻚⾯ page.js / page.json / page.wxml / page.wxss ,如示例的 entry 将会⽣成如 下这些⽂件,⽂件内容下⽂慢慢讲来:

// webpack.config.js
{
// ...
entry: {
app: resolve('./src/main.js'), // app 字段被识别为 app
index: resolve('./src/pages/index/main.js'), // 其余字段被识别为 pag
'news/home': resolve('./src/pages/news/home/index.js')
}
}
// 产出⽂件的结构
.
├── app.js
├── app.json
├──· app.wxss
├── components
│ ├── card$74bfae61.wxml
│ ├── index$023eef02.wxml
│ └── news$0699930b.wxml
├── news
│ ├── home.js
│ ├── home.wxml
│ └── home.wxss
├── pages
│ └── index
│ ├── index.js
│ ├── index.wxml
│ └── index.wxss
└── static
├── css
│ ├── app.wxss
│ ├── index.wxss
│ └── news
│ └── home.wxss
└── js
├── app.js
├── index.js
├── manifest.js
├── news
│ └── home.js
└── vendor.js

wxml 每⼀个 .vue 的组件都会被⽣成为⼀个 wxml 规范的 template , 然后通过 wxml 规范的 import 语法来达到⼀个复⽤,同时组件如果涉及到 props 的 data 数据,我们也会做相应的处理,举个实际的例⼦: 这样⼀个 Vue 的组件的模版部分会⽣成相应的 wxml

<template>
<div class="my-component" @click="test">
<h1>{{msg}}</h1>
<other-component :msg="msg"></other-component>
</div>
</template>
<script>
import otherComponent from './otherComponent.vue'
export default {
components: { otherComponent },
data () {
return { msg: 'Hello Vue.js!' }
},
methods: {
test() {}
}
}
</script>

这样⼀个 Vue 的组件的模版部分会⽣成相应的 wxml

<import src="components/other-component$hash.wxml" />
<template name="component$hash">
<view class="my-component" bindtap="handleProxy">
<view class="_h1">{{msg}}</view>
<template is="other-component$hash" wx:if="{{ $c[0] }}" data="{{ ..
</view>
</template>

可能已经注意到了 other-component(:msg=“msg”) 被转化成了 。 mpvue 在运⾏时会从根组件开始把所有的组件实例数据合并成⼀个树形的数据,然后 通过 setData 到 appData , $c 是 $children 的缩写。⾄于那个 0 则 是我们的 compiler 处理过后的⼀个标记,会为每⼀个⼦组件打⼀个特定的 不重复的标记。 树形数据结构如下


// 这⼉数据结构是⼀个数组,index 是动态的
{
    $child: {
        '0'{
            // ... root data
            $child: {
                '0': {
                    // ... data
                    msg: 'Hello Vue.js!',
                    $child: {
                        // ...data
                    }
                }
            }
        }
    }
}

wxss

这个部分的处理同 web 的处理差异不⼤,唯⼀不同在于通过配置⽣成 .css 为 .wxss ,其中的对于 css 的若⼲处理,在 postcss-mpvue- wxss 和 px2rpx-loader 这两部分的⽂档中⼜详细的介绍

推荐和⼩程序⼀样,将 app.json/page.json 放到⻚⾯⼊⼝处,使⽤ copy-webpack- plugin copy 到对应的⽣成位置。

这部分内容来源于 app 和 page 的 entry ⽂件,通常习惯是 main.js , 你需要在你的⼊⼝⽂件中 export default { config: {} } ,这才能被我 们的 loader 识别为这是⼀个配置,需要写成 json ⽂件

import Vue from 'vue';
import App from './app';
const vueApp = new Vue(App);
vueApp.$mount();
// 这个是我们约定的额外的配置
export default {
    // 这个字段下的数据会被填充到 app.json / page.json
    config: {
        pages: ['static/calendar/calendar', '^pages/list/list'], // Will be
        window: {
        backgroundTextStyle: 'light',
        navigationBarBackgroundColor: '##455A73',
        navigationBarTitleText: '美团汽⻋票',
        navigationBarTextStyle: '##fff'
        }
    }
};

更多面试题

如果你想了解更多的前端面试题,可以查看本站的WEB前端面试题 ,这里基本包涵了市场上的所有前端方面的面试题,也有一些大公司的面试图,可以让你面试更加顺利。

面试题
HTML CSS JavaScript
jQuery Vue.js React
算法 HTTP Babel
BootStrap Electron Gulp
Node.js 前端经验相关 前端综合
Webpack 微信小程序 -

这些题库还在更新中,如果你有不错的面试题库欢迎分享给我,我整理后放上来;人人为我,我为人人,互帮互助,共同提高,祝大家都拿到心仪的Offer!

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了