首页 > 其他分享 >一种简单的视图层数据查询模块数据流--视图、路由、API

一种简单的视图层数据查询模块数据流--视图、路由、API

时间:2022-10-20 16:58:57浏览次数:42  
标签:-- 视图 API 参数 query 数据 路由

背景简介

实现前台项目的搜索页时,通常会将查询参数直接传给路由并显示在顶部的地址。

params 参数可以路径的一部分,因此可以理解;不过保留 query 的目的暂不清楚,对 SSR 模式有用,但 SPA 模式大多还是通过 AJAX 发送请求。一个可能的猜测是页面刷新时,路径不会改变,因此可以保留传递的参数。此外,路由传参也是全局通信方式的一种,可以按需使用。

数据分层

此类场景下,数据通常分为 3 层(实际的变量定义可能不会分得这么清楚):

  • 视图:由框架维护的数据,通常用于存储需要显示到视图上的输出类数据或从视图获取的用户输入类数据,任何开发模式下都会有该类数据
  • 路由:路由参数,包括 params 和 query
  • API:访问 API 时传入的参数,也就是与后端交互所需的数据

一般地,维护视图数据和 API 参数就够用了。

数量流向维护过程

以下过程按照数据的流向并以时间先后分为:

  • 初始化阶段:页面第一次加载时,初始化查询参数,由业务组件向服务端发送第一次请求;拿到数据后,渲染到视图中
  • 数据交互阶段:基于用户操作,修改本地数据
  • 查询阶段:基于修改后的本地数据,在用户只需特定操作时,修改当前路由地址(修改查询参数);同时,修改 API 参数并重新发送请求;之后,重新将服务端响应的数据渲染到视图中

第二、三阶段可能在用户的同一个交互行为下依次触发,比如:用户点击分类选择器组件,修改本地数据后,立刻修改 API 参数并发送请求,并不需要用户点击查询按钮。

根据以上过程,可画出以下的数据流向图:

对于一般的请求,从数据层到 API 层直接走上图中的虚线部分;而当需要维护路由参数时,则走实线部分。

以下是根据上图整理的具体执行过程:

发送请求:

  • 视图层到数据层:由于 vue 的双向绑定机制的存在,两层间的部分数据通信会自动执行,如表单输入等;而对于点击、选择等交互行为,可能需要绑定专门的事件处理器。
  • 数据层到路由层:从数据层拿到数据,整理成 paramsquery 对象,并通过 push() 方法推入路由器对象(router)。
  • 路由层到 API 层:通过 watch 侦听路由对象(route)变化,自动将 paramsquery 对象整理成 API 所需的参数,并调用相应 API 。

接收响应(与一般的请求处理过程相同):

  • API 层到数据层:接收数据后传给本地数据变量。此处不经过路由层。
  • 数据层到视图层:双向绑定或单向绑定到视图

代码示例

以下过程实际是通过函数/方法处理的,视图层、数据层和路由层本身只负责存储或展示数据,API 层由组件的函数/方法调用。

示例根据上述数据流向和过程,分为几大部分:

  1. 在请求的回调中将返回的数据保存为本地数据。这部分比较常规,不过多赘述。
  2. 通过事件绑定,将用户输入转为本地数据,并调用路由参数处理函数/方法 handleQueryChanged(newQuery) 。同上,不多赘述。
  3. 根据最新输入,转换为路由对象的 paramsquery 属性(可以为空),并通过 push() 方法传给 router 对象
  4. watch 侦听 $route,自动调用 API 参数处理函数/方法,完成后调用相应的 API

刷新后,由于 watch 的存在,保存 API 参数信息的变量会自动更新,若这些变量被绑定到视图,则视图也会同步更新,也就达到了刷新后维持之前状态的效果。

绑定事件处理器

新增或修改数据

handleDataUpdated(newData) {
  // 更新本地参数,并调用路由参数处理方法
  this.someData = newData; // 对象或数组在 vue2 中需要通过 this.$set 赋值来保留响应性
  handleQueryChanged(newQuery);
  
  // 若将作为 API 参数的变量绑定到视图,则可以直接将新的数据作为 query 的属性
  // 后续在 handleQueryChanged 方法内部,调用 API 参数处理方法后,视图也会自动更新
  handleQueryChanged({ queryKey: newData });
}

删除数据

handleDataUpdated(newData) {
  // 一般类型的参数直接置空
  this.data = ''; // 或者 0 undefined 等
  // 或者已将作为 API 参数的变量绑定到视图,则可以直接给 query 一个空值属性,跳过本地数据的置空动作
  handleQueryChanged({ queryKey: '' });
  
  // 对象或数组通过 this.$set ,将特定位置或属性的值置空
  let props = [].concat(this.$route.query.props);
  props.splice(attrId, 1);
  handleQueryChanged({ props: props.length > 0 ? props : null });
}

值为空的 query 参数不会显示在路径中。当然,也可以选择将需要置空的属性直接删除。

处理路由参数

// 此处仅处理了 query 的变化;params 同理,将特殊处理添加到合并语句之前即可
handleQueryChanged(newQuery) {
  let location = { name: 'RouteComponentName' };
  // 获取路由更新前的参数副本
  let oldParams = this.$route.params,
    oldQuery = Object.assign({}, this.$route.query);
  
  ... // 其他特殊处理
  
  // 新的 query 如果提供空的属性值,则将 oldQuery 对象中的该属性置空,如:query = { keyword: '' }
  for (const key in newQuery) {
    if (Object.hasOwnProperty.call(newQuery, key) && !newQuery[key]) {
      oldQuery[key] = undefined;
    }
  }
  
  ... // 其他特殊处理
  
  // 将新 query 对象中新增的属性合并到原 query 对象;同名属性会被覆盖为新值
  newQuery = Object.assign(oldQuery, newQuery);
  // 重新添加路由参数
  if (!isEmpty(oldParams)) location.params = oldParams;
  if (!isEmpty(newQuery)) location.query = newQuery;
  this.$router.push(location);
},

处理 API 参数

setupSearchParams(route) {
  const params = route.params,
    query = route.query;
  this.searchParams = Object.assign(
    this.searchParams,
    {
      ... // 属性值初始化;这种方式初始化时,参数变量始终带有所有属性,只是部分属性可能为空,值为 undefined 的参数不会被添加到请求中
    },
    params,
    query
  );
},

侦听路由对象

watch: {
  $route: {
    immediate: true,
    handler(newRoute) {
      this.setupSearchParams(newRoute);
      this.fetchSearchResult(this.searchParams);
    },
  },
},

标签:--,视图,API,参数,query,数据,路由
From: https://www.cnblogs.com/cjc-0313/p/16810460.html

相关文章

  • python第十九课--
    昨日内容回顾包的实际应用内部含有__init__.py文件的文件夹如果直接导入包名其实导入的是内部的__init__.py文件,所以包名点的方式其实是跟__init__.py文件要名字......
  • 管理配置Ansible
    管理配置Ansible目录管理配置AnsibleAnsible清单定义清单清单的位置使用静态清单指定受管主机验证清单构建Ansible清单自定义清单文件管理Ansible配置文件配置Ansible配置......
  • 前端Vue2-Day54
    ToDoList案例:组件间通信:父组件给子组件传参:父组件绑定值至子标签,子组件利用props接收。子组件给父组件传参:父组件绑定函数至子标签,子组件props接收函数,并设置methods进......
  • Js:当前日期格式化与比较大小
    //日期格式转换getCurrentTime(){vardate=newDate();//当前时间varyear=date.getFullYear()//返......
  • Delphi 客户端调用WebService
    客户程序:第一步:新建一个Application。第二步:File----->New----->Other------>WebServices----->WSDLimporter第三步:   生成了一个新的接口定义单元  Wsdl ......
  • vue3:vue+nginx+php进行服务端部署的配置(nginx/1.18.0 / [email protected])
    一,开发环境中的配置:1,前端:vue的vue.config.jsconst{defineConfig}=require('@vue/cli-service')module.exports=defineConfig({transpileDependencies:t......
  • SOLIDWORKS如何快速填写焊件切割清单属性
    SOLIDWORKS的焊件功能大家都很熟悉,而且还能够直接生成焊件切割清单,但美中不足的是,如果每种焊件需要编代号的话,就只能一种一种的去添加。今天给大家介绍的这款SOLIDWORKS插......
  • 实验5:开源控制器实践——POX
    (一)基本要求:1.搭建下图所示SDN拓扑,协议使用OpenFlow1.0,控制器使用部署于本地的POX(默认监听6633端口)1)生成拓扑:sudomn--topo=single,3--mac--controller=remote,ip......
  • hdfs测试(文件上传,内容读取,文件删除)
    工具:idea2021配置:hadoop2.6.0项目:Maven项目 首先编辑pom.xml(Maven项目的核心文件)文件,添加如下内容,导入依赖(所需jar包)(注意hadoop版本号)<?xmlversion="1.0"encod......
  • HTML标签-文本标签1和HTML标签-文本标签2
    HTML标签-文本标签1文本标签:和文本有关的标签注释:<!-- 注释内容 --><h1>to<h6>:标题标签h1~h6:字体大小逐渐递减<p>:段落标签<br>:换行标签<hr>:......