• 在尤大微博铺垫着“将会引入一些关于 TypeScript 的改进”一周之后,代号为 Level E 的 Vue.js 2.5 带着日漫风来到了我们眼前。从 Release Notes 可以看到,Vue.js 2.5 有着更好的 TypeScript 集成,更好的错误处理...

    在尤大微博铺垫着“将会引入一些关于 TypeScript 的改进”一周之后,代号为 Level E 的 Vue.js 2.5 带着日漫风来到了我们眼前。从 Release Notes 可以看到,Vue.js 2.5 有着更好的 TypeScript 集成,更好的错误处理,更好地支持单文件组件中的函数式组件以及与环境无关的服务端渲染。

    具体如下:

    更好的 TypeScript 集成

    得益于 TypeScript 团队的帮助,2.5 提供了大大改进的类型声明:

    • 使用默认的 Vue API 时,对于 this 可以使用适当的类型推断。 它也可以在单文件组件中工作!

    • 基于组件的 props 选项,对于 this 中的 props 输入推断。

    • 最重要的是,

      这些改进也使得纯 JavaScript 用户受益匪浅!

      如果你使用 VSCode 与超级棒的的 Vetur 扩展,你将获得大大改进的自动完成建议,甚至在Vue组件中使用纯 JavaScript 时也能获得输入提示! 这是因为vue-language-server是负责分析 Vue 组件的内部包,可以利用 TypeScript 编译器来提取有关你的代码的更多信息。 此外,任何支持语言服务器协议的编辑器都可以利用 vue-language-server来提供类似的功能。

    注意:TypeScript 用户还应将以下包更新为最新版本从而兼容类型声明:vue-router,vuex,vuex-router-sync 和 vue-class-component。

    更好地错误处理

    在 2.4 及更早版本中,我们通常使用全局 config.errorHandleroption 来处理应用程序中的意外错误。 我们还有 renderError 组件选项来处理渲染函数中的错误。 但是,我们缺少处理应用程序特定部分内的泛型错误的机制。

    在2.5中,我们引入了新的 errorCaptured 钩子。 具有此钩子的组件捕获其子组件树(不包括其自身)中的所有错误(不包括在异步回调中调用的那些)。 如果你熟悉 React,这与 React 16 中引入的错误边界的概念相似。钩子接收与全局 errorHandler 相同的参数,你可以利用这个 钩子(https:// http://gist.github.com/yyx990803/ 9bdff05e5468a60ced06c29c39114c6b #error-handling-with-errorcaptured-hook)来优雅地处理和显示错误。

    更好地支持 SFC 中的函数式组件

    使用 vue-loader> = 13.3.0 和 Vue 2.5,在 * .vue 文件中定义为单个文件组件的函数式组件现在可以得到正确的模板编译,Scoped CSS和热重新加载支持。 这使得将叶子组件转换为函数式的更为容易,从而进行性能优化。

    与环境无关的服务端渲染

    vue-server-renderer 的默认构建假定一个 Node.js 环境,这使得它在有的 JavaScript 运行时(如 php-v8js 或Nashorn)中不可用。 在 2.5 中,我们已经发布了一个与环境无关的 vue-server-renderer 版本,可以在浏览器或纯 JavaScript 引擎中使用。 这可以打开有趣的策略,例如直接在 PHP 进程中使用 Vue 服务端渲染。

    同样,建议你查看完整的发布说明从而了解其他 API 的改进,包括 v-on,v-model,scoped slot,provide/inject 等。

    Vue 2.5.0 源码下载: https://codeload.github.com/vuejs/vue/zip/v2.5.0

    Vue.js 这款渐进式的 JavaScript 框架自 2013 年发布至今,其简洁的语法设计、轻量快速的特点深受技术社区喜爱,在国内外都获得了非常广泛的应用及拓展,比如饿了么的开源组件库 Element UI 即是 Vue 开发,而阿里巴巴的 Weex 与 Vue 也多有合作。

    今天,我们来介绍一款由美团点评研发,使用 Vue.js 来开发微信小程序的前端框架 —— mpVue。使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为 H5 和小程序提供了代码复用的能力。如果想将 H5 项目改造为小程序,或开发小程序后希望将其转换为 H5,mpVue将是十分契合的方案。

    为了提高开发效率,增强开发体验,我们造了个用 Vue 开发小程序的轮子

    小程序开发特点

    微信小程序推荐简洁的开发方式,通过多页面聚合完成轻量的产品功能。小程序以离线包方式下载到本地,通过微信客户端载入和启动,开发规范简洁,技术封装彻底,自成开发体系,有 Native 和 H5 的影子,但又绝不雷同。

    小程序本身定位为一个简单的逻辑视图层框架,官方并不推荐用来开发复杂应用,但业务需求却难以做到精简。复杂的应用对开发方式有较高的要求,如组件和模块化、自动构建和集成、代码复用和开发效率等,但小程序开发规范较大地限制了这部分能力。为了解决上述问题,提供更好的开发体验,我们创造了 mpVue,通过使用 Vue.js 开发微信小程序。

    mpVue 是什么

    mpVue 是一套定位于开发小程序的前端开发框架,其核心目标是提高开发效率,增强开发体验。使用该框架,开发者无须了解小程序开发规范,只需要熟悉 Vue.js 基本语法即可上手。框架提供了完全的 Vue.js 开发体验,开发者编写 Vue.js 代码,mpVue 将其解析转换为小程序并确保其正确运行。此外,框架还通过 CLI 工具向开发者提供 Quick Start 示例代码,开发者只需执行一条简单命令,即可获得可运行的项目。

    为什么做 mpVue

    在小程序内测之初,我们计划快速迭代出一款对标 H5 的产品实现,其核心诉求在于快速实现、代码复用、低成本和高效率等。随后我们经历了多个小程序建设,结合业务场景、技术选型和小程序开发方式,整理汇总出了开发阶段面临的主要问题:

    1. 组件化机制不够完善;
    2. 代码多端复用能力欠缺;
    3. 小程序框架和团队技术栈无法有机结合;
    4. 小程序学习成本不够低。

    具体体现为:

    • 组件机制:小程序逻辑和视图层代码彼此分离,公共组件提取后无法聚合为单文件入口,组件需分别在视图层和逻辑层引入,维护性差;组件无命名空间机制,事件回调必须设置为全局函数,组件设计有命名冲突的风险,数据封装不强。开发者需要友好的代码组织方式,通过 ES 模块一次性导入;组件数据有良好的封装。成熟的组件机制,对工程化开发至关重要。
    • 多端复用:常见的业务场景有两类,通过已有 H5 产品改造为小程序应用或反之。从效率角度出发,开发者希望通过复用代码完成开发,但小程序开发框架却无法做到。我们曾尝试通过静态代码分析将 H5 代码转换为小程序,但只做了视图层转换,无法带来更多收益。多端代码复用需要更成熟的解决方案。

    另一方面,小程序开发方式与 H5 近似,因此我们考虑和 H5 做代码复用。同时,沿袭团队技术栈选型,我们将 Vue.js 确定为小程序开发规范。使用 Vue.js 开发小程序,将直接带来如下开发效率的提升:

    1. H5 代码可以通过最小修改复用到小程序;
    2. 使用 Vue.js 组件机制开发小程序,可实现小程序和 H5 组件复用;
    3. 技术栈统一后小程序学习成本降低,开发者从 H5 转换到小程序不需要更多学习;
    4. 代码维护成本降低,Vue.js 代码可以让所有前端直接参与开发维护。

    为什么是 Vue.js?这取决于团队技术栈选型,引入新的选型对统一技术栈和提高开发效率相悖,有违开发工具服务业务的初衷。

    mpVue 的演进

    mpVue 的形成,来源于业务场景和需求,最终方案的确定,经历了三个阶段。

    • 第一阶段:我们实现了一个视图层代码转换工具,旨在提高代码首次开发效率。通过将 H5 视图层代码转换为小程序代码,包括 HTML 标签映射、Vue.js 模板和样式转换,在此目标代码上进行二次开发。我们做到了有限的代码复用,但组件化开发和小程序学习成本并未得到有效改善。
    • 第二阶段:我们着眼于完善代码组件化机制。参照 Vue.js 组件规范设计了代码组织形式,通过代码转换工具将代码解析为小程序。转换工具主要解决组件间数据同步、生命周期关联和命名空间问题。最终我们实现了一个 Vue.js 语法子集,但想要实现更多特性或跟随 Vue.js 版本迭代,工作量变得难以估计,有永无止境之感。
    • 第三阶段:我们的目标是实现对 Vue.js 语法全集的支持,达到使用 Vue.js 开发小程序的目的。并通过引入 Vue.js RunTime 实现了对 Vue.js 语法的支持,从而避免了人肉语法适配。至此,我们完成了使用 Vue.js 开发小程序的目的。较好地实现了技术栈统一、组件化开发、多端代码复用、降低学习成本和提高开发效率的目标。

    mpVue 设计思路

    Vue.js 和小程序都是典型的逻辑视图层框架,逻辑层和视图层之间的工作方式为:数据变更驱动视图更新;视图交互触发事件,事件响应函数修改数据再次触发视图更新,如图 1 所示。

    图 1 小程序实现原理

    鉴于 Vue.js 和小程序一致的工作原理,我们思考将小程序的功能托管给 Vue.js,在正确的时机将数据变更同步到小程序,从而达到开发小程序的目的。这样,我们可以将精力聚焦在 Vue.js 上,参照 Vue.js 编写与之对应的小程序代码,小程序负责视图层展示,所有业务和逻辑收敛到 Vue.js 中,Vue.js 数据变更后同步到小程序,如图 2 所示。如此一来,我们就获得了以 Vue.js 的方式开发小程序的能力。为此,我们设计的方案如下:

    图 2 mpVue 实现原理

    Vue 代码:

    1. 将小程序页面编写为 Vue.js 实现;
    2. 以 Vue.js 开发规范实现父子组件关联。

    小程序代码:

    1. 以小程序开发规范编写视图层模板;
    2. 配置生命周期函数,关联数据更新调用;
    3. 将 Vue.js 数据映射为小程序数据模型。

    并在此基础上,附加如下机制:

    1. Vue 实例与小程序 Page 实例建立关联;
    2. 小程序和 Vue 生命周期建立映射关系,能在小程序生命周期中触发 Vue 生命周期;
    3. 小程序事件建立代理机制,在事件代理函数中触发与之对应的 Vue 组件事件响应。

    这套机制总结起来非常简单,但实现却相当复杂。在揭秘具体实现之前,读者可能会有这样一些疑问:

    1. 要同时维护 Vue.js 和小程序,是否需要写两个版本的代码实现?
    2. 小程序负责视图层展现,Vue.js 的视图层是否还需要,如果不需要应该如何处理?
    3. 生命周期如何打通,数据同步更新如何实现?

    上述问题包含了 mpVue 框架的核心内容,下文将仔细为你道来。首先,mpVue 为提高效率而生,本身提供了自动生成小程序代码的能力,小程序代码根据 Vue.js 代码构建得到,并不需要同时开发两套代码。

    Vue.js 视图层渲染由 Render 方法完成,同时在内存中维护着一份虚拟 DOM,mpVue 无需使用 Vue.js 完成视图层渲染,因此我们改造了 Render 方法,禁止视图层渲染。熟悉源代码的读者都知道 Vue RunTime 有多个平台的实现,除了我们常见的 Web 平台,还有 Weex。从现在开始,我们增加了新的平台 mpVue。

    再看第三个问题,生命周期和数据同步是 mpVue 框架的灵魂,Vue.js 和小程序的数据彼此隔离,各自有不同的更新机制。mpVue 从生命周期和事件回调函数切入,在 Vue.js 触发数据更新时实现数据同步。小程序通过视图层呈现给用户、通过事件响应用户交互,Vue.js 在后台维护着数据变更和逻辑。可以看到,数据更新发端于小程序,处理自 Vue.js,Vue.js 数据变更后再同步到小程序。为实现数据同步,mpVue 修改了 Vue.js RunTime 实现,在 Vue.js 的生命周期中增加了更新小程序数据的逻辑。

    而用户交互触发的数据更新则是通过事件代理机制完成。在 Vue.js 代码中,事件响应函数对应到组件的 method 方法,Vue.js 自动维护了上下文环境。然而在小程序中并没有类似的机制,又因为 Vue.js 执行环境中维护着一份实时的虚拟 DOM,这与小程序的视图层完全对应。我们思考,在小程序组件节点上触发事件后,只要找到虚拟 DOM 上对应的节点,触发对应的事件不就完成了么。Vue.js 事件响应如果触发了数据更新,其生命周期函数更新将自动触发,在此函数上同步更新小程序数据,数据同步就实现了。

    mpVue 如何使用

    mpVue 框架本身由多个 npm 模块构成,入口模块已经处理好依赖关系,开发者只需要执行如下代码即可完成本地项目创建。

    安装 vue-cli

    $ npm install --global vue-cli

    根据模板项目创建本地项目,目前为内网地址,暂稳开放

    $ vue init ‘bitbucket:xxx.meituan.com:hfe/mpvue-quickstart’ --clone my-project

    安装依赖和启动自动构建

    $ cd my-project

    $ npm install

    $ npm run dev

    执行完上述命令,在当前项目的 dist 子目录将构建出小程序目标代码,使用小程序开发者工具载入 dist 目录即可启动本地调试和预览。

    示例项目遵循 Vue.js 模板项目规范,通过 Vue.js 命令行工具 vue-cli 创建。代码组织形式与 Vue.js 官方实例保持一致,我们为小程序定制了 Vue.js RunTime 和 Webpack 加载器,此部分依赖也已经内置到项目中。

    针对小程序开发中常见的两类代码复用场景,mpVue 框架为开发者提供了解决思路和技术支持,开发者只需要在此指导下进行项目配置和改造。

    将小程序转换为 H5

    直接使用 Vue.js 规范开发小程序,代码本身与 H5 并无不同,具体代码差异会集中在平台 API 部分。此外无需明显改动,改造主要分以下几个部分:

    1. 将小程序平台的 Vue.js 框架替换为标准 Vue.js;
    2. 将小程序平台的 Vue-loader 加载器替换为标准 Vue-loader;
    3. 适配和改造小程序与 H5 的底层 API 差异。

    将 H5 转换为小程序

    已经使用 Vue.js 开发完 H5,则需要完成以下事宜:

    1. 将标准 Vue.js 替换为小程序平台的 Vue.js 框架;
    2. 将标准 Vue-loader 加载器替换为小程序平台的 Vue-loader;
    3. 适配和改造小程序与 H5 的底层 API 差异。

    根据小程序开发平台提供的能力,我们最大程度地支持了 Vue.js 语法特性,但部分功能现阶段暂时尚未实现,具体见表 1。

    表 1 mpVue 暂不支持的语法特性

    mpVue 框架的目标是将小程序和 H5 的开发方式通过 Vue.js 建立关联,达到最大程度的代码复用。但由于平台差异的客观存在(主要集中在实现机制、底层 API 能力差异),我们无法做到代码 100%复用,平台差异部分的改造成本无法避免。对于代码复用的场景,开发者需要重点思考如下问题并做好准备:

    1. 尽量使用平台无的语法特性,这部分特性无需转换和适配成本;
    2. 避免使用不支持的语法特性,譬如 slot、filter 等,降低改造成本;
    3. 如果使用特定平台 API,考虑抽象好适配层接口,通过切换底层实现完成平台转换。

    mpVue 最佳实践

    在表 2 中,我们对微信小程序、mpVue、WePY 这三个开发框架的主要能力和特点做了横向对比,帮助大家了解不同框架的侧重点,结合业务场景和开发习惯,确定技术方案。对于如何更好地使用 mpVue 进行小程序开发,我们总结了一些最佳实践。

    表 2 框架主要能力及特性对比

    1. 使用 vue-cli 命令行工具创建项目,使用 Vue 2.x 的语法规范进行开发;
    2. 避免使用不框架不支持的语法特性,即有部分 Vue.js 语法在小程序中无法使用,尽量 mpVue 和 Vue.js 共有特性;
    3. 合理设计数据模型,对数据的更新和操作做到细粒度控制,避免性能问题;
    4. 合理使用组件化开发小程序,提高代码复用。

    结语

    mpVue 框架已经在业务项目中得到实践和验证,目前开发文档也已经就绪,正在做开源前的最后准备,希望能够为小程序和 Vue.js 生态贡献一份力量。mpVue 的初衷是希望让 Vue.js 的开发者以低成本接入小程序开发,其能力和使用体验还有待进一步的检验。我们未来会继续扩展现有功能、解决用户的问题和需求、优化开发体验、完善周边生态建设,以帮助到更多的开发者。

    需要说明一下,mpVue 是通过 fork Vue.js 源码进行二次开发,新增加了 mp 平台的 Vue.js 实现,我们保留了跟随 Vue.js 版本升级的能力,希望未来能够实现更好的能力增强,最后感谢 Vue.js 框架和微信小程序对业界带来的便利

    本文作者:火龙果软件工程
    原文作者:用Vue开发小程序的框架-实战教程-小程序社区-微信小程序-微信小程序开发社区-小程序开发论坛-微信小程序联盟


    展开全文
  • mpvue是一款使用Vue.js开发微信小程序的前端框架。使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为H5和小程序提供了代码复用的能力。如果想将 H5 项目改造为小程序,或开发小程序后希望将其转换为H5,mpvue...

    前言

    mpvue是一款使用Vue.js开发微信小程序的前端框架。使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为H5和小程序提供了代码复用的能力。如果想将 H5 项目改造为小程序,或开发小程序后希望将其转换为H5,mpvue将是十分契合的一种解决方案。

    目前,mpvue已经在美团点评多个实际业务项目中得到了验证,因此我们决定将其开源,希望更多技术同行一起开发,应用到更广泛的场景里去。github项目地址请参见mpvue 。使用文档请参见 http://mpvue.com/

    为了帮助大家更好的理解mpvue的架构,接下来我们来解析框架的设计和实现思路。文中主要内容已经发表在《程序员》杂志2017年第9期小程序专题封面报道,内容略有修改。

    小程序开发特点

    微信小程序推荐简洁的开发方式,通过多页面聚合完成轻量的产品功能。小程序以离线包方式下载到本地,通过微信客户端载入和启动,开发规范简洁,技术封装彻底,自成开发体系,有Native和H5的影子,但又绝不雷同。

    小程序本身定位为一个简单的逻辑视图层框架,官方并不推荐用来开发复杂应用,但业务需求却难以做到精简。复杂的应用对开发方式有较高的要求,如组件和模块化、自动构建和集成、代码复用和开发效率等,但小程序开发规范较大的限制了这部分能力。为了解决上述问题,提供更好的开发体验,我们创造了mpvue,通过使用Vue.js来开发微信小程序。

    mpvue是什么

    mpvue是一套定位于开发小程序的前端开发框架,其核心目标是提高开发效率,增强开发体验。使用该框架,开发者只需初步了解小程序开发规范、熟悉Vue.js基本语法即可上手。框架提供了完整的 Vue.js 开发体验,开发者编写Vue.js代码,mpvue 将其解析转换为小程序并确保其正确运行。此外,框架还通过 vue-cli 工具向开发者提供quick start 示例代码,开发者只需执行一条简单命令,即可获得可运行的项目。

    为什么做mpvue

    在小程序内测之初,我们计划快速迭代出一款对标 H5 的产品实现,核心诉求是:快速实现、代码复用、低成本和高效率… 随后经历了多个小程序建设,结合业务场景、技术选型和小程序开发方式,我们整理汇总出了开发阶段面临的主要问题:

    • 组件化机制不够完善
    • 代码多端复用能力欠缺
    • 小程序框架和团队技术栈无法有机结合
    • 小程序学习成本不够低

    组件机制:小程序逻辑和视图层代码彼此分离,公共组件提取后无法聚合为单文件入口,组件需分别在视图层和逻辑层引入,维护性差;组件无命名空间机制,事件回调必须设置为全局函数,组件设计有命名冲突的风险,数据封装不强。开发者需要友好的代码组织方式,通过 ES 模块一次性导入;组件数据有良好的封装。成熟的组件机制,对工程化开发至关重要。

    多端复用:常见的业务场景有两类,通过已有 H5 产品改造为小程序应用或反之。从效率角度出发,开发者希望通过复用代码完成开发,但小程序开发框架却无法做到。我们尝试过通过静态代码分析将 H5 代码转换为小程序,但只做了视图层转换,无法带来更多收益。多端代码复用需要更成熟的解决方案。

    引入 Vue.js:小程序开发方式与 H5 近似,因此我们考虑和 H5 做代码复用。沿袭团队技术栈选型,我们将 Vue.js 确定为小程序开发规范。使用 Vue.js 开发小程序,将直接带来如下开发效率提升:

    • H5 代码可以通过最小修改复用到小程序
    • 使用 Vue.js 组件机制开发小程序,可实现小程序和 H5 组件复用
    • 技术栈统一后小程序学习成本降低,开发者从 H5 转换到小程序不需要更多学习
    • Vue.js 代码可以让所有前端直接参与开发维护

    为什么是 Vue.js?这取决于团队技术栈选型,引入新的选型与统一技术栈和提高开发效率相悖,有违开发工具服务业务的初衷。

    mpvue 的演进

    mpvue的形成,来源于业务场景和需求,最终方案的确定,经历了三个阶段。

    第一阶段:我们实现了一个视图层代码转换工具,旨在提高代码首次开发效率。通过将H5视图层代码转换为小程序代码,包括 HTML 标签映射、Vue.js 模板和样式转换,在此目标代码上进行二次开发。我们做到了有限的代码复用,但组件化开发和小程序学习成本并未得到有效改善。

    第二阶段:我们着眼于完善代码组件化机制。参照 Vue.js 组件规范设计了代码组织形式,通过代码转换工具将代码解析为小程序。转换工具主要解决组件间数据同步、生命周期关联和命名空间问题。最终我们实现了一个 Vue.js 语法子集,但想要实现更多特性或跟随 Vue.js 版本迭代,工作量变得难以估计,有永无止境之感。

    第三阶段:我们的目标是实现对 Vue.js 语法全集的支持,达到使用 Vue.js 开发小程序的目的。并通过引入 Vue.js runtime 实现了对 Vue.js 语法的支持,从而避免了人肉语法适配。至此,我们完成了使用 Vue.js 开发小程序的目的。较好地实现了技术栈统一、组件化开发、多端代码复用、降低学习成本和提高开发效率的目标。

    mpvue设计思路

    Vue.js 和小程序都是典型的逻辑视图层框架,逻辑层和视图层之间的工作方式为:数据变更驱动视图更新;视图交互触发事件,事件响应函数修改数据再次触发视图更新,如图1所示。

    这里写图片描述

    图1: 小程序实现原理

    鉴于 Vue.js 和小程序一致的工作原理,我们思考将小程序的功能托管给 Vue.js,在正确的时机将数据变更同步到小程序,从而达到开发小程序的目的。这样,我们可以将精力聚焦在 Vue.js 上,参照 Vue.js 编写与之对应的小程序代码,小程序负责视图层展示,所有业务逻辑收敛到 Vue.js 中,Vue.js 数据变更后同步到小程序,如图2所示。如此一来,我们就获得了以 Vue.js 的方式开发小程序的能力。为此,我们设计的方案如下:


    图2:mpvue 实现原理

    Vue代码
    - 将小程序页面编写为 Vue.js 实现
    - 以 Vue.js 开发规范实现父子组件关联

    小程序代码
    - 以小程序开发规范编写视图层模板
    - 配置生命周期函数,关联数据更新调用
    - 将 Vue.js 数据映射为小程序数据模型

    并在此基础上,附加如下机制
    - Vue.js 实例与小程序 Page 实例建立关联
    - 小程序和 Vue.js 生命周期建立映射关系,能在小程序生命周期中触发 Vue.js 生命周期
    - 小程序事件建立代理机制,在事件代理函数中触发与之对应的 Vue.js 组件事件响应

    这套机制总结起来非常简单,但实现却相当复杂。在揭秘具体实现之前,读者可能会有这样一些疑问:

    • 要同时维护 Vue.js 和小程序,是否需要写两个版本的代码实现?
    • 小程序负责视图层展现,Vue.js的视图层是否还需要,如果不需要应该如何处理?
    • 生命周期如何打通,数据同步更新如何实现?

    上述问题包含了 mpvue 框架的核心内容,下文将仔细为你道来。首先,mpvue 为提高效率而生,本身提供了自动生成小程序代码的能力,小程序代码根据 Vue.js 代码构建得到,并不需要同时开发两套代码。

    Vue.js 视图层渲染由 render 方法完成,同时在内存中维护着一份虚拟 DOM,mpvue 无需使用 Vue.js 完成视图层渲染,因此我们改造了 render 方法,禁止视图层渲染。熟悉源代码的读者,都知道 Vue runtime 有多个平台的实现,除了我们常见的 Web 平台,还有 Weex。从现在开始,我们增加了新的平台 mpvue。

    生命周期关联:生命周期和数据同步是 mpvue 框架的灵魂,Vue.js 和小程序的数据彼此隔离,各自有不同的更新机制。mpvue 从生命周期和事件回调函数切入,在 Vue.js 触发数据更新时实现数据同步。小程序通过视图层呈现给用户、通过事件响应用户交互,Vue.js 在后台维护着数据变更和逻辑。可以看到,数据更新发端于小程序,处理自 Vue.js,Vue.js 数据变更后再同步到小程序。为实现数据同步,mpvue 修改了 Vue.js runtime 实现,在 Vue.js 的生命周期中增加了更新小程序数据的逻辑。

    事件代理机制:用户交互触发的数据更新通过事件代理机制完成。在 Vue.js 代码中,事件响应函数对应到组件的 method, Vue.js 自动维护了上下文环境。然而在小程序中并没有类似的机制,又因为 Vue.js 执行环境中维护着一份实时的虚拟 DOM,这与小程序的视图层完全对应,我们思考,在小程序组件节点上触发事件后,只要找到虚拟 DOM 上对应的节点,触发对应的事件不就完成了么;另一方面,Vue.js 事件响应如果触发了数据更新,其生命周期函数更新将自动触发,在此函数上同步更新小程序数据,数据同步也就实现了。

    mpvue如何使用

    mpvue框架本身由多个npm模块构成,入口模块已经处理好依赖关系,开发者只需要执行如下代码即可完成本地项目创建。

    # 安装 vue-cli
    $ npm install --global vue-cli
    # 根据模板项目创建本地项目,目前为内网地址
    $ vue init ‘bitbucket:xxx.meituan. com:hfe/mpvue-quickstart’ --clone my- project
    # 安装依赖和启动自动构建
    $ cd my-project
    $ npm install
    $ npm run dev

    执行完上述命令,在当前项目的 dist 子目录将构建出小程序目标代码,使用小程序开发者工具载入 dist 目录即可启动本地调试和预览。示例项目遵循 Vue.js 模板项目规范,通过Vue.js 命令行工具vue-cli创建。代码组织形式与 Vue.js 官方实例保持一致,我们为小程序定制了 Vue.js runtime 和 webpack 加载器,此部分依赖也已经内置到项目中。

    针对小程序开发中常见的两类代码复用场景,mpvue 框架为开发者提供了解决思路和技术支持,开发者只需要在此指导下进行项目配置和改造。我们内部实践了一个将 H5 转换为小程序的项目,下图为使用 mpvue 框架的转换效果:

    这里写图片描述

    图3: H5 和小程序转换效果

    将小程序转换为H5:直接使用 Vue.js 规范开发小程序,代码本身与H5并无不同,具体代码差异会集中在平台 Api 部分。此外并不需明显改动,改造主要分如下几部分:

    • 将小程序平台的 Vue.js 框架替换为标准 Vue.js
    • 将小程序平台的 vue-loader 加载器替换为标准 vue-loader
    • 适配和改造小程序与 H5 的底层 Api 差异

    将H5转换为小程序:已经使用 Vue.js 开发完 H5,我们需要做的事情如下:

    • 将标准 Vue.js 替换为小程序平台的 Vue.js 框架
    • 将标准 vue-loader 加载器替换为小程序平台的 vue-loader
    • 适配和改造小程序与 H5 的底层 Api 差异

    根据小程序开发平台提供的能力,我们最大程度的支持了 Vue.js 语法特性,但部分功能现阶段暂时尚未实现。

    这里写图片描述

    表1: mpvue 暂不支持的语法特性

    项目转换注意事项:框架的目标是将小程序和 H5 的开发方式通过 Vue.js 建立关联,达到最大程度的代码复用。但由于平台差异的客观存在(主要集中在实现机制、底层Api 能力差异),我们无法做到代码 100% 复用,平台差异部分的改造成本无法避免。对于代码复用的场景,开发者需要重点思考如下问题并做好准备:

    • 尽量使用平台无的语法特性,这部分特性无需转换和适配成本
    • 避免使用不支持的语法特性,譬如 slot, filter 等,降低改造成本
    • 如果使用特定平台 Api ,考虑抽象好适配层接口,通过切换底层实现完成平台转换

    mpvue 最佳实践

    在表2中,我们对微信小程序、mpvue、WePY 这三个开发框架的主要能力和特点做了横向对比,帮助大家了解不同框架的侧重点,结合业务场景和开发习惯,确定技术方案。对于如何更好地使用 mpvue 进行小程序开发,我们总结了一些最佳实践。

    • 使用 vue-cli 命令行工具创建项目,使用Vue 2.x 的语法规范进行开发
    • 避免使用框架不支持的语法特性,部分 Vue.js语法在小程序中无法使用,尽量使用 mpvue 和 Vue.js 共有特性
    • 合理设计数据模型,对数据的更新和操作做到细粒度控制,避免性能问题
    • 合理使用组件化开发小程序,提高代码复用率

    这里写图片描述

    表2: 框架使用特点对比

    结语

    mpvue 框架已经在业务项目中得到实践和验证,目前正在美团点评内部大范围使用。mpvue 来源于开源社区,饮水思源,我们也希望为开源社区贡献一份力量,为广大小程序开发者提供一套技术方案。mpvue 的初衷是让 Vue.js 的开发者以低成本接入小程序开发,做到代码的低成本迁移和复用,我们未来会继续扩展现有能力、解决开发者的诉求、优化使用体验、完善周边生态建设,帮助到更多的开发者。

    最后,mpvue 基于 Vue.js 源码进行二次开发,新增加了小程序平台的实现,我们保留了跟随 Vue.js 版本升级的能力,由衷的感谢 Vue.js 框架和微信小程序给业界带来的便利。

    作者简介


    成全:美团点评酒旅事业群资深前端工程师,目前主要从事移动端和小程序技术方向,致力于小程序的工程化开发和业务级应用。

    招聘时间~美团点评酒旅业务研发中心诚招中、高级前端工程师、技术专家,欢迎投递简历到 huchengquan#meituan.com。

    这里写图片描述

    展开全文
  • vue+vueRouter+vuex+vue编写的单页面手机端项目框架 非常适合H5项目··· 咱们开始吧! main.js import Vue from 'vue' import Vuex from 'vuex' import FastClick from 'fastclick' import {...

    用vue+vueRouter+vuex+vue编写的单页面手机端项目框架

    非常适合H5项目···

    咱们开始吧!


    main.js


    import Vue from 'vue'
    import Vuex from 'vuex'
    import FastClick from 'fastclick'
    import {WechatPlugin, AjaxPlugin, LoadingPlugin, ToastPlugin, AlertPlugin} from 'vux'
    import router from './router'
    import App from './App'
    /**
     * 加载插件
     */
    Vue.use(Vuex)
    Vue.use(WechatPlugin)
    Vue.use(AjaxPlugin)
    Vue.use(LoadingPlugin)
    Vue.use(ToastPlugin)
    Vue.use(AlertPlugin)
    /**
     * 设置vuex
     */
    const store = new Vuex.Store({})
    store.registerModule('vux', {
      state: {
        loading: false,
        showBack: true,
        title: '',
        number: ''
      },
      mutations: {
        updateLoading (state, loading) {
          state.loading = loading
        },
        updateShowBack (state, showBack) {
          state.showBack = showBack
        },
        updateTitle (state, title) {
          state.title = title
        },
        updateNumber (state, number){
          let num = ''
          if(number <= 0){
            state.number = num
          }else {
            num = number.toString()
            state.number = num
          }
    
        }
      }
    })
    /**
     * 公用组件
     */
    Vue.prototype.updateTitle = function (value) {
      this.$store.commit('updateTitle', value)
    }
    /**
     *  日志输出开关
     */
    Vue.config.productionTip = true
    /**
     *  点击延迟
     */
    FastClick.attach(document.body)
    /**
     *  创建实例
     */
    new Vue({
      store,
      router,
      render: h => h(App)
    }).$mount('#app-box')
    


    2、路由文件(router/index.js)

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    /**
     *  加载模块
     */
    Vue.use(VueRouter)
    /**
     *  路由配置
     */
    const router = new VueRouter({
      base: __dirname,
      likActiveClass: 'link-active',
      routes: [
        {
          path: '/init',
          name: 'init',
          component: resolve => require(['../components/init.vue'], resolve),
          children: [
            {
              path: 'personal/userInfo',
              name: 'userInfo',
              component: resolve => require(['../components/personal/userInfo.vue'], resolve),
              meta: {title: '主页'}
            },
            {
              path: 'home',
              name: 'home',
              component: resolve => require(['../components/home.vue'], resolve),
              meta: {title: '主页'}
            }
          ]
        },
        {
          path: '/',
          name: 'login',
          component: resolve => require(['../components/login.vue'], resolve),
          meta: {title: '登录'}
        }
      ]
    })
    
    /**
     *  路由出口
     */
    export default router
    


    index.vue

    <template>
      <div id="Init">
        <top class="top"></top>
        <transition>
          <router-view></router-view>
        </transition>
        <bottom></bottom>
      </div>
    </template>
    
    <script>
      import Top from './layouts/top.vue'
      import Bottom from './layouts/bottom.vue'
      export default {
        components: { Top, Bottom}
      }
    </script>
    
    <style>
      html, body {
        height: 100%;
        width: 100%;
        overflow-x: hidden;
      }
      #Init .top{margin-bottom: 46px;}
    </style>
    
    里面的top和bottom是自己写的组件,可以删掉(还是贴上代码吧!)

    top.vue

    <template>
      <div id="Top">
        <x-header slot="header" style="width:100%;position:absolute;left:0;top:0;z-index:100;"
                  :left-options="{showBack: showBack, backText: ''}" :right-options="{showMore: true}"
                  @on-click-more="showMenus = true">{{title}}
        </x-header>
    
        <div v-transfer-dom>
          <popup v-model="showMenus" position="right">
            <div style="width:200px;">
              <group>
                <cell v-for="(menu,value) in menuList" :title="menu.title" :value="menu.value"
                      @click.native="goToUrl(menu.url)" :class="menu.class" v-bind:key="menu.key"></cell>
              </group>
            </div>
          </popup>
        </div>
      </div>
    </template>
    
    <script>
      import {mapState} from 'vuex'
      import {XHeader, TransferDom, Popup, Group, Cell, cookie} from 'vux'
    
      export default {
        directives: {
          TransferDom
        },
        components: {
          XHeader,
          Popup,
          Group,
          Cell
        },
        computed: {
          ...mapState({
            showBack: state => state.vux.showBack,
            title: state => state.vux.title
          })
        },
        data () {
          return {
            menuList: [
              {title: 'userInfo', value: '', url: '/userInfo'},
              {title: '', value: 'userInfo', url: '/userInfo', class: 'menu'},
              {title: 'userInfo', value: '', url: '/userInfo'},
              {title: '', value: 'userInfo', url: '/userInfo', class: 'menu'}
            ],
            showMenus: false
          }
        },
        methods: {
          goToUrl(path) {
            if (path) {
              console.log(path)
            }
            let vue = this
          }
        }
      }
    </script>
    <style>
      *{font-size: 14px}
      #Top .vux-header-title {
        font-size: 16px;
      }
      #Top .menu {
        margin-right: 70px;
      }
      #Top .menu div {
        color: #000;
      }
      #Top .menu:before {
        right: -70px;
      }
    </style>
    
    bottom.vue

    <template>
      <div>
        <tabbar>
          <tabbar-item selected link="/init/home">
            <img slot="icon" src="static/bottom/icon_nav_button.png">
            <span slot="label">home</span>
          </tabbar-item>
          <tabbar-item show-dot>
            <img slot="icon" src="static/bottom/icon_nav_msg.png">
            <span slot="label">Message</span>
          </tabbar-item>
          <tabbar-item selected link="/init/personal/userInfo">
            <img slot="icon" src="static/bottom/icon_nav_article.png">
            <span slot="label">userInfo</span>
          </tabbar-item>
          <tabbar-item badge="2">
            <img slot="icon" src="static/bottom/icon_nav_cell.png">
            <span slot="label">News</span>
          </tabbar-item>
        </tabbar>
      </div>
    </template>
    
    <script>
      import { Tabbar, TabbarItem, Group, Cell } from 'vux'
    
      export default {
        components: {
          Tabbar,
          TabbarItem,
          Group,
          Cell
        }
      }
    </script>
    <style>
    
    </style>
    
    这两个组件在init里面用到了

    init.vue

    <template>
      <div id="Init">
        <top class="top"></top>
        <transition>
          <router-view></router-view>
        </transition>
        <bottom></bottom>
      </div>
    </template>
    
    <script>
      import Top from './layouts/top.vue'
      import Bottom from './layouts/bottom.vue'
      export default {
        components: { Top, Bottom}
      }
    </script>
    
    <style>
      html, body {
        height: 100%;
        width: 100%;
        overflow-x: hidden;
      }
      #Init .top{margin-bottom: 46px;}
    </style>
    

    这段代码里面有个

    <transition>
      <router-view></router-view>
    </transition>
    也就是说,后面的页面到加载到
    <router-view></router-view>   

    比如http://····················#/init/personal/userInfo  路径里面有init

    好了上述是框架主要代码了,了解vue的一眼就懂了。我也是做个笔记而已。


    附上框架效果图




    最后附上git地址(这个很重要)   https://github.com/Apache-Ra/vue-wechat-demo.git (不定期更新)


    不理解的地方请留意

    展开全文
  • 概述 基础环境: Node.js最新稳定版 Vue2.x ...VueCli3 ...开发:跟普通的vue单页应用开发方式一致。...开发环境下,可以借助chrome进行调试,需要注意的是,如果涉及到微信验证的接口,要手动在sessionStora...

    概述

     npm i //安装依赖
     npm run serve //启动开发环境
     npm run build// 打包
    复制代码
    • 调试:

      • 开发环境下,可以借助chrome进行调试,需要注意的是,如果涉及到微信验证的接口,要手动在sessionStorage中注入 wx_info类似的验证,具体的wx_info配置可以询问后端开发人员

      • 如果要进行真实账号测试或者是生产环境下,可以通过微信开发者工具进行调试,调试方式跟chrome类似。

      • vuex的调试,请先科学上网,然后在chrome拓展工具里搜索安装 Vue.js devtools ,安装完成后打开开发者工具,在最右侧vue栏里进行vuex调试。

    具体使用

    路由管理

    • 采用树形结构管理路由

    • 每一个大模块单独设置一个路由,再汇总到总路由文件

    const Demo=() => import(/* webpackChunkName: "demo-page" */ '@views/demo/index')
    const DemoDetail =() => import(/* webpackChunkName: "demo-page" */ '@views/demo/detail/index')
    
    const DEMO_ROUTERS =[
        {
            path: '/demo',
            name: '订单1',
            component: Demo,
            meta: {requireAuth: false,index:1},
        },
        {
            path: '/detail',
            name: '订单详情',
            component: DemoDetail,
            meta: {requireAuth: false,index:2},
        },
    ]
    
    export default DEMO_ROUTERS
    复制代码
    • 如果该模块较为复杂,页面很多,可以视情况再细分路由。

    • 结合 Vue 的异步组件和 Webpack 的代码分割功能,实现路由组件的懒加载

    serve管理

    • serve 下的 base.js用于全局配置api请求的域名或者ip地址等

      可以快速的切换测试环境和生产环境

    const base = {
         dv:'http://test',  // 测试环境
         pr: 'http://prodect', // 生产环境
         mock:' https://easy-mock.com/mock/5cb4762ae14be30f81aee1a6/mock' // mock环境
    }
    export default base;
    复制代码
    • 推荐一个好用的在线生成前端mock数据的网站,easy-mock

      注册后把mock这边的地址改成你的mock地址即可对接mock接口

    get(url, params) {
            return new Promise((resolve, reject) => {
                axios({
                    method: 'get',
                    url: url,
                    params: params
    
                }).then(res => {
                    // console.log(res);
                    if (res.data.errCode !== 0) Toast.failed(res.data.errMsg);
                    else resolve(res.data);
                }, err => {
                    reject(err);
                    Toast.failed(err.message);
                });
            });
        },
    复制代码

    此处的 errMsg是我自己配的mock接口状态码,请根据自己的项目自行更改,如果不希望在全局使用toast 把此处的toast注释掉即可

    • serve下的 http.js 用于封装axios

      如果是微信公众号的项目,需要token验证,在此处配置token的获取,并且添加到请求头

    数据管理

    • 简单项目无需使用vuex,反而加重项目

    • 数据交互较多,难以管理时,使用vuex提高效率

      按照 store 下的demo 这个module作为参考,分模块编写。

    • 已经集成了vuex数据持久化插件,默认为所有state数据都存入session

      如果要更改存储位置,或者希望局部存入,自行修改plugin配置,配置方法vuex-persistedstate

    自适应方案(rem+vw)

    // 主题色配置
    $theme-color:#4fc08d;
    // rem 单位换算:定为 75px 只是方便运算,750px-75px、640-64px、1080px-108px,如此类推
    $vw_fontsize: 75; // iPhone 6尺寸的根元素大小基准值
    @function rem($px) {
      @return ($px / $vw_fontsize ) * 1rem;
    }
    // 根元素大小使用 vw 单位
    $vw_design: 750;
    html {
      font-size: ($vw_fontsize / ($vw_design / 2)) * 100vw;
      // 同时,通过Media Queries 限制根元素最大最小值
      @media screen and (max-width: 300px) {
        font-size: 64px;
      }
      @media screen and (min-width: 750px) {
        font-size: 108px;
      }
    }
    // body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小
    body {
      max-width: 750px;
      min-width: 300px;
    }
    复制代码
    • 默认配置以750作为设计稿基准

    • 同时可以配置最大最小适配范围

    上述功能都集成在view/demo项目里,可以参考demo具体了解

    开发优化

    • alias:在vue.config查看alias 路径,自行添加或者修改

    • mixins: 已经全局配置,在static 下的mixin 进行样式函数的编写

    用户体验

    • 使用路由懒加载,提高加载速度

    • 全局动态配置了路由切换动画,为了正确显示切换动画,在配置路由时一定要写明路由层级,切换动画时会根据层级比较作为判断

    结语

    没啥干货,权当服务一下前端初学者和伸手党,同时把自己不成熟的框架拿出来供大家检阅,发现不足之处。

    项目地址

    Github

    如果有帮助到您,厚着脸皮希望给个小星星

    转载于:https://juejin.im/post/5cb690f4f265da03705fadc9

    展开全文
  • 最近需要开发微信公众号,前端使用的vue框架,看完腾讯的,我的内心无比沉重,天噜啦,生无可恋~~~ 简单的总结一下吧, 1页面绘制 微信公众号开发而言还是使用基础的html、css、js绘制画面就行,就像h5一样,(一开始...

    vue开发微信公众号入门系列

    最近需要开发微信公众号,前端使用的vue框架,看完腾讯的,我的内心无比沉重,天噜啦,生无可恋~~~
    简单的总结一下吧,

    1页面绘制

    微信公众号开发而言还是使用基础的html、css、js绘制画面就行,就像h5一样,(一开始没做之前我以为还需要,,,单独学习语言,会死人的啊。还好腾讯比较照顾我们前端)

    2获取openid

    其实这个做完之后也感觉非常easy了,你只需要把你的页面部署到服务器上,然后呢,后端会给你这样一段url

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri='+ redirect_uri +'&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect'
    

    每个参数的意义请查看:微信网页授权

    其中redirect_uri成功回调跳转到你的网页,然后后台会给你拼接点参数,从这样
    在这里插入图片描述

    在这里插入图片描述

    你就需要从url上获取code/state然后调取后台给你定义的接口就能取到openid了,前端不需要做的太复杂,无非取参数,调接口获取openid。

    3vue调取微信sdk分享功能

    1.全局分享的页面都是一样的

    npm install weixin-js-sdk --save
    

    在你需要的页面引入

     import wx from 'weixi
    
    

    直接上代码:
    在这里插入图片描述

    注意,调取sdk都需要先wx.config,如果成功的话,就再wx.ready里执行,你在wx.config.jsApiList里面能执行的业务,在微信开发者工具里能看到结果。真机调试的时候wx.config.debug=true,用苹果机能弹出详情

    在这里插入图片描述

    2.业务需要,有邀请页分享有二维码,其它页面分享都一样
    写一个common.js,

     import {
         verifyConfigForShare
       } from '@/api/weiconfig/weiconfig'
       import wx from 'weixin-js-sdk'
       export default {
         weiconfig: function () {
           verifyConfigForShare({
             url: location.href.split('#')[0],
           }).then(res => {
             // console.log(res)
             if (res.code == 0) {
               wx.config({
                 debug: false,
                 appId:appId,
                 nonceStr: res.data.content.nonceStr,
                 signature: res.data.content.signature,
                 timestamp: res.data.content.timestamp,
                 jsApiList: [
                   'onMenuShareTimeline', // 分享到朋友圈接口
                   'onMenuShareAppMessage', //  分享到朋友接口
                   'onMenuShareQQ', // 分享到QQ接口
                   'onMenuShareWeibo', // 分享到微博接口
                   'onMenuShareQZone'
                 ]
               });
               var shareData = {
                 imgUrl: 'http://p9s9revyo.bkt.clouddn.com/%E7%BA%AF%E7%B2%B91.png', // 分享显示的缩略图地址
                 link: 'https://home.vankin.com.cn', // 分享地址
                 desc: '跨越认知边界,成就美好未来', // 分享描述
                 title: '万金科技', // 分享标题
                 success: function () {}
               }
               wx.ready(res => {
                 wx.onMenuShareTimeline(shareData);
                 wx.onMenuShareAppMessage(shareData);
                 wx.onMenuShareQQ({});
                 wx.onMenuShareWeibo({});
                 wx.onMenuShareQZone({})
               })
             }
           })
         },
         addRegister: function () {
           var name = JSON.parse(window.localStorage.getItem('userInfo')).name;
           verifyConfigForShare({
             url: location.href.split('#')[0],
           }).then(res => {
             // console.log(res)
             if (res.code == 0) {
               wx.config({
                 debug: false,
                 appId:appId,
                 nonceStr: res.data.content.nonceStr,
                 signature: res.data.content.signature,
                 timestamp: res.data.content.timestamp,
                 jsApiList: [
                   'onMenuShareTimeline', // 分享到朋友圈接口 
                   'onMenuShareAppMessage', //  分享到朋友接口
                   'onMenuShareQQ', // 分享到QQ接口
                   'onMenuShareWeibo', // 分享到微博接口
                   'onMenuShareQZone'
                 ]
               });
    
               var shareData = {
                 imgUrl: 'http://p9s9revyo.bkt.clouddn.com/%E7%BA%AF%E7%B2%B91.png', // 分享显示的缩略图地址
                 link: 'https://home.vankin.com.cn', // 分享地址
                 desc: '跨越认知边界,成就美好未来', // 分享描述
                 title: name, // 分享标题
                 success: function () {}
               }
               wx.ready(res => {
                 wx.onMenuShareTimeline(shareData);
                 wx.onMenuShareAppMessage(shareData);
                 wx.onMenuShareQQ({});
                 wx.onMenuShareWeibo({});
                 wx.onMenuShareQZone({})
               })
             }
           })
         }
       }
    

    在main.js中全局引入

    import common from '../commonFunction/common.js'
    Vue.prototype.common = common;
    

    在你需要的页面直接引入

     mounted() { /
         this.common.addRegister();
        //  this.common.weiconfig();
        },
    

    4vue调取微信sdk支付功能
    也是在 mounted中请求接口配置 wx.config

     verifyConfig({
              url: location.href.split('#')[0],
            }).then(res => {
              if (res.code == 0) {
                const shareobj = { 
                  'appId': appId,
                  'timestamp': res.data.content.timestamp,
                  'nonceStr': res.data.content.nonceStr,
                  'signature': res.data.content.signature,
                  'jsApiList': ['chooseWXPay']
                }
                this.shareObj = shareobj;
                  wx.config({
                  debug: false,
                  appId: appId,
                  nonceStr: shareobj.nonceStr,
                  signature: shareobj.signature,
                  timestamp: shareobj.timestamp,
                  jsApiList: ['chooseWXPay']
                });
              }
            })
    

    先调取后端接口,获取,再在wx.ready中调 wx.chooseWXPay微信支付

    payMoneyForH5(params).then(res => {
                if (res.code == 0) {
                  const poas = res.data.content;
                  console.log(res)
                  wx.ready((res) => {
                    wx.chooseWXPay({
                      'appId': appId,
                      'timestamp': poas.timeStamp,
                      'nonceStr': poas.nonceStr,
                      'package': poas.package,
                      'signType': poas.signType,
                      'paySign': poas.paySign,
                      success: function (res) {
                        // alert(res)
                        if (res.errMsg == 'chooseWXPay:ok') {
                          that.$router.push({
                            path: '/pay/wxPaySuccess',
                          }) 
                        }
                      },
                      cancel: function (err) {
                        that.$router.push({
                          path: '/pay/wxPayFail',
                          query: {
                            courseId: that.content.id,
                            orderNo: that.orderId
                          }
                        })
                      }
                    })
                  });
                  wx.error(function (res) {
                    console.log(res)
                    alert("wx.error")
                  });
                }
    

    5调取微信摄像头并上传到后台服务器

    也是在 mounted中请求接口配置 wx.config

     init() {
            weixinSignphoto({
              url: url//你当前页面路径
            }).then(res => {
              if (res.success) {
                const shareobj = {
                  'appId': res.data.appId,
                  'timestamp': res.data.timestamp,
                  'nonceStr': res.data.nonceStr,
                  'signature': res.data.signature,
                  'jsApiList': ['chooseImage', 'uploadImage']//调取摄像头和上传照片sdk
                }
                this.shareObj = shareobj;
                this.wxInit(this.shareObj);
              }
            })
          },
          wxInit(shareobj) {//微信的config
            wx.config({
              debug: true,
              appId: shareobj.appId,
              nonceStr: shareobj.nonceStr,
              signature: shareobj.signature,
              timestamp: shareobj.timestamp,
              jsApiList: ['chooseImage', 'uploadImage']
            });
          },
          ready() {//微信的ready
            wx.ready((res) => {
              wx.checkJsApi({
                jsApiList: [
                  'chooseImage',
                  'uploadImage',
                ],
                success: function (res) {
                  console.log(JSON.stringify(res));
                }
              });
            })
          },
    

    首先点击调取摄像头或相册,再上传到微信服务器,会返回你mediaId,然后上传到后端,后端

    在这里插入图片描述
    进行下载去,

    photoBtnb() {//点击上传照片
            var that = this;
            wx.chooseImage({//调取摄像头或相册
              count: 1, // 默认9
              sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
              sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
              success: function (res) {
                  const localIds = res.localIds[0];
                  that.src1 = res.localIds[];//可以先相框显示出来你图片,没有上传成功的话在替换回去,我这里没有走downloadImage和getLocalImgData,图省事了;
                  wx.uploadImage({//上传到微信服务器,上传图片有效期3天,可用微信多媒体接口下载图片到自己的服务器,此处获得的 serverId 即 media_id。
                    localId: localIds, // 需要上传的图片的本地ID,由chooseImage接口获得  
                    isShowProgressTips: 1, // 默认为1,显示进度提示  
                    success: function (res) {
                      const mediaId = res.serverId;
                      that.src1Id=mediaId;//id传到后台
                      const params={};
                      params.mediaId=mediaId;
                      savePicture(params).then(res=>{//传给自己的后台,后台根据这段代码上面的图片去拼接
                        if (res.success) {
                       //干你自己想干的事吧
                        }
                      })
                    },
                    fail: function (error) {
                      that.src1 = 'http://p9s9revyo.bkt.clouddn.com/HumanFace.png'
                    }
                  });
            });
          },
    
    展开全文
  • 在上一篇文章中本人讲述了微信公众号的授权以及获取用户信息,在此基础上今天这篇博客跟大家分享一下微信支付的流程及代码,还有自己在开发时的一些坑。1、在进行微信支付时,除了需要一个公众号之外,你还需要一个...
  • 调用授权地址 设置 window.location.href = ...redirect_uri="+ urlcode+"&response_type=code&scope=snsapi_userinfo&state...
  • 搭建vue前端框架或微信小程序vue框架步骤 1.下载node.js 下载地址:https://nodejs.org/en/download/ 查看node、npm版本,确保环境正确 node --version npm --version 2.安装vue脚手架工具vue-cli 若开发工具为...
  • 基于Vue2.5.6+Vuex+vue-cli+vue-router+vue-gemini-scrollbar+swiper+elementUI等技术混合架构开发的仿微信web端聊天室——vueWebChat,实现了发送消息、表情(动图),图片、视频预览,右键菜单、截屏、截图可直接...
  • 微信公众号开发,主要是移动端网页的页面开发,在这里推荐3个移动端UI框架:WeUI、SUI和Mint UI
  • 手机端程序可以和企业微信进行整合,我们也可以使用企业微信JSSDK功能,实现一些原生的功能。 整合步骤 在整合之前需要阅读 整合步骤。 http://work.weixin.qq.com/api/doc#10029 1.引入JSSDK npm i -S ...
  • 现在把本次开发过程中遇到的问题以及我是如何解决的,做个记录。防止自己以后再去解决解决过的问题。 一、微信网页授权   网页授权流程分为四步,这里只说前端需要做的,其中的第一步:跳转授权页面获取code。 ...
  • 1、在进行微信开发之前你 首先你得需要一个微信公众号(具体的申请步骤省略)2、进行微信开发的开发配置(我这里是配置一个测试账号后面的微信支付还是要走微信公众号 配置是一样的)URL为微信开发正确响应发送...
  • vue写的一个微信公众号菜单配置 框架 vue + elementUI + mockjs
  • 作为国内主流的三大mv类框架vue的主要优势在于其轻量和上手快。除此以外,她还有很多比其他两大框架要好的地方,比如可读性更强的语法和更好的数据绑定方式。可能是因为她出生比较晚,有更多的机会去借鉴和吸收吧...
  • 需求微信授权登录(基于公众号的登录方案)接入JS-SDK实现图片上传,分享等功能现状及难点采用的Vue框架,前后端分离模式(vue工程仅作为客户端),用户通过域名访问的是客户端,但是微信授权中涉及签名和token校验...
  • 起手式:必要的开发环境 工欲善其事必先利其器!在开始写代码之前,请确保你已经安装了必要的开发环境和工具,以下是几个必需的和可选的工具: 1)node.js 现在,前端工具链基本都依赖Node.js,所以请率先安装它吧。...
  • 简介:微信小程序是一种全新的连接用户与服务的方式。那么怎样才能快速开发一个小程序呢?下面小编为大家介绍几款小程序快速开发框架。WePY腾讯官方开源的小程序组件化开发框架,目前有1.4w+Star ,一直在更新着,...
  • 采用bootstrap开发的一组微信公众号界面,采用VUE动态绑定数据。界面美观,并且可以兼容各种版本。
  • 老板要求写一个微信公众号页面,采用uni-app框架,不多介绍,自己去搜搜 以前没有仔细做过微信支付,现在终于把整个流程顺下来了,特此写一个文档,也希望对其他人有点帮助 首先: npm install jweixin-module -...
1 2 3 4 5 ... 20
收藏数 12,777
精华内容 5,110
关键字:

微信开发vue框架