整合营销服务商

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

免费咨询热线:

税友股份取得数据交互方法专利,HTML程序可确保摆脱HTTP服务的束缚,以使HTML能够更好地在本地程序中进行应用

融界2024年7月9日消息,天眼查知识产权信息显示,税友软件集团股份有限公司取得一项名为“一种数据交互方法、系统、电子设备及存储介质“,授权公告号CN113010237B,申请日期为2021年3月。

专利摘要显示,本发明公开了一种数据交互方法,包括:HTML程序利用HTML容器提供的服务接口生成本地资源获取请求,并通过HTML容器的容器进程将本地资源获取请求发送至本地服务容器;本地服务容器利用本地服务容器中包含的业务服务对接收到的本地资源获取请求进行处理,得到相应的本地资源数据,并将本地资源数据发送至HTML容器;HTML容器接收本地资源数据,并将本地资源数据发送至HTML程序;本方法中的HTML程序可直接使用HTML容器及本地服务容器进行本地资源获取,可确保HTML程序摆脱HTTP服务的束缚,以使HTML能够更好地在本地程序中进行应用;本发明还提供数据交互系统、电子设备及存储介质,具有上述有益效果。

本文源自金融界

本系列上一篇文章分析了数据交互基础面试题,详见连接:Web前端面试题剖析:数据交互

本次为大家解读中高级数据交互问题。

中级

REST Web Services

在REST应用中,默认通过HTTP协议,并且使用GET、POST、PUT和DELETE方法对资源进行操作,这样的设计风格和Web标准完全契合。

REST的最佳应用场景是公开服务,使用HTTP并遵循REST原则的Web服务,我们称之为RESTful Web Service。RESTful Web Service从以下三个方面进行资源定义:

  • 直观简短的资源地址:URI,比如:http://example.com/resources/
  • 传输的资源:Web Service接受与返回的互联网媒体类型,比如JSON,XML等
  • 对资源的操作:Web Service在该资源上所支持的一系列请求方法(比如:GET,POST,PUT或Delete)

下图展示了RESTful Web Service的执行流程

中间层:

在 Node.js 中,你可以使用 http-proxy 完成一些简单的代理请求的服务,当然也可以使用具有更多功能的 express-gateway。

在第一个 API Gateway 示例中,我们在其代理请求到真实的服务之前,先进行权限认证。

const express = require('express')

const httpProxy = require('express-http-proxy')

const app = express()

const userServiceProxy = httpProxy('https://user-service')

// Authentication

app.use((req, res, next) => {

// TODO: my authentication logic

next()

})

// Proxy request

app.get('/users/:userId', (req, res, next) => {

userServiceProxy(req, res, next)

})

另一种方式是由 API Gateway 向微服务发送请求,再将响应回馈给客户端:

const express = require('express')

const request = require('request-promise-native')

const app = express()

// Resolve: GET /users/me

app.get('/users/me', async (req, res) => {

const userId = req.session.userId

const uri = `https://user-service/users/${userId}`

const user = await request(uri)

res.json(user)

})

总结:

API Gateway 提供了一个中间层来协调客户端和微服务架构。它有助于帮助我们完成单一职责原则,让我们的应用或者服务持续的关注一件事。你可以将通用逻辑放入 API Gateway 中,但是也应该注意不要过度的使用 API Gateway。

高级

前后端分离架构

原创不易,欢迎关注、转发、点赞。

命是有周期的,比如一个人的生老病死便是他的生命周期;一个公司和企业也是拥有周期的,从创立,稳定,发展,到上市;本章节我们主要学习vue的生命周期以及vue中的数据交互。对于vue来说它只是一段执行的代码,为什么拥有周期呢?通过本章节的学习你会拥有答案。并且本章节中的第二部分内容也是很重要的,叫做数据交互,也就是如何使前端和后端进行数据的传递,这里读者应该想起ajax技术,vue中提供了Axios技术来替换ajax完成数据交互。

3.1 Vue生命周期

在vue官网中针对生命周期提供了一张图片来展示周期内的不同阶段,并且配文:“你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。”但是仍然建议你对生命周期充分理解,避免将来在学习和编程过程中踩坑。

3.1.1 Vue生命周期概述

学习Vue的生命周期之前,我们先做一个小的思考,人的一生有不同的阶段,大概分为出生,婴儿,儿童,少年,青年,老年,到最终生命的消亡。每个人都会按照固定的顺序经历不同的阶段,并且会在不同的阶段做不同的事情。这些固定顺序的阶段就组成了一个人的生命周期,那生命周期有什么用呢?比如一个人要结婚,这个事情正常来说肯定是要发生在一个人的青年或者中年阶段,那如果发生在儿童阶段,那就乱套了。总结来说一个人的生命周期可以保证这个人在正确的阶段做正确的事情。

那么我们在回到Vue本身,回顾第一章我们学习过的Vue实例的创建代码。

Var app = new Vue({

el: "#app",

data: {

msg: "hello world" }

})

我们知道每个Vue应用都是从Vue实例的初始化开始的。Vue 实例在被创建时都要经过一系列的过程,比如创建、数据初始化、挂载、更新、销毁等,这就是一个Vue所谓的生命周期。Vue在经历不同的过程时会调用不同的函数,我们将这些函数叫做生命周期钩子函数,或者生命周期函数。

总结来说,一个Vue实例拥有生命周期,这些生命周期会顺序执行,在经历不同的过程时会自动调用生命周期函数。开发者可以将自己的业务逻辑代码编写在不同的生命周期函数内,这样就是可以实现在Vue实例不同的过程中执行不同的代码。

这里先列出所有的钩子函数,然后我们再一一详解:

  • beforeCreate 创建前状态
  • created 创建完毕状态
  • beforeMount 挂载前状态
  • mounted 挂载结束状态
  • beforeUpdate 更新前状态
  • updated 更新完成状态
  • beforeDestroy 销毁前状态
  • destroyed 销毁完成状态

我们先创建本章节的第一个案例,此案例中包含钩子函数的代码编写方式,注意运行时打开控制台查看日志,console中输出的结果可以帮助我们了解生命周期钩子函数。创建index.html,代码内容如3-1所示。

例3-1 index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>vue生命周期</title>
  8. <script src="vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <h1>{{message}}</h1>
  13. </div>
  14. </body>
  15. <script>
  16. var vm = new Vue({
  17. el: '#app',
  18. data: {
  19. message: '学习Vue生命周期'
  20. },
  21. beforeCreate: function() {
  22. console.group('------beforeCreate创建前状态------');
  23. console.log(this.$el); //undefined
  24. console.log(this.$data); //undefined
  25. console.log(this.message)
  26. },
  27. created: function() {
  28. console.group('------created创建完毕状态------');
  29. console.log(this.$el); //undefined
  30. console.log(this.$data); //已被初始化
  31. console.log(this.message); //已被初始化
  32. },
  33. beforeMount: function() {
  34. console.group('------beforeMount挂载前状态------');
  35. console.log( (this.$el)); //已被初始化
  36. console.log(this.$data); //已被初始化
  37. console.log(this.message); //已被初始化
  38. },
  39. mounted: function() {
  40. console.group('------mounted 挂载结束状态------');
  41. console.log(this.$el); //已被初始化

  42. console.log( this.$data); //已被初始化
  43. console.log( this.message); //已被初始化
  44. },
  45. beforeUpdate: function () {
  46. console.group('------beforeUpdate 更新前状态------');
  47. console.log( this.$el);

  48. console.log(this.$data);
  49. console.log(this.message);
  50. },
  51. updated: function () {
  52. console.group('------updated 更新完成状态------');
  53. console.log( this.$el);

  54. console.log( this.$data);
  55. console.log(this.message);
  56. },
  57. beforeDestroy: function () {
  58. console.group('------beforeDestroy 销毁前状态------');
  59. console.log( this.$el);

  60. console.log(this.$data);
  61. console.log(this.message);
  62. },
  63. destroyed: function () {
  64. console.group(------'destroyed 销毁完成状态------');
  65. console.log(this.$el);

  66. console.log(this.$data);
  67. console.log(this.message)
  68. }
  69. })
  70. </script>

运行index.html,有些读者对vscode的使用可能不是特别熟悉,这里说一下简要的步骤:1点击菜单栏中的运行;2点击启动调试;3选择运行环境,比如谷歌浏览器,如果没有谷歌浏览器可以配置自己本机的浏览器环境。

运行结果如图3.1所示。

图3.1 运行结果

代码解释:

我们拿其中的beforeCreate的钩子函数进行讲解,钩子函数书写在vue实例的初始化选项中,属性名为钩子函数名称,属性值为函数,函数会在钩子函数的对应生命周期被自动调用执行。

beforeCreate: function() {

console.group('------beforeCreate创建前状态------');

console.log(this.$el); //undefined

console.log(this.$data); //undefined

console.log(this.message)

}

其中this.$el,this.$data,this.message分别在不同的生命周期用于获取当前Vue实例的el选项,data选项,message数值,通过控制台我们可以探究他们分别在什么阶段有值,我们会在各个钩子函数详细讲解中进行学习。

通过运行结果我们可以看到钩子函数执行的顺序为:beforeCreate,created,beforeMount,mounted,也说明了在vue实例创建过程中,按照顺序经历了,实例创建之前,实例创建成功后,挂载之前,挂载完成后。这些函数要求开发者按照案例3.1中的形式书写,执行是由Vue在经历不同的生命周期时自动调用的。

有同学可能会问,为什么没有执行其他的几个钩子函数,比如beforeDestroy,destroyed等。这个问题其实很好回答,从字面意思分析一下这些钩子函数。拿destroyed来说,destroyed表示销毁,也就是说这个函数只会在实例销毁时才会执行,实例没有经历销毁的过程,所以也不会执行对应的钩子函数。

Vue完整的生命周期以及钩子函数如图3.2所示。

图3.2 Vue生命周期

3.1.2 准备阶段

准备阶段开始创建Vue实例,我们结合图片分析此阶段发生了什么事情,如图3.3所示。

图3.3 开始阶段

  • new Vue({}) :开始创建vue实例。
  • Init events&Lifecycle:此时vue实例只有默认的一些生命周期和 默认的事件,此时的data,methods,el等等都不存在,还没有初始 化数据。
  • beforeCreate():beforeCreate钩子函数在此时自动运行。

beforeCreate: function() {

console.group('------beforeCreate创建前状态------');

console.log(this.$el); //undefined

console.log(this.$data); //undefined

console.log(this.message)

}

create表示创建,beforeCreate也就是创建之前,值得注意的是,这里并不是表示在Vue实例初始化之前,而是在实例开始初始化之后,但是实例未完全创建之前。此时实例的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data等选项。对应的运行结果中可以看到此时获取实例对象的el,data,message选项都是undefined:

------beforeCreate创建前状态------

undefined

undefined

undefined

3.1.3 初始化数据阶段

初始化数据阶段进行了Vue实例的中选项的初始化,比如el,data,methods等但是还未编译模板。如图3.4所示。

图3.4 初始化阶段

  • init injections&reactivity:这个阶段的vue实例不再是空壳了,在它内部已经初始 化了数据和事件,包括data和methods,但是还没编译模板。
  • created:钩子函数运行,此时你可以使用created钩子函数获取到vue中初始化的数据,在这里是你最早可以获取到数据的地方,更改数据不会触发update和其他钩子函数。一般在这个钩子函数中进行初始化数据的获取。

created: function() {

console.group('------created创建完毕状态------');

console.log(this.$el); //undefined

console.log(this.$data); //已被初始化

console.log(this.message); //已被初始化

},

通过控制台的打印我们可以看出,此时data和message可以获取其值,但是el还是undefined,el指定的就是我们的模板,也就是说此时还未编译模板。created对应的运行结果如下:

------created创建完毕状态------

undefined

{message: <accessor>, __ob__: Observer}

学习Vue生命周期

3.1.4 编译模板阶段

从creatd()钩子函数到beforeMount钩子函数之间称之为编译模板阶段,此时模板编译成功,生成了一个编译好的模板字符串,在内存中将这个模板字符串渲染为内存中的DOM,但是还在内存中,没有挂载到页面中。具体流程如图3.5所示。

图3.5 编译模板阶段

  • Has “el” option:编译阶段会首先判断Vue实例的选项中是否存在el选项,所以要求我们的初始化代码中一定要执行el选项,此选项是用于执行html中模板的位置。
  • Compile el’s outerHTML as template:将el选项指定的html标签编译成模板,字符串,并且保存在内存中。
  • beforeMount:是位于编译模板阶段的钩子函数,在这里可以进行一般数据的获取和更改,同 created() 函数一样更改数据不会触发update和其他钩子函数,这个阶段是在内存中生成了虚拟DOM还没有挂载到页面中!

beforeMount: function() {

console.group('------beforeMount挂载前状态------');

console.log( (this.$el)); //已被初始化

console.log(this.$data); //已被初始化

console.log(this.message); //已被初始化

},

beforeMount对应的运行结果我们可以看出,此时vue实现的内部选项已经初始化完毕,可以分别获取el和data的值。但是值得注意的是在beforeMount钩子函数找那个并不是能对页面中的元素进行修改,原因是beforeMount()钩子函数是触发在编译阶段的,此时还没搭载到页面上,就无法对页面上的元素和内容进行修改。

------beforeMount挂载前状态------

div#app

{message: <accessor>, __ob__: Observer}

学习Vue生命周期

3.1.5 挂载页面阶段

上一个阶段是编译阶段,在内存中生成的是虚拟的DOM,还没挂载到页面上,编译阶段还不能操作页面上的dom元素。编译模板阶段之后就是挂载阶段,此时在内存中的虚拟DOM挂载到了浏览器的页面上,我们可以操作页面上的DOM元素了!此阶段的流程如图3.6所示。

图3.6 挂在页面阶段

  • Create vm.$el and repacle “el” with it :渲染真实DOM,说白了就是我们用的模板语法被真实的数据替换了比如html中的{{msg}}被替换了真实的数据。
  • mount:编译、挂载后执行的钩子函数。此时的实例已经被完全创建出来,并且可以操作页面中的dom元素。

mounted: function() {

console.group('------mounted 挂载结束状态------');

console.log(this.$el); //已被初始化


console.log( this.$data); //已被初始化

console.log( this.message); //已被初始化

},

对应的日志输出:

-------mounted 挂载结束状态-----

div#app

{message: <accessor>, __ob__: Observer}

学习Vue生命周期

3.1.6 运行阶段

在mounted()钩子函数之后,vue实例已经创建完毕了,这个运行阶段有两个钩子函数,只有当data中的数据发生改变时,才会触发。也就是beforeUpdate和updated。此阶段的流程如图3.7所示。

图3.7 运行阶段

  • beforeUpdate:组件更新之前执行的钩子函数;当vue发现data中的数据发生了改变,会触发对应组件的重新渲染,先后调用beforeUpdate和updated钩子函数。
  • update:组件重新渲染后调用。

我们发现例3.1中并没有执行此阶段的两个钩子函数,原因是我们例3.1中并未涉及到数据的改变,那么我们接下来创建index2.html来演示beforeUpdate和update函数的执行。代码如例3-2所示:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>vue生命周期</title>
  8. <script src="vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <h3 id="h3">{{ msg }}</h3>
  13. <input type="button" value="点击" @click="show">
  14. </div>

  15. </body>
  16. <script>

  17. var vm=new Vue({
  18. el:"#app",
  19. data:{
  20. msg:"你好"
  21. },
  22. methods:{
  23. show:function () {
  24. this.msg="hello";
  25. console.log(this.msg);
  26. }
  27. },
  28. beforeUpdate(){
  29. console.log("msg"+document.getElementById('h3').innerText);
  30. console.log("更改之后的msg"+this.msg);
  31. }
  32. })
  33. </script>
  34. </html>

运行结果:

当我们点击按钮之后,会执行methods中的show函数,在show函数中将data中的msg的值进行了变更,此时就会触发beforeUpdate函数,在beforeUpdate中通过dom元素获取的数据还是修改之前msg的值,直接通过msg属性获取的值是修改之后的数据,证明了此时beforeUpdate执行在数据修改之前。

3.1.7 销毁阶段

当用户关闭整个页面或者执行了某些$destroy时,就会从运行阶段进入销毁阶段此阶段的流程如图3.8所示。

图3.8 销毁阶段

beforeDestroy :销毁前执行的钩子函数,可以继续使用vue实例中的数据,如data, methods,filters,derictives等等。

destroyed : 已经销毁了,vue实例中的数据不可用了。

3.2 Axios数据交互

本小节我们学习Axios数据交互。我们都知道动态网站的数据都是存在于服务器的数据库中,那么对于完整的项目来说一般需要涉及到前端和后端的数据交互才能够实现将后端的数据展示在前端的页面上,没有学习Axios之前我们会采用原生的ajax或者jquery提供的封装来完成数据交互。在Vue中我们更加建议使用Axios来替代原生ajax和jQuery封装来实现数据交互。

3.2.1 Axios简介

首先我们来看一下关键的自我介绍:“Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。”我们需要复习一些名词和常识。

  • promise :ECMAscript 6 原生提供了 Promise 对象,用来传递异步操作的消息。也就是说Axios 是es6中的新语法。
  • HTTP 库 :进行http协议的网络请求处理的代码库。
  • node.js :简单的说 Node.js 就是运行在服务端的 JavaScript,不是本书中讨论的重点,作为了解。

总结来说Axios是es6中提供的语法,通过promise实现对ajax技术的一种封装,就像jQuery实现ajax封装一样。ajax技术也实现了网页的局部数据刷新,axios实现了对ajax的封装。这里我们做一下代码上的对比。

Axios语法:

axios({

url: '/getUsers',

method: 'get',

responseType: 'json', // 默认的

data: {

“name”: ‘aaa’,

“id”:1

}

}).then(function (response) {

console.log(response);

console.log(response.data);

}).catch(function (error) {

console.log(error);

})

jquery封装ajax语法:

$.ajax({

url: '/getUsers',

type: 'get',

dataType: 'json',

data: {

“name”: ‘aaa’,

“id”:1

},

success: function (response) {

console.log(response);

}

})

从语法来说axios和jQuery的封装代码结构上的区别并不大,那么我们为什么要使用Axios呢,我们来做一下两种方式特点的对比。

ajax特点:

  • 本身是针对MVC的编程,不符合现在前端MVVM的浪潮
  • 基于原生的XHR开发,XHR本身的架构不清晰,es6中已经有了fetch的替代方案
  • JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理。

axios特点:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应 (就是有interceptor)
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

可能大家对interceptor(拦截器)并不是很熟悉,在这里作下介绍,拦截器可以在请求发送前和发送请求后做一些处理。有一张图可以清晰的了解它在一次HTTP请求中做了什么,如下图3.9所示。

图3.9 拦截器

3.2.2 Axios安装

了解过Axios之后,我们开始学习Axios的使用,第一步就是需要进行安装,也就是在自己的应用中引入Axios环境。这里有三种方式进行安装,读者可以自行选择自己了解的方式,他们的导入分别如下。

使用 npm执行命令:

$ npm install axios

使用 bower工具:

$ bower install axios

使用 csdn:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

3.2.3 Axios的使用

Axios的使用并不复杂,代码中重要部分是指定请求方式,请求路径,请求参数,相应处理等,听到这里是不是觉得axios使用流程上和jQuery封装的ajax操作十分类似,确实是这样,只是使用的对象和方法属性不同而已,接下来我们直接通过代码来学习Axios的基本使用。代码如例3-3所示。

例3-3 index3.html

  1. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  2. <script>

  3. //基本用法
  4. //可以通过向 axios 传递相关配置来创建请求
  5. //axios(config) 基于promise的api ,所以在then方法中接收数据
  6. axios({
  7. method: 'post',
  8. url: '/url',
  9. data: {
  10. firstName: 'Fred',
  11. lastName: 'Flintstone'
  12. }
  13. }).then(res=>console.log(res));
  14. </script>

3.3 本章小结

  • Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
  • Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。
  • MVC表示“模型-视图-控制器”,MVP表示“模型-视图-演示者”,MVVM表示“模型-视图-视图模型”。
  • 使用双大括号来包裹 js 代码构成插值表达式,用于将双大括号中的数据替换成对应属性值进行展示,插值表达式中可以写入JSON数字,字符串,数字,js表达式。
  • 遇到复杂逻辑时建议使用Vue特带的计算属性computed来进行处理,在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果。
  • 侦听器用于当数据发生变化时,及时做出响应处理,当需要在数据变化时执行异步或开销较大的操作时

3.4 理论习题与实践练

1.思考题

1.1 请简述vue的优点。

1.2 请简述vue和jQuery的区别。

1.3 请简述vue起步的操作流程。

1.4 请简述什么是MVC,MVVM?

2.编程题

  • 2.1 回顾vue起步的操作流程,独自完成vue环境搭建,并要求练习使用到插值,属性计算以及侦听器。