网站建设投标人资质,最有效的网站推广方案,网站的集约化建设,广东省建筑信息网查询系统计算属性
使用场景
如果一个结果需要依赖data中的数据#xff0c;但是需要经过一些逻辑处理#xff0c;才能得到你想要的数据。此时就可以使用计算属性。
例如#xff1a;要对给定的字符串做翻转处理之后再来显示。
div idapp!-- 此处逻辑复杂 …计算属性
使用场景
如果一个结果需要依赖data中的数据但是需要经过一些逻辑处理才能得到你想要的数据。此时就可以使用计算属性。
例如要对给定的字符串做翻转处理之后再来显示。
div idapp!-- 此处逻辑复杂 --h3{{msg.split().reverse().join()}}/h3/divscript src./vue.js/scriptscriptconst vm new Vue({el: #app,data: {msg: javascript}})/script定义格式
在vue实例中补充computed配置项。
new Vue({// 声明计算属性computed: {//属性名字计算属性名称//属性的值计算属性处理函数计算属性名1 () {// 对依赖的数据进行处理且进行returnreturn }计算属性名2 () {// 对依赖的数据进行处理且进行returnreturn }}
})computed 是vue的配置选项它的值是一个对象其中可定义多个计算属性每个计算属性就是一个函数。
属性名称 计算属性的名称属性的值计算属性的素材函数 对需要依赖的数据进行逻辑上的处理处理完毕后需要return出去返回的值就是计算属性的值
使用格式
在两个地方使用
模板 用插值表达式 {{计算属性名}}用其它指令 在实例内 this.计算属性名
示例
颠倒字符串 div idapp!-- 逻辑复杂 --h3{{msg.split().reverse().join()}}/h3!-- 计算属性 和data类似--h3{{reverseMsg}}/h3/divscript src./vue.js/scriptscriptconst vm new Vue({el: #app,data: {msg: hi vue},// 声明计算属性computed: {//属性名字计算属性名称//属性的值计算属性处理函数reverseMsg () {// 对依赖的数据进行处理且进行returnreturn this.msg.split().reverse().join()}}})/script在模板中使用计算属性和使用data的方式是一样的。 虽然在计算属性中声明的是函数但是在模板中使用当中数据来使用不需要加括号。
总结 什么时间用需要对数据进行复杂的逻辑加工产生新的数据时。 定义 就是一个特殊的配置项computed。其中有多个函数。 使用计算属性的使用方式与data中的数据项一致 计算属性-计算这个值是对原数据进行计算之后得到的新的数据计算属性-属性它的使用方法与原数据一样。this.计算属性名,{{计算属性名}} 执行的时机 如果计算属性中依赖的数据项变化时它会自动调用。
computed有缓存
问
当我们在模板中来显示一份经过对数据项进行复杂计算之后的结果时我们有两种解决方案
计算属性函数
应该如何选择
答 methods定义函数如果在模板中使用每使用一次就相当于调用了一次处理逻辑会重新执行。 computed定义计算属性如果在模板中使用使用多次但是如果依赖的数据不发生改变计算属性对应的函数不会重新执行。 计算属性会做缓存提高渲染的性能。
示例
div idapph3学习计算属性/h3p计算属性{{ reversedMsg }}/pp计算属性{{ reversedMsg }}/pp计算属性{{ reversedMsg }}/phrp函数{{fReversedMsg()}}/pp函数{{fReversedMsg()}}/pp函数{{fReversedMsg()}}/p/div
script srchttps://cdn.jsdelivr.net/npm/vue/dist/vue.js/scriptscript// 计算属性的特点缓存// - 如果计算属性所依赖的数据项并没有发生变化则就算使用多个计算函数其函数也只执行一次// 因为它把结果缓存起来了。const vm new Vue({el: #app,data: {msg: javascript},methods: {fReversedMsg () {console.log( 函数 fReversedMsg )//把msg的翻转一下let newMsg this.msg.split().reverse().join()return newMsg}},computed: {reversedMsg () {console.log( reversedMsg )//把msg的翻转一下let newMsg this.msg.split().reverse().join()return newMsg}}})// setTimeout (function() {vm.msg abc// 由于计算属性有缓存虽然在页面上用到三次但它的函数体只执行一次。// 对于普通的函数在页面上用到了三次它就会执行三次},2000)
/script总结
计算属性有缓存提高渲染性能。如果在页面上需要用到 对现有的数据进行加工得到新数据则时要使用计算属性
案例-资产列表(续)
目标 计算总资产计算属性 根据输入的内容筛选符合条件的资产计算属性 筛选
思路
- 给筛选输入框添加双向绑定
- 添加一个计算属性根据输入框的内空对list进行筛选
- 把计算属性的值显示在表格中求和
思路
补充一个计算属性对cList进行循环求出它的price的和
代码
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlelink hrefhttps://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css relstylesheetstyle.red {color:red}/style
/head
bodydiv idappdiv classcontainerdiv classform-groupdiv classinput-group!-- 使用自定义指令来让input自动获取焦点 .trim 去掉空格--input v-focus v-model.trimkey typetext classform-control placeholder搜索/div/divtable classtable table-bordered table-hovertheadtrth编号/thth资产名称/thth价格/thth操作/th/tr/theadtbody!-- tr v-for(循环变量索引变量) in 数据在计算属性的基础上进行循环 --tr v-for(item,idx) in cListtd{{item.id}}/tdtd{{item.name}}/td!-- 如果价格超过100就有red这个类 --!-- td classred{{item.price}}/td --!-- 三元--!-- td :classitem.price 100 ? red : {{item.price}}/td --!-- :class 放一个对象如果对象中的属性值是true,则把对象中的属性名添加到类名中--!-- 过滤器把12345 12,345 1. 在前面加一个2. 千分位的分隔加,--!-- td :class{red:item.price100}{{item.price | currency}}/td --td :class{red:item.price100}{{item.price | $}}/tdtda href# click.preventhDel(idx)删除/a/td/tr/tbodytfoottr!-- colspan合并单元格把4列合成一个 --td colspan4共计:{{cTotal | $}}/td/tr/tfoot/table!-- 添加资产 --form classform-inlinediv classform-groupdiv classinput-groupinput v-model.trimname typetext classform-control placeholder资产名称/div/divnbsp;nbsp;nbsp;nbsp;div classform-groupdiv classinput-groupinput v-model.trim.numberprice typetext classform-control placeholder价格/div/divnbsp;nbsp;nbsp;nbsp;!-- 阻止表单提交 --button classbtn btn-primary click.preventhAdd添加资产/button/form/div/div!-- script srchttps://cdn.bootcdn.net/ajax/libs/vue/1.0.11/vue.js/script --script srchttps://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.js/scriptscript// 目标 用vue.js实现// 1. 把表格数据显示出来// 2. 实现删除功能// 3. 添加功能// 4. 标注如果价格超过100标红色显示。// 步骤// 1.引入vue.js// 2. 实例化vue对象 // 三大件 el,data,methods// 3. 实现功能// (1) 循环渲染数据 v-for// (2) 删除数据click,并传入要删除的下标// (3) 标注红色 动态的添加样式只有100才加。 使用对象来绑定class.// (4) 添加功能// 1) 基本输入框结构// 2) 点击添加// - 收集用户的输入信息:v-model,补一些必要的修饰符。// - 简单判空// - 添加到list中// (5) 计算总和// 补充一个计算属性在其中对list进行循环算出总共的price// (6) 筛选功能// 在筛选区域的input框中输入关键字则在下面的list中找出对应的项,其它项应该要隐藏起来// - 给input添加v-model,收集用户需要的关键字// - 定义一个计算属性根据关键字来在list中进行数据的过滤找出符合关键字要求的项const vm new Vue({el: #app,data: {name: , // 名称price: 0, // 价格list: [{ id: 1, name: 外套, price: 199 },{ id: 2, name: 裤子, price: 34 },{ id: 3, name: 鞋, price: 25.4 },{ id: 4, name: 头发, price: 19900 },{ id: 5, name: 梳子, price: 899 }],key: // 搜索关键字},computed: {cList () {if(this.key ) {return this.list}// 这个计算属性依赖于 key 和list,只有一个变化则它会重新执行// 如果视图上没有用计算属性那么这个依赖项变化时计算属性不会执行console.log(cList,Date.now())// 根据this.key对list进行过滤// 对于this.list中的每一项如果其中name包含 this.key关键字则保留let newList this.list.filter(item {// 如果其中name包含 this.key关键字if(item.name.includes( this.key )) {return true} else {return false}})// console.log( newList )return newList},// 由于添加了筛选功能则要对整个的计算属性cList中数据进行循环计算出 总共的pricecTotal: function() {// 这个计算属性依赖于另一个计算属性 cList// 当cList 变化时这个计算属性也会重新执行let totalPrice 0this.cList.forEach(item {totalPrice totalPrice item.price})return totalPrice.toFixed(2)}},methods: {hDel (index) {console.log(要删除的下标是,index)// 删除数组中指定位置的元素this.list.splice(index, 1)},hAdd () {// 收集用户的输入信息// 简单判空if(this.name ) {return }if(this.price || this.price 0) {return }// 添加到list中console.log(this.name,this.price)// 向数组中添加一个元素let id 1if (this.list.length 0) {// 新的id 数组中最后一个元素的id值1id this.list[this.list.length-1].id 1}this.list.push({id: id,name: this.name,price: this.price})}},filters: {// 定义过滤器// 过滤器的名字就是$$: function (value, _currency) {// 正则表达式 全局匹配 三个连续的且之后也是数值的 数值var digitsRE /(\d{3})(?\d)/g;value parseFloat(value);// 判断是否数值if (!isFinite(value) || !value value ! 0) return ;// 设置金额的符号_currency _currency ! null ? _currency : ;// 取绝对值保存两位有效数字转成字符串var stringified Math.abs(value).toFixed(2);// 获取整数部分。 -3 表示倒数3位var _int stringified.slice(0, -3);// 整数部分以3为基准长度划分剩下几位var i _int.length % 3;// 取出头部// 12345 --- 12,var head i 0 ? _int.slice(0, i) (_int.length 3 ? , : ) : ;// 取出小数字部分var _float stringified.slice(-3);// 判断符号var sign value 0 ? - : ;// 整体输出return _currency sign head _int.slice(i).replace(digitsRE, $1,) _float;}// $: function(value) {// // 1. 在前面加一个// // 2. 千分位的分隔加, // // 有难度与vue,与过滤器没有关系。请大家自己在下面做练习。 // // 我们这里直接去vue的源码中抄一段出来直接用。// // 在Vue1.0版本中它是自带这个货币金额过滤器// console.log(value)// return value// }},directives: {focus: {inserted (el) {el.focus()}}}})// list: [// { id: 1, name: 外套, price: 99 },// { id: 2, name: 裤子, price: 34 },// { id: 3, name: 鞋, price: 25.4 },// { id: 4, name: 头发, price: 19900 }// ]/script
/body
/htmlcomputed: {cList () {if(this.key) {return this.list.filter(it it.name.includes(this.key))}else {return this.list}},cTotal () {return this.cList.reduce((total,it){ return totalit.price*1}, 0)}
},自已写接口
在开发过程中经常会遇到后端接口滞后的情况前端页面写完了后端的接口没有就绪此时我们就可以先准备接口。
前后端分离开发
代码层的分离
代码上的分离前后端是同一个项目开发目录上的区分项目级的分离前端是一个单独的项目后台是一个单独的项目
开发的内容的分离
后端负责业务逻辑写接口前端负责业面交互调接口。 我们的理解必须后台先提供接口前端才能进行开发。 分离的意义前后端可以并行开发。 收到任务前端后端一起制定接口规则形成接口文档接口名功能参数返回值…并行开发 后端开发接口接口1接口2…前端写页面调用接口(自己按第2步的接口文档要求写真的假接口)
json-server 前端自己写接口可以用nodejs自己写也可以借助第三方现成的工具json-server json-server快速地根据json文件生成接口 json ----json-server----- 接口 在后端接口没有交付之前使用json-server快速创建模拟接口推进前端开发进程。
在后端接口实现之后再切换回去。
使用步骤
全局安装json-server
它是依赖于nodejs的第三方包。需要全局安装不需要初始化。
npm i json-server -g# 安装完成
C:\Users\fanyoufu\AppData\Roaming\npm\json-server - C:\Users\fanyoufu\AppData\Roaming\npm\node_modules\json-server\lib\cli\bin.jsjson-server0.16.1
updated 1 package in 12.418s
##只需要安装一次就行了。
准备空文件夹
在任意目录下准备一个空文件夹取名mock-server(可改成其它名字) 创建json文件
在文件夹中新建一个名为db.json文件(可改其它名称注意名字是是英文 初始化结构
在db.json文件中按json格式的要求去定义一个对象
键值对格式用双引号括起来
{assets: [{ id: 1, name: 外套, price: 99 },{ id: 2, name: 裤子, price: 34 },{ id: 3, name: 鞋,price: 25.4 },{ id: 4, name: 头发, price: 19900 }]
}启动接口服务
根据上面创建的db.json自动地生成接口。
在此文件夹下打开命令行窗口输入命令json-server db.json (json-server后有空格) 如果没有错误则运行结果如下
测试
在浏览器中访问上面地址 注意
json格式。属性名 — 接口的地址属性值 — 接口返回数据 数组|对象
原理图 RESTful接口
json-server提供的接口是符合RESTful接口规范的。 在写接口时每个程序员都有自己的写法:取不同的名字例如实现添加资产 A同学 localhost:3000/addAsset | delAsset B同学 localhost:3000/insertAsset | deleteAsset C同学 localhost:3000/tjzj | sczj 针对上述问题提出一套约定 RESTful接口的规范是通过 请求方式来决定操作类别添加删除修改查询用名词来表示要操作的目标 以上面启动的服务为例
接口地址请求方式操作类型/assetsGET获取全部数据/assets/1GET获取单个数据/assetsPOST添加操作 {name,price}/assets/1DELETE删除操作/assets/1PUT完整修改{name,price}/assets/1PATCH局部修改{name}
以上接口规则就是restful规则。json-server提供的就是符合restful规则的接口。
postman测试
使用postmant来测试json-server提供的接口。
获取全部数据
GET: http://localhost:3000/assets 获取单个数据
以id为查询依据
GET: http://localhost:3000/assets/1 根据条件查询数据
json-server服务器提供了条件查询的功能
格式: ? 字段**_like**值 不可以加引号
添加操作
以json格式传递参数id会自动增加。
POST:http://localhost:3000/assets/
{name: 电脑, price: 6880} 另一个操作示例 删除操作
以id为查询依据
DELETE: http://localhost:3000/assets/1
完整修改
以json格式传递参数
PUT: http://localhost:3000/assets/3
要求必须传入一个完整的对象如果这一条记录中有100个属性则要传入100个属性因为它会整体覆盖这条数据。
局部修改
以json格式传递参数
PATCH: http://localhost:3000/assets/3
只需要传入要更改的字段要修改哪个属性就传入哪个属性 。
axios调用接口
我们发ajax请求接口有如下方式
原生的。纯手写。XMLHttpRequest…$.ajax()。jquery中的ajaxaxios。它是一个专业的只发ajax请求的工具。它可以在nodejs中和浏览器使用。
下载并使用
axios是一个js工具要想使用就要先下载。
http://www.axios-js.com/docs/
axios提交数据的时候默认的数据类型content-type是 application/json
下载地址https://unpkg.com/axios/dist/axios.min.js
格式
完整写法
axios({// 请求方式 get|post|put|patch|delete 大小写不区分method: get,// 路径上传参在url后进行拼接url: http://localhost:3000/brands/1,// ?后键值对传参params: {},// 请求体传参data: {},// 请求头传参headers: {}
}).then(res{console.log(成功)
}).catch(err{console.log(失败)
})简写格式
对于比较简单接口调用可以采用简写格式
格式
axios.请求方式url, .......).then().catch()
示例
// get类型的 参数要放在写params中
axios.get(url,params: {}).then(res{console.log(成功)})
.catch(err{console.log(失败)
})
// post类型 直接写参数
axios.post(url,{}).then(res{console.log(成功)})
.catch(err{console.log(失败)
})示例
通过json-server启动接口服务器然后再写axios代码来进行调用测试
查询 // 1. 查询// 所有// axios.get(http://localhost:3000/assets).then(res{// // res是响应对象 // res.data是后台响应内容数据// console.log(res.data)// })// // 单个// axios.get(http://localhost:3000/assets/2).then(res{// // res是响应对象 // res.data是后台响应内容数据// console.log(res.data)// })// 筛选条件查询// 方式1自己手动在地址栏?后进行拼接// 方式2针对get传参?后键值对传参固定传参方式 {params:{//传参对象 }}axios.get(http://localhost:3000/assets,{params:{name_like:奥}}).then(res{// res是响应对象 // res.data是后台响应内容数据console.log(res.data)})添加 // 2. 添加// 除去get请求外函数的第二个参数都是请求体传参是对象类型。axios.post(http://localhost:3000/assets,{name:宝马,price:500000}).then(res{console.log(成功)})删除 // 3. 删除axios.delete(http://localhost:3000/assets/2).then(res{console.log(成功)})修改 // 4. 修改 完整// axios.put(http://localhost:3000/assets/3,{name:长安奔奔,price:36000}).then(res{// console.log(成功)// })// 5. 修改 局部axios.patch(http://localhost:3000/assets/3,{name:奔奔}).then(res{console.log(成功)})总结不同方式的参数怎么传递给后台。
案例-资产列表-接口版
目标 用json-server启动后端接口服务器 axios发请求 用vue管理视图
渲染列表
目标用axios请求json-server提供的接口并显示数据出来。
准备静态页面
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlelink relstylesheet href./bootstrap.min.css
/headbodydiv idappdiv classcontainer!-- 搜索 --form classform-inline stylepadding: 20px 0input typetext classform-control placeholder输入关键字进行搜索/form!-- 表格 --table classtable table-bordered table-hovertheadtrth编号/thth资产名称/thth创建时间/thth操作/th/tr/theadtbodytrtd1/tdtdxxx/tdtdxxxx/tdtda href#删除/a/td/tr/tbody/table!-- 添加资产 --form classform-inlineinput typetext classform-control placeholder资产名称nbsp;nbsp;nbsp;nbsp;button classbtn btn-primary添加资产/button/form/div/div
/body/html创建vue实例实现列表渲染
实现渲染列表大致步骤
在data配置项中声明一个列表数据list先设置一些假数据。在模板当中根据list和数据中的字符段进行渲染 使用v-for指令注意处理无数据的情况。
vue实例如下
script src./vue.js/script
script src./axios.min.js/script
scriptconst vm new Vue({el: #app,data: {// 资产列表数据list: [{id:1,name:t,price:1}]}})
/script对应模板如下
tbodytr v-foritem in list :keyitem.idtd{{item.id}}/tdtd{{item.name}}/tdtd{{item.price}}/tdtda href#删除/a/td/trtr v-iflist.length0td colspan4 styletext-align: center;暂无数据/td/tr
/tbody发ajax请求取回真数据
现在一切就绪只需在某个时间点向后台接口发请求拿回数据给list重新赋值即可 以前window.onload function(){} 默认渲染页面加载完成之后 或者$(function(){}) 默认渲染页面文章加载完成之后 在vue中需要默认渲染vue实例初始化完毕后发请求获取数据进行渲染。 vue提供一个配置选项created类型是函数实例化后执行的函数。 script src./vue.js/scriptscript src./axios.min.js/scriptscriptconst vm new Vue({el: #app,data: {// 资产列表数据list: []},created () {// vue实例后执行回调函数钩子函数在某个时机会被调用的函数。this.get()},methods: {// 获取列表数据get() {axios.get(http://localhost:3000/assets).then(res {this.list res.data})this.name }}})/script总结一般在created函数中获取页面需要的初始化数据。
删除资产
目标点击页面上的删除按钮把对应的数据删除掉。
步骤 给a标签绑定点击事件注意阻止默认行为 定义处理函数给函数传入资产ID 在函数中 弹出确认框提示 点击确认框之后发删除请求 如果成功之后更新列表移除删除的行
tda click.preventhDel(item.id) href#删除/a/td// 删除资产函数
hDel(id) {if (confirm(你确定要删除 id)) {axios.delete(http://localhost:3000/assets/ id).then(res {this.get()})}
},添加资产
目标在点击页面上的添加时可以实现添加新资产的功能
步骤
双向数据绑定输入资产的表单元素绑定表单的提交事件阻止默认行为在methods中定义一个事件函数在函数中 组织需要提交给后台的数据{name,price}id后台不需要自动自增。提交数据前对name进行校验发起添加请求如果成功重新获取后台列表数据即可。之前输入的内容清空
在案例中落地的代码
!-- 添加资产 --
form classform-inlinediv classform-groupdiv classinput-groupinput typetext v-model.trimname classform-control placeholder资产名称/div/divnbsp;nbsp;nbsp;nbsp;div classform-groupdiv classinput-groupinput typetext v-model.numberprice classform-control placeholder价格/div/divnbsp;nbsp;nbsp;nbsp;button classbtn btn-primary click.preventhAdd添加/button
/formdata: {list: [],name: ,price: 0,
},// 添加资产函数
hAdd() {if (!this.name) {return}if (!this.price) {return}axios.post(http://localhost:3000/assets, {name: this.name,price: this.price,}).then(res {this.get()})this.name
}