首页

掌握这20条用户体验设计原则,助力设计成长!

鹤鹤

文章整理了20条用户体验设计原则,希望通过这份简洁易懂的合集能够让你对用户体验领域有一个初步的概览和了解。

1.以用户为中心 

这是最常被提及的用户体验设计基础,当涉及到产品设计决策时,提醒我们要学会使用同理心,而不是仅凭个人的想法或意见。

真正好的用户体验设计是为用户量身打造的,用户的意见、痛点、愿望、偏好和需求对产品来说至关重要,所以在项目初始阶段需要投入大量的时间和精力去了解用户。

用户体验研究重点是了解用户,为接下来的产品设计做准备。以用户为中心的设计理念是设计师迎合用户的需求,区分了设计任何人都可以使用的产品和为目标用户设计的产品。


一款特定的产品需要面对不同的目标群体,前期研究中需要了解目标人群需要什么并在产品中反映出来,这是针对性很强的设计研究。 


2.了解信息架构

可能很多人对信息架构的定义很模糊,这里举个例子来具象说明一下信息架构的含义。

例如在一款产品中,如果把所有内容都堆到一个列表或页面中,可能我们将无法使用这款产品,所以我们看到大多数的App和网站都包含很多的导航和页面结构,按照内容重要程度有序地来组织内容。

信息体系结构的最终目标是帮助用户理解他们在看什么,并帮助他们找到需要寻找的内容。

信息架构在制作线框图或原型之前完成,因为它是产品的基础,有助于设计师考虑什么功能是最重要的,哪些是用户最需要的以及哪些次要内容可以隐藏起来等。

这种结构与产品的导航设计密切相关,有助于将用户引导到正确的位置。导航和信息架构都试图让用户以最少的认知努力来完成操作。


信息架构的设计不当会造成重大故障甚至可能危及整个产品。如果用户在使用产品时找不到任何想要的内容,点击任何元素都没有反应,会给用户带来很糟糕的使用体验。 


3.考虑使用场景

没有场景,任何设计都很难生效。设计师在项目开始时会投入时间去了解用户面临的问题以及围绕这些问题的背景。


这条原则有助于设计师考虑还有哪些因素会影响用户和产品,很多产品设计会为用户提供一些有助于消除使用摩擦的操作提示。 
例如在设计表单时,会尽可能的添加 输入提示,最大程度地减少用户出错的机会。 


4.了解一致性及其重要性

保持一致性是用户体验设计的关键原则。拥有一致设计的产品可以更快地被新用户接受,因为用户不需要再次学习如何操作,他们会回忆起之前的操作习惯并将其作为指导,这也解释了为什么同类型的产品例如电商类App页面设计的很相似。

保持一致意味着在需要时可以重复使用某些UI组件,并在整个产品中保持一致的行为。例如当点击或悬停在按钮上面时,所以按钮的状态应该是一致的。


从逻辑上讲,产品越大,这种一致性会变得越来越有挑战性,这促使许多设计团队创建自己的设计系统。一款产品的学习曲线越长越陡,放弃的用户就会越多,在市场营销中,这通常被称为销售漏斗中的漏洞。 


5.给予用户适当的控制权

这条原则意味着用户希望能控制产品,无论是完成任务还是定制满足他们需求的内容。

在设计过程中一直试图给用户尽可能多的控制权,例如允许用户撤消操作、更改设置、自定义UI外观、创建快捷方式等中。


需要注意的是,当提供太多选项或用户太依赖于自己的选择时,用户可能会不知所措,造成所谓的 选择悖论。所以在设计时要了解用户乐于掌控的余地,不能让用户感到使用压力。 


6.把可用性放在首位

在整体上看,建立高标准的可用性是为用户做的最好的事情,有助于检查用户是否能够轻松地完成任务、产品是否正常运行以及是否完成工作。


可用性的重要之处在于要理解可用性的灵活性和重要性。 


7.了解用户测试

结合可用性的概念,我们还要进行用户测试,这是设计师对工作进行测试的方式,对新的产品来说至关重要。

当设计思想和理念被转化为有形的原型时,设计师要观察真实的用户是如何与之交互的,可以通过许多不同的方式例如简单的A/B测试到全面的审核测试等来实现。


测试通常分几轮进行,团队在向原型添加更多细节之前验证每个步骤。随着测试结果的出现,设计也随之发生了变化。 
如果发生更改,将会进行新一轮的测试,通过这个过程,设计团队可以改进他们的工作,直到达到可用性标准。 


8.少即是多

在创造力和创造独特事物的渴望中,很多设计师很容易无意中弄乱产品界面甚至产品本身。

功能过多的产品可能会失去焦点并削弱吸引力。具有太多元素的页面会变得充满视觉冲击,但也会给用户带来负面体验,在设计时要学会克制并优先考虑真正关键的部分很重要。


另外手机端的屏幕空间非常小,创建一个有效的布局,想出巧妙的方法来隐藏次要元素并创建一个令人愉悦的界面需要付出很大的努力和创造力。 


9.视觉层次

视觉层次是向用户传达产品中元素重要性的方式。良好的层次结构有助于用户视线在界面上移动,并立即了解最重要的内容以及这些内容与其他部分的关系。

视觉层次结构与布局设计紧密相连,帮助用户消化所接触到的信息。


创建层次结构从概念的草图开始,一直持续到完成设计。例如发送按钮通常会用绿色而是不红色,而次要按钮会显示为灰色或与背景混合,并显示“撤消”或“返回”。 


10.了解用户的心智模型

为用户创建心智模型是尝试使用同理心的一种方式,是帮助设计师从用户的角度看待问题的工具。

正确使用意味着用户无需投入精力就可以使用的直观产品,而错误的思维模型会导致一些问题,例如界面混乱、高昂的交互成本。


为了匹配用户的心智模型,可以采用多种不同类型的研究方法,常见的方法包括 卡片分类、决策树、对用户行为的密切观察,或者使用大量的数据来建立关键用户的心理模型。 


11.设计中的讲故事

讲故事的方式更加直观,利用图像、视频、动画和文本等元素让整个页面与用户对话。用户体验设计中的视觉叙事是为了唤起用户的情感,给用户留下持久的印象。


想出一种可视化的方式来传达复杂的内容具有挑战性,但同时也是有益的,可以更好地接近用户并将其作为提高产品可学习性的方法。 


12.不要直接跳到高保真原型上

高保真原型是设计项目的最终目标,但是直接使用原型软件不断添加各种页面细节是错误的操作。


避免直接出高保真的主要原因是因为这样做的成本会更高。在没有任何用户研究和测试的情况下,一款产品无论具有多少的细节都有可能面临不符合用户使用的情况。 


13.可访问性测试很重要

不仅要检查关键用户是否可以流畅地使用产品,还应该检查其他所有用户例如少数群体等是否都能够正常使用产品。


事实上,残疾人和其他用户一样需要数字产品,但很多产品在设计时并没有考虑到这些群体,但这也提供了一个机会,为所有用户提供一个可以依赖的好产品。 


14.熟悉并在用户体验设计中使用

我们知道为用户提供一致的设计有助于克服学习曲线,同时为用户提供熟悉的东西也有助于缩短学习曲线。

例如,大多数用户都会立即识别某些UI组件(汉堡菜单/单选按钮),这意味着他们会本能地知道这些组件代表什么意思或者如何操作。

使用用户已经熟悉的东西并不一定会让产品的独特性消失,有经验的设计师会利用这种熟悉性来来创造一些独特的设计,同时也是直观的,不需要太多努力就可以使用。


设计一个完全不依赖熟悉度的产品可能是具有风险的行为,因为它很容易让那些不熟悉产品的用户超负荷,形成巨大的学习曲线,增加用户负担。 


15.了解交付成果的力量

可交付成果是可以在整个团队中交付的内容,包括用户画像、心智模型、用户旅程以及线框图和原型等,是一种有形和具体的表现。

可交付成果是用户体验设计原则,可以帮助设计团队和其他利益相关者理解和交流概念。

▲ 用户画像可以捕捉理想用户,并提供可以相关联的真实面孔,是一种指导设计的工具。用户旅程图帮助设计师了解用户完成任务需要的具体步骤,有助于确保这些步骤确实可以轻松执行,并且整个过程很流畅。


这些交付成果服务于关键功能,设计师需要在整个项目中都依赖它们,不断转换为用户可以与之交互的真实有形的设计。 


16.专业的原型设计工具

用户体验设计的过程不是线性的,而是一个循环。无论创建什么样的产品,都需要专业的原型工具,将基本框架放在一起,然后添加可能需要的所有细节。


从逻辑上讲,设计团队的具体需求会因团队而异,但一些关键功能例如团队协作、需求管理、交互设计和开发移交等,对于大多数团队来说是必要的。 


17.精心管理产品需求

一切都从收集需求开始,然后慢慢创建关键列表。虽然简单地列出一个列表听起来很容易,但随着项目的进展,要保持列表的条理性确实是一个挑战。


除了创建需求和检查复选框之外,还有一个问题就是调整需求,需要从 设计、技术和业务各个方面来处理各种需求,还要确保这些需求之间没有相互矛盾。  


18.了解移动和网络产品之间的差异

网页端和移动端产品最明显的区别是屏幕尺寸,这意味着所有的视觉层次结构和信息架构都将将从Web到App发生变化。


移动端产品会有更多影响设计决策的因素,例如设备的操作系统、使用产品的环境等。了解移动端产品在 导航设计、用户流程等关键方面的差异是至关重要的用户体验设计原则。 


19.利用UX设计模式

几乎所有的产品都专注于设计模式,它们可靠、易于查找并通过减少设计时间来为项目增加实用性。


▲ 当用户在谷歌搜索中输入的内容有问题时,谷歌会提供一个相关的搜索提示,辅助用户进行精确地搜索,解决用户使用不同方式在搜索栏中传达他们正在寻找的内容的问题。 


20.使用合适的工具才能有效

拥有单一的内容来源可以为团队带来清晰性和高效性,如果线框和原型分散在多个渠道中,这种内容的集合就会变得很难达成。


通过合适高效的工具能够避免产品在到达终点时遇到各种各样的可用性问题,防止产品细节没有表现出来或者被忽略。 


最后

通过这份用户体验设计原则的合集希望能够让你对这个领域有一个大致的了解。

没有人知道用户体验设计在未来会引领我们走向哪里,不过我们可以确定,无论它带给我们什么,肯定都会很有趣

慢慢来比较快,希望对你有所帮助~

文章来源:站酷  作者:Clippp
分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

腾讯公益小红花火爆全网,背后的设计思维是什么?

鹤鹤

今年是腾讯发起99公益日的第七个年头。腾讯公益不仅在配捐机制、产品体系、企业联动、公益基础建设上全面升级,还连接数亿网友、近万家慈善组织和爱心企业,为全民公益交出一张漂亮的成绩单:

数据显示,小红花互动人次超1.25亿,送小红花、答公益题目等行为公益实现破圈传播,亿万爱心网友共同领取了超9000万朵助力小红花,共计有超过6870万人次在99公益日期间捐出35.69亿元,加上腾讯公益慈善基金会的6亿元资金支持,共募得善款41.69亿元。

99 公益日为何能实现破圈传播,作为腾讯公益日和 99 公益日的品牌符号,小红花的设计背后又传达了怎样的思考?今天就来聊聊小红花那些事。



2015年9月9日,腾讯公益联合国内数百家公益组织、知名企业共同发起了中国第一个互联网公益日。

为了让用户了解互联网公益的核心特色与参与方式,让更多的人参与到互联网公益中,第一届 99 公益日的活动主题定调为“一起爱”,在logo的设计中也借用了“无限”符号表示“爱无止境”的含义。


在前三年的 99 公益日中,募款额度得到了广度上的增长,在用户已经了解到互联网公益低门槛、多形式、透明度、可记录的特点之后,如何留住用户,对互联网公益形成日常习惯和持久投入,就成为了设计亟需解决的问题。

“小红花”是腾讯公益平台在2018年给出的答案。因为小红花作为国人的集体回忆,关联着你我儿时从老师那里收获到的鼓励。每一朵小红花背后,是我们完成的一件“好事”。

延续小红花的记忆线索进行延展,在公益中,小红花是对用户的捐赠给予的最大肯定,是受助者正在发生的改变。在传播上,小红花是记录用户每一次公益行为的符号,通过「戴小红花,一块做好事」而得到成就感的有效激励。

于是,2018年99公益日的主视觉上,无数的爱心化为花瓣,汇聚成一朵小红花,这是小红花在腾讯公益平台的初次绽放。



为了让品牌有延续性,加深用户对小红花和99公益日的认知,小红花作为核心品牌元素开始贯穿在每一年99公益日的主视觉中,并通过不同的画面故事表达每一年的主题。

比如,2018年的主题是积小善,成大爱,于是在设计中,让很多爱心小花汇聚在一起,让小的爱心变成大爱;2019年的主题是一块做好事,通过每个人的善意汇聚成小红花……



在2019年,“小红花”正式成为腾讯公益与99公益日的品牌符号。



从2020年开始,小红花开始发力于传播,联动外部品牌 IP 如QQ、微信、Bilibili、狐妖小红娘等开启推广,在各种不同的场景,诠释“一块做好事”的内涵。

这一年,小红花之歌火了,同名神曲MV播放量超1亿次;在线下,小红花也开到喜茶等连锁品牌的店里。

而2021年,属于用户独特的小红花爱心账户上线了,用户在腾讯公益平台做好事打卡,向好友发起集小红花的自发传播,从而争取更大的配捐额,在增强用户捐款积极性的同时,撬动更多用户了解并参与到活动中来。


小红花爱心账户


用户还可将积累的小红花兑换周边礼品。在推广上则从创作入手,发起共绘小红花的活动。



可以说,小红花串联起了用户从感知、到行动、到反馈的全流程,保证了用户参与互联网公益的动机和动力。

在预热推广阶段,腾讯公益推出一支小红花为主角的宣传片,试图为小红花是什么,做出来自官方的定义。

不管是线上线下征集用户绘制的小红花,“每个人的小红花”画展,还是在感恩日随证书送出的小红花画作,都让用户全方位地感受到腾讯公益小红花的“玩法”,也为小红花元素赋予了丰富的内涵。

征集到的部分小红花作品


寄出公益荣誉证书


爱心用户的开箱视频


99公益日期间,小红花与腾讯新闻、微保、腾讯视频、腾讯会议等多产品的玩法联动,让小红花开遍“地球村”。


多款产品联动一块做好事


而在线下,小红花也伴随系列广告,落地在线上下,IP联盟、异业合作、核心城市灯光投影秀等,让小红花无处不在。


部分城市地标灯光投影秀


最后,小红花这一品牌形象的成功,不仅在公益设计这一领域上有借鉴的意义,在品牌IP的设计上同样有值得学习的地方。

文章来源:站酷  作者:零弟小武
分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

为什么越简单的设计越说不出理由

鹤鹤

常见场景


设计师日常工作中,经常遇见的那些显而易见的设计逻辑,却难以给出设计理由的情况到底指的是什么呢?


以我自己近期的工作为例,不妨为大家举个简单的例子:


下图是一个补贴规则的设置流程,在用户未设置补贴规则之前,明确告知用户还未设置补贴规则,当用户设置了补贴规则后,可以对补贴规则进行修改。



我认为这是一个非常简单且合理的页面路径跳转,并且在很多现有的产品中都有类似这样的逻辑存在。然而在与上下游同学对接的过程中,却遇到了不同的意见:有人认为没有必要区分用户是否设置了规则,用户未设置规则可以直接展示系统默认的补贴条件和补贴范围,如果用户认为不合理,自行修改便是。

不知道大家看到这里是什么感觉,我在听到「方案二」时的反应是:能够理解却并不认同,说不出来哪里不对,就是觉得这事它不应该这样。


以上,就是在我工作中发生的一次非常具体的案例。


直觉真的不如推理靠谱吗?


那么为什么我会产生“感觉哪里不对,却又说不出为什么”的强烈感受呢?


最直接的原因是,这样的设计方案(方案一)是用直觉做出来的,缺少了对方案本身的思考。


直觉,指的是那些没有经过分析推理的观点,因此常常给人一种不靠谱的感觉。


可是有时候我们依赖「直觉」做事真的就完全不靠谱吗?带着这样的疑惑,我去查阅了一些相关的资料来辅助我更好理解这种直觉性思考,恰好找到了一个真实的实验案例:


1997年,Bechara, Antoine et在一个赌博游戏实验中发现:「直觉」比「意识」更能指引正常人做出有利的的选择。

该实验先后邀请了10名正常人和6名前额叶损伤的决策缺陷患者,以探究人们做出正确选择是在对相关知识进行推理之前还是之后。在游戏开始前,工作人员给予每位参与者2000美金、发放4副牌,要求参与者在游戏过程中翻出100张卡片,并尽可能的多赢钱,但他们不会告知参与者每副牌中的卡片价值:从A、B两副牌中翻出正常的卡片能赚100美金,C、D两副牌中的正常卡片值50美金,同时每副牌中也隐藏着罚款,A、B两副牌中的罚款比C、D两副牌的罚款重,参与者很可能会输光所有的钱。

实验结果显示:正常人在意识到哪副牌赢面更大之前就开始选择有利的卡牌,而决策缺陷患者即使知道了正确的策略,却仍然继续选择对自己不利的卡牌。


根据上述实验,我们起码能发现直觉未见得不可靠,也就是说,凭借直觉出的设计方案,并不意味着不是一个正确的方案


可是在日常沟通协作的过程中,「直觉设计」一旦遇到不同的意见,就会缺少理论支撑。决策者无法判断设计师的直觉是否可靠,从而觉得方案本身也不可靠。


遇到这种看似「死胡同」的情况,我们应该怎么去思考呢?


很简单,直觉在前,策略性推理在后


乔纳森•海特(Jonathan Haidt),著名社会心理学家,在《正义之心》中有提到:


判断和论证是两个相互分离的过程,直觉与推理的关系就像大象与骑象人,骑象人(推理)骑在大象(直觉)上,骑象人不断发展以服务于大象。


拿上述的方案来说,当我面对这类的质疑时,我也会有愣住,但我知道我不能惊慌,而是该让骑象人(推理)表演了。


其实仔细分析一下上述案例就会发现,方案一和方案二最本质的区别在于:


是否需要区分用户(商家)自行设置过「补贴规则 」?


百度百科对规则的定义是:


规则,一般指由群众共同制定、公认或由代表人统一制定并通过的,由群体里的所有成员一起遵守的条例和章程。


规则本身是属于利益相关者之间的约定。按照这个逻辑,「补贴规则」可以理解为用户(商家)与消费者形成的基本约定


用户(商家)未设置规则,如果系统直接展示默认的补贴条件和补贴范围,就会给用户(商家)一种平台借以商家的名义与消费者形成了约定的印象,这与现实不符,甚至可能给用户(商家)的业务带来不必要的纷争。因此,区分用户是否设置过补贴规则是非常有必要的。


为什么要为自己的设计辩护?


在上述场景中,虽然我的直觉先于理性给我发送了信号,但设计师如果光依靠直觉却给不出任何说明,同样会带来一系列麻烦。


汤姆·格里弗(Tom Greever)在一篇文章提到,伟大的设计往往取决于你怎么说


描述设计不是一件容易的事情,但每个设计师都不得不向很多没有设计经验的人讲述自己的设计,并且要让他们信服自己是对的,这群人很可能是方案的决策者。决策者通常会选择那个听上去最合理的方案,所以方案的表述对于最终方案的确立至关重要。


普通设计师和顶级设计师之间的差距不仅仅是他们解决问题的能力,还在于他们能否用一种让人心服口服、并促使人们同意的方式来阐述他们是怎么解决问题的。理论上,最好的设计应该胜出,然而事实并非如此,设计评审很容易变成设计批判会,每个人都在告诉设计师要怎么设计。


最终,那些能够说服别人“我是对的”的人会胜出。设计师如果没有办法说服别人为什么他们要这么做,就不得不按照他们不同意的方式去修改设计,原因仅仅是因为他们没有办法简要的为自己的设计辩护


听起来似乎这些决策有失公允,甚至成了设计师的辩护大会,那么对于一些有着出色能力却不善言辞的设计师而言,就真的没有任何方法了吗?


如何突破直觉,能言善辩?


设计师要想守卫自己的设计,就要警惕那些单凭设计直觉做出来的方案。


设计直觉的形成与个人经历、阅读经历相关。遇到相似的问题,设计师如果有这方面的经验固然是好的,直接复用之前的做法可以大大提升设计效率。但我们完成设计后,最好想想哪些地方存在路径依赖,以确保自己的方案能经得住质疑。


一个最实用的可以判断自己的设计方案,是不是由直觉得来的,就是多向自己提问


同样,我们来用实际的案例做个说明:


想想下图中「智能上传」「更多操作」按钮放在表格的左下方行不行?


很明显不行,但重点是支持这么做不行的理由是什么?


如果你的理由是:


“别的页面是将按钮放在了列表左上角的”

“放在左下角不好看呀”

“没见过有产品这么放啊”

“......”


那这个方案就是直觉设计的产物了。


想要突破直觉设计,设计师需要尽可能在每个设计点上多思考几步,比如:


为什么别的页面会将按钮放在左上角?


根据2006年NNGroup 在眼动实验中的发现,人们在网络中的阅读成F型,即用户进入页面中的第一眼,通常会落在页面的左上角,也就是说左上方的区域是页面的黄金区。「智能上传」「更多操作」属于页面的核心操作,那么放在列表左上方是非常合理的。


此外,我们可以看到页面的翻页器是可以筛选列表展示的条数,假设用户设置的条数,超出了屏幕显示范围,也就意味用户进入到页面会看不到操作选项,所以按钮放在表格的左下方也是不合理的。


为什么别的页面按钮放在左上角这个页面也要这么做?


因为我们需要保障产品的一致性,产品的核心操作方式保持一致,可以有效地降低用户的学习成本,避免不必要的思考。


总结


在设计协作的过程中,设计师不可避免地会接收到来自四面八方的声音,而我自己也曾在设计沟通中陷入过类似困境,因此我越发明白只有清晰地表述出自己的设计思考,才可能赢得每个人的支持。


  • 凭借直觉出的设计方案,并不意味着不是一个正确的方案。

  • 直觉在前,策略性推理在后。

  • 顶尖的设计师,也是顶尖的交流者。

  • 要想守卫自己的设计,就要警惕那些单凭设计直觉做出来的方案。

  • 多向自己提问,以确保自己的方案能经得住质疑。


以上是关于这篇文章的关键思考总结,回到设计师个体而言,我认为我们需要对直觉设计保持警惕,因为看似简单的设计背后往往蕴含着复杂的设计原理,而一个好的设计师除了拥有过硬的设计能力,强大的设计思考力和表达能力以外,我相信同样在跨学科的研究和学习上会远强于普通设计师,否则根本无法支撑起背后的设计思考。

文章来源:站酷  作者:范思蜀
分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


js_防抖与节流(闭包的使用)

前端达人

js的防抖与节流

防抖事件

定义:持续触发事件,一定时间内没有触发事件,事件处理函数只会执行一次,
当设定的时间内触发过一次事件后会重新开始延时。
例:输入框的事件(2s显示内容,不是实时刷新显示内容),对比输入框的内容事件。
实时刷新的效果

 <div class="container"> <div class="left"> <p>实时刷新显示内容</p> <input type="text" id="leftInput" /> <div class='textDiv' id="textShow"></div> </div> <div class="right"></div> </div> <script> var inputDom=document.getElementById('leftInput'); inputDom.addEventListener('keyup',function(e){ var textDom=document.getElementById('textShow'); console.log(e.target.value); textDom.innerText=e.target.value; }) </script>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

输入123456会依次打印123456的金字塔
在这里插入图片描述

防抖(1s内显示输入内容)

 <div class="container"> <div class="left"> <p>防抖(1s内显示输入内容)</p> <input type="text" id="leftInput" /> <div class='textDiv' id="textShow"></div> </div> <div class="right"></div> </div> <script> // 防抖 var inputDom = document.getElementById('leftInput'); // 函数柯里化 function debounce(delay, callback) { let timer return function(value) { //闭包内存泄漏 clearTimeout(timer) timer = setTimeout(function() { //执行 callback(value) }, delay) } } // 显示内容的函数 function showText(value) { var textDom = document.getElementById('textShow'); console.log(value) textDom.innerText = value; } var debounceFunc = debounce(1000, showText); inputDom.addEventListener('keyup', function(e) { let value = e.target.value debounceFunc(value) }) </script>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

1s内输入123456只会打印一次123456
在这里插入图片描述

节流事件

定义:一段时间直只调用一次事件处理函数
实际用例:提交事件 、游戏的技能cd(在游戏cd中点击n次都不会发动技能)

// 节流
            var skillDom = document.getElementById('skillTriger');
            function throttle(wait,callback) {
                let timeOut;
                return function(value) {
                    if (!timeOut) {
                        timeOut = setTimeout(function() {
                            callback(value);
                            //执行一次,时间段内的都不知执行
                            timeOut = null;
                        }, wait)
                    }
                }
            }
            function skillEvent(value){
                var textDom = document.getElementById('skillEventId');
                console.log(value)
                ++count
                textDom.innerText = value+count;
            }
            var skillAc=throttle(3000,skillEvent)
            var count=0
            skillDom.addEventListener('click', function(e) {
                let value = e.target.value
                skillAc(value)
            })  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在这里插入图片描述

完整的html

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>防抖与节流</title> </head> <style> * { margin: 0; padding: 0; } .container { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 600px; height: 400px; background: #262626; display: flex; } .left { position: relative; width: 50%; height: 100%; background: #00cec9; box-sizing: border-box; overflow: hidden; } .right { position: relative; width: 50%; height: 100%; background: #b2bec3; } </style> <body> <div class="container"> <div class="left"> <p>防抖(1s内显示输入内容)</p> <input type="text" id="leftInput" /> <div class='textDiv' id="textShow"></div> </div> <div class="right"> <p>节流(3s内触发一次)</p> <input type="submit" id="skillTriger" value="发动技能" /> <div class='skillEvent' id="skillEventId"></div> </div> </div> <script> // 防抖 var inputDom = document.getElementById('leftInput'); // 函数柯里化 function debounce(delay, callback) { let timer return function(value) { //闭包内存泄漏 clearTimeout(timer) timer = setTimeout(function() { //执行 callback(value) }, delay) } } // 显示内容的函数 function showText(value) { var textDom = document.getElementById('textShow'); console.log(value) textDom.innerText = value; } var debounceFunc = debounce(1000, showText); inputDom.addEventListener('keyup', function(e) { let value = e.target.value debounceFunc(value) }) // 节流 var skillDom = document.getElementById('skillTriger'); function throttle(wait, callback) { let timeOut; return function(value) { if (!timeOut) { timeOut = setTimeout(function() { callback(value); //执行一次,时间段内的都不知执行 timeOut = null; }, wait) } } } function skillEvent(value) { var textDom = document.getElementById('skillEventId'); console.log(value) ++count
                textDom.innerText = value + count; } var skillAc = throttle(3000, skillEvent) var count = 0 skillDom.addEventListener('click', function(e) { let value = e.target.value skillAc(value) }) </script> </body> </html>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

1

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

配合前端vue实现表格的增删改查

前端达人

前言:

        这个章节内容是比较多的,分为前端部分和后端部分。

目录:

实现效果:增删改查

 一、后端部分:

(1)数据库:

        新建一张表user,设置几个字段,效果如下:

 (2)egg逻辑部分:

提供的接口:http://localhost:7001/setUserList

 (3)egg具体实现步骤:

1、router.js中添加:

2、新建:app / controller / new / user.js

(1)查,模糊查询 

(2)增

 (3)改

 (4)删

 user.js 源码:

3、引入mysql:点我

4、跨域问题解决:点我

 二、前端部分:

新建vue文件:testApi.vue

1、初始化查询列表数据:页面展示列表,列表数据mouted获取

2、页面点击新增:展示弹框,并将弹框内容去除掉,点击新增,将弹框内容发送给后端

 3、页面点击列表里面具体数据的编辑:弹框,并回填数据,修改将当前数据的id和表格数据传给后端

4、删除按钮,点击出现二次确认弹框,点击确认将当前数据的id给后端就行 

 testApi.vue 源码:


实现效果:增删改查

 一、后端部分:

(1)数据库:

        新建一张表user,设置几个字段,效果如下:

 (2)egg逻辑部分:

提供的接口:http://localhost:7001/setUserList

  1. get 请求,获取数据,支持模糊查询
  2. post 请求,新增数据
  3. put 请求,给后端当前数据id,修改内容
  4. delete 请求,根据数据id删除当前条数据

 (3)egg具体实现步骤:

1、router.js中添加:

 
  1. /**
  2. * 路由配置
  3. * @param app
  4. */
  5. module.exports = app => {
  6. const { router, controller } = app;
  7. //--------------------------------------------------
  8. // server接口
  9. //--------------------------------------------------
  10. app.get('/setUserList', controller.new.user.getUserList);
  11. app.post('/setUserList', controller.new.user.postUserList);
  12. app.put('/setUserList', controller.new.user.putUserList);
  13. app.delete('/setUserList', controller.new.user.deleteUserList);
  14. }

2、新建:app / controller / new / user.js

(1)查,模糊查询 

select * from user where name like ? % 内容 %

(2)增

this.app.mysql.insert('表名',内容)

 (3)改

UPDATE loginlist SET `password` = 'Ad123456' WHERE id = 2

 (4)删

delete from user where id = 1

 user.js 源码:

 
  1. /**
  2. * 用户信息路由
  3. * @param app
  4. * @returns {HomeController}
  5. */
  6. const Controller = require('egg').Controller;
  7. class NewsController extends Controller {
  8. async getUserList() {
  9. //查询库里的user表
  10. let params = this.ctx.query //获取路径后面的参数
  11. console.log('用户的参数:');
  12. console.log(params);
  13. let sql = 'select * from user'
  14. let initSql = sql
  15. let content = [];//参数
  16. let isMore = false;//是否有多个查询参数
  17. /**
  18. * @模糊查询-量大的时候效率低
  19. * select * from user where name like ? % 内容 %
  20. * 在user表中全局查找name值 == 内容的
  21. * % 内容 % 全局查找内容
  22. * 内容 % 查找以 内容 开头的数据
  23. * */
  24. if(params.name){
  25. sql += " where name like ?";
  26. content.push( "%"+params.name+"%" );
  27. isMore = true;
  28. }
  29. if(params.age){
  30. if(isMore){//true代表有多个参数
  31. sql += "and age LIKE ?";//and是两个条件都必须满足,or是或的关系
  32. }else{
  33. sql += " WHERE age LIKE ?";
  34. }
  35. content.push( "%"+params.age+"%" )
  36. isMore = true;
  37. }
  38. if(params.address){
  39. if(isMore){//true代表有多个参数
  40. sql += "and address LIKE ?";//and是两个条件都必须满足,or是或的关系
  41. }else{
  42. sql += " WHERE address LIKE ?";
  43. }
  44. content.push( "%"+params.address+"%" )
  45. isMore = true;
  46. }
  47. if(params.phone){
  48. if(isMore){//true代表有多个参数
  49. sql += "and phone LIKE ?";//and是两个条件都必须满足,or是或的关系
  50. }else{
  51. sql += " WHERE phone LIKE ?";
  52. }
  53. content.push( "%"+params.phone+"%" )
  54. }
  55. //开启分页
  56. if(params.page || params.pageSize){
  57. let current = params.page;//当前页码
  58. let pageSize = params.pageSize;//一页展示多少条数据
  59. sql += " limit ?,?";
  60. content.push((current-1)*pageSize,parseInt(pageSize));
  61. }
  62. let allList = await this.app.mysql.query(initSql);
  63. let userList= await this.app.mysql.query(
  64. sql,content
  65. );
  66. this.ctx.body = {
  67. code:200,
  68. masg:'success',
  69. data: {
  70. list:userList,
  71. total:allList.length
  72. }
  73. };
  74. }
  75. /**
  76. * 新增用户信息
  77. * INSERT INTO loginlist (aaa,bbb,ccc) VALUES ('"'+111+'","'+222+'","'+333+'"')
  78. * this.app.mysql.insert('表名',内容)
  79. * this.app.mysql.insert('表名',{
  80. * name:123,
  81. * age:1,
  82. * address:西安
  83. * })
  84. */
  85. //
  86. async postUserList() {
  87. console.log(this.ctx.request.body);
  88. //新增数据-user表
  89. let data = this.ctx.request.body
  90. data.id = parseInt(Math.random()*100000)
  91. let insertResult = await this.app.mysql.insert(
  92. 'user', data
  93. );
  94. this.ctx.body = {
  95. code:200,
  96. masg:'success',
  97. data:insertResult
  98. };
  99. }
  100. /**
  101. * 修改用户信息
  102. * UPDATE loginlist SET `password` = 'Ad123456' WHERE id = 2(唯一值),修改一个
  103. * UPDATE loginlist SET username = 'admins', `password` = 'Ad123456' WHERE id = 2,修改多个
  104. */
  105. async putUserList(){
  106. //新增数据-user表
  107. let id = this.ctx.query.id //获取路径后面的参数
  108. let data = this.ctx.request.body
  109. let sql = 'update user set '
  110. let isMore = false;//是否有多个查询参数
  111. if(!id){
  112. this.ctx.body = {
  113. code:200,
  114. masg:'warning',
  115. data:'id没有传'
  116. };
  117. return
  118. }
  119. //姓名
  120. if(data.name){
  121. sql += 'name = "'+data.name+'"'
  122. isMore = true
  123. }
  124. //年龄
  125. if(data.age){
  126. if(isMore){
  127. sql += ',age = "'+data.age+'"'
  128. }else{
  129. sql += 'age = "'+data.age+'"'
  130. }
  131. isMore = true
  132. }
  133. //地址
  134. if(data.address){
  135. if(isMore){
  136. sql += ',address = "'+data.address+'"'
  137. }else{
  138. sql += 'address = "'+data.address+'"'
  139. }
  140. isMore = true
  141. }
  142. //手机号
  143. if(data.phone){
  144. if(isMore){
  145. sql += ',phone = "'+data.phone+'"'
  146. }else{
  147. sql += 'phone = "'+data.phone+'"'
  148. }
  149. isMore = true
  150. }
  151. //邮箱地址
  152. if(data.email){
  153. if(isMore){
  154. sql += ',email = "'+data.email+'"'
  155. }else{
  156. sql += 'email = "'+data.email+'"'
  157. }
  158. }
  159. sql += ' where id = ' + id
  160. let insertResult = await this.app.mysql.query(sql)
  161. this.ctx.body = {
  162. code:200,
  163. masg:'success',
  164. data:insertResult
  165. };
  166. }
  167. /**
  168. * 注销用户接口
  169. * DELETE FROM loginlist WHERE username = 'superman'
  170. */
  171. async deleteUserList(){
  172. //查询库里的user表
  173. let params = this.ctx.query //获取路径后面的参数
  174. console.log('用户的参数:');
  175. console.log(params);
  176. let sql = 'delete from user where id = '+ params.id
  177. let res = await this.app.mysql.query(
  178. sql
  179. );
  180. this.ctx.body = {
  181. code:200,
  182. masg:'success',
  183. data:res
  184. };
  185. }
  186. /**
  187. * 模糊查询封装方法
  188. * @params = auth
  189. * */
  190. async query( auth ) {
  191. const TABLE_NAME = 'user';
  192. const QUERY_STR = 'id, name, age, phone, address';
  193. let sql = `select ${QUERY_STR} from ${TABLE_NAME} where authName like "%${auth.authName}%"`;
  194. const row = await this.app.mysql.query(sql);
  195. return row;
  196. }
  197. }
  198. module.exports = NewsController;

3、引入mysql:点我

4、跨域问题解决:点我

 二、前端部分:

新建vue文件:testApi.vue

1、初始化查询列表数据:页面展示列表,列表数据mouted获取

 
  1. <el-table
  2. :data="tableInfo.list"
  3. style="width: 100%">
  4. <el-table-column
  5. type="index"
  6. label="序号"
  7. align="center">
  8. </el-table-column>
  9. <el-table-column
  10. prop="name"
  11. label="姓名"
  12. align="center">
  13. </el-table-column>
  14. <el-table-column
  15. prop="age"
  16. label="年龄"
  17. align="center">
  18. </el-table-column>
  19. <el-table-column
  20. prop="address"
  21. label="地址">
  22. </el-table-column>
  23. <el-table-column
  24. prop="phone"
  25. label="手机号">
  26. </el-table-column>
  27. <el-table-column
  28. prop="email"
  29. label="邮箱">
  30. </el-table-column>
  31. <el-table-column
  32. label="操作"
  33. width="100">
  34. <template slot-scope="scope">
  35. <el-button type="text" size="small" @click="editFun(scope.row)">编辑</el-button>
  36. <el-button type="text" size="small" @click="deleteFun(scope.row)">删除</el-button>
  37. </template>
  38. </el-table-column>
  39. </el-table>
 
  1. mounted(){
  2. this.initPage()
  3. },
  4. methods: {
  5. /***
  6. * 获取列表数据
  7. */
  8. initPage() {
  9. let params = {
  10. page: this.tableInfo.page, //当前页
  11. pageSize: this.tableInfo.pageSize //一页展示多少条
  12. }
  13. this.$axios.get('http://localhost:7001/setUserList',{
  14. params
  15. }).then(res => {
  16. this.tableInfo.list = res.data.data.list
  17. this.tableInfo.total = res.data.data.total
  18. }).catch(error => {
  19. this.$message(error.data.message)
  20. })
  21. },
  22. }

2、页面点击新增:展示弹框,并将弹框内容去除掉,点击新增,将弹框内容发送给后端

 3、页面点击列表里面具体数据的编辑:弹框,并回填数据,修改将当前数据的id和表格数据传给后端

 

 

4、删除按钮,点击出现二次确认弹框,点击确认将当前数据的id给后端就行 

 testApi.vue 源码:

 
  1. <template>
  2. <div class="pro_body">
  3. <el-button type='success' @click="addModal">新增</el-button>
  4. <el-table
  5. :data="tableInfo.list"
  6. style="width: 100%">
  7. <el-table-column
  8. type="index"
  9. label="序号"
  10. align="center">
  11. </el-table-column>
  12. <el-table-column
  13. prop="name"
  14. label="姓名"
  15. align="center">
  16. </el-table-column>
  17. <el-table-column
  18. prop="age"
  19. label="年龄"
  20. align="center">
  21. </el-table-column>
  22. <el-table-column
  23. prop="address"
  24. label="地址">
  25. </el-table-column>
  26. <el-table-column
  27. prop="phone"
  28. label="手机号">
  29. </el-table-column>
  30. <el-table-column
  31. prop="email"
  32. label="邮箱">
  33. </el-table-column>
  34. <el-table-column
  35. label="操作"
  36. width="100">
  37. <template slot-scope="scope">
  38. <el-button type="text" size="small" @click="editFun(scope.row)">编辑</el-button>
  39. <el-button type="text" size="small" @click="deleteFun(scope.row)">删除</el-button>
  40. </template>
  41. </el-table-column>
  42. </el-table>
  43. <el-pagination
  44. class="work_pagination"
  45. background
  46. :layout="'total,prev, pager, next,sizes'"
  47. :total="tableInfo.total"
  48. :hide-on-single-page="false"
  49. :current-page="tableInfo.page"
  50. :page-size="tableInfo.pageSize"
  51. @current-change="pageChange"
  52. @size-change="pageSizeChange"
  53. >
  54. </el-pagination>
  55. <!--弹框部分-->
  56. <el-dialog
  57. custom-class="modalName"
  58. :visible.sync="modal.show"
  59. :width="modal.type === 'delete'? '470px' : '800px'">
  60. <h3 v-if="modal.type === 'add'" slot="title">新增</h3>
  61. <h3 v-if="modal.type === 'edit'" slot="title">修改</h3>
  62. <h3 v-if="modal.type === 'delete'" slot="title">提示</h3>
  63. <div v-if="modal.type !== 'delete'" class="editNameBody">
  64. <el-form class="editNameFrom" :model="modalFrom" label-width="120px" label-position="right">
  65. <el-form-item label="姓名:">
  66. <el-input v-model="modalFrom.name"></el-input>
  67. </el-form-item>
  68. <el-form-item label="年纪:">
  69. <el-input v-model="modalFrom.age"></el-input>
  70. </el-form-item>
  71. <el-form-item label="手机号:">
  72. <el-input v-model="modalFrom.phone"></el-input>
  73. </el-form-item>
  74. <el-form-item label="邮箱:">
  75. <el-input v-model="modalFrom.email"></el-input>
  76. </el-form-item>
  77. <el-form-item label="地址:">
  78. <el-input v-model="modalFrom.address" type="textarea"></el-input>
  79. </el-form-item>
  80. </el-form>
  81. </div>
  82. <div v-if="modal.type === 'delete'">
  83. <i class="el-icon-warning" style="margin-right:7px;color:#FFAA00;font-size: 16px;"></i>请确认是否删除
  84. </div>
  85. <div slot="footer" class="dialog-footer">
  86. <el-button @click="modal.show = false">取 消</el-button>
  87. <el-button v-if="modal.type === 'add'" type="primary" @click="addUserList">新增</el-button>
  88. <el-button v-if="modal.type === 'edit'" type="primary" @click="editUserList">修改</el-button>
  89. <el-button v-if="modal.type === 'delete'" type="primary" @click="deleteUserList">确 认</el-button>
  90. </div>
  91. </el-dialog>
  92. </div>
  93. </template>
  94. <script>
  95. export default {
  96. data() {
  97. return {
  98. tableInfo:{
  99. columns:[
  100. {
  101. title: '序号',
  102. type: 'index',
  103. },{
  104. title: '姓名',
  105. prop: 'name',
  106. align: 'center'
  107. },
  108. {
  109. title: '年龄',
  110. prop: 'age',
  111. align: 'center'
  112. },{
  113. title: '地址',
  114. prop: 'address',
  115. align: 'center'
  116. },{
  117. title: '邮箱',
  118. prop: 'email',
  119. align: 'center'
  120. },{
  121. title: '手机号',
  122. prop: 'phone',
  123. align: 'center'
  124. },
  125. {//内容slot
  126. slot: 'operateT'
  127. }
  128. ],
  129. list:[],
  130. page:1,
  131. pageSize:10,
  132. total:0,
  133. },
  134. modal:{
  135. show:false,
  136. type:'add'
  137. },
  138. modalFrom:{
  139. name:'',
  140. age:'',
  141. phone:'',
  142. address:'',
  143. email:''
  144. }
  145. };
  146. },
  147. mounted(){
  148. this.initPage()
  149. },
  150. methods: {
  151. /***
  152. * 获取列表数据
  153. */
  154. initPage() {
  155. let params = {
  156. page: this.tableInfo.page, //当前页
  157. pageSize: this.tableInfo.pageSize //一页展示多少条
  158. }
  159. this.$axios.get('http://localhost:7001/setUserList',{
  160. params
  161. }).then(res => {
  162. this.tableInfo.list = res.data.data.list
  163. this.tableInfo.total = res.data.data.total
  164. }).catch(error => {
  165. this.$message(error.data.message)
  166. })
  167. },
  168. /**
  169. * 当前页发生改变
  170. * */
  171. pageChange(page) {
  172. this.tableInfo.page = page
  173. this.initPage() //刷新列表数据
  174. },
  175. /**
  176. * 当前第几页发生改变
  177. * */
  178. pageSizeChange(pageSize) {
  179. this.tableInfo.page = 1
  180. this.tableInfo.pageSize = pageSize
  181. this.initPage() //刷新列表数据
  182. },
  183. //新增弹框
  184. addModal(){
  185. this.modalFrom ={
  186. name:'',
  187. age:'',
  188. phone:'',
  189. address:'',
  190. email:''
  191. }
  192. this.modal.show = true
  193. this.modal.type = 'add'
  194. },
  195. //修改弹框
  196. editFun(row){
  197. this.modalFrom = row
  198. this.modal.show = true
  199. this.modal.type = 'edit'
  200. },
  201. //删除弹框
  202. deleteFun(row){
  203. this.modalFrom = row
  204. this.modal.show = true
  205. this.modal.type = 'delete'
  206. },
  207. addUserList(){
  208. this.$axios({
  209. method:'post',
  210. url:'http://localhost:7001/setUserList',
  211. data:this.modalFrom
  212. }).then(res => {
  213. this.$message.success('新增成功')
  214. this.initPage() //刷新数据
  215. this.modal.show = false
  216. })
  217. },
  218. editUserList(){
  219. this.$axios({
  220. method:'put',
  221. url:'http://localhost:7001/setUserList',
  222. params:{
  223. id:this.modalFrom.id
  224. },
  225. data:this.modalFrom
  226. }).then(res => {
  227. this.$message.success('修改成功')
  228. this.initPage() //刷新数据
  229. this.modal.show = false
  230. })
  231. },
  232. deleteUserList(){
  233. this.$axios({
  234. method:'delete',
  235. url:'http://localhost:7001/setUserList',
  236. params:{
  237. id:this.modalFrom.id
  238. }
  239. }).then(res => {
  240. this.$message.success('删除成功')
  241. this.initPage() //刷新数据
  242. this.modal.show = false
  243. })
  244. }
  245. }
  246. }
  247. </script>
  248. <style lang='scss'>
  249. .modalName{
  250. h3{
  251. padding:10px;
  252. }
  253. }
  254. </style>


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

全面总结图表设计的思路和方法

涛涛

数据成为了日常工作的一大重要角色,越来越多的公司以数据驱动产品进行迭代。但令人困惑的是可视化图表无处不矮,但却给大家带来了误导。作者分享了一些简单的思路与方法,以此来改善这些问题,希望对你有所帮助。


越来越多的公司以数据驱动产品进行迭代,从中我们能看出数据的重要性。

日常工作中,无论是汇报还是设计,都离不开图表的使用。但令人困惑的可视化图表无处不在,往往给人带来误导性,通过遵循下面这些简单的思路和方法可以有效改善这些问题。

一、选择正确的图表类型

选择错误的图表类型,或默认使用最常见的类型,可能会混淆用户对数据产生误解。

一组数据可以有多种表示方式,具体类型取决于用户希望看到的内容。

二、根据正负值确定方向

当数据中出现正负值时,要先确定基线的位置,再确定数据位置,将正值分布在基线上侧(X轴)或右侧(Y轴),负值分布在下侧(X轴)或左侧(Y轴)。

避免在基线的同一侧同时添加正值和负值,造成用户对图表信息理解错误。

三、始终从零开始绘制条形图

单看左侧的条形图,能发现B的值比D的值要多3倍以上,但在右侧从零开始的条形图中,实际差异要小得多。从零开始可确保用户获得更准确的数据展示。

四、折线图使用自适应Y轴

对折线图来说,如果始终将Y轴的比例限制为从零开始,一旦数据波动幅度很小,那整个折线图会看起来很平坦,效果不明显。

折线图主要用来表现趋势,根据给定时间的数据调整比例,并保持折线区域能占到Y轴范围的三分之二。

五、使用折线图时考虑时间间隔

折线图是由一条条小线段连接组成,这些线段展示了在短时间内数据是如何变化的。当时间间隔很大或数据更新不频繁时,就要慎重考虑是否使用折线图。

例如想表示年收入,左侧的两个折线图样式都不太合适,每个月的收入是固定的数字,而折线图展现的数据更像是收入的变化,相反右侧的条形图更适合来展示每月具体的收入。

六、不要使用平滑的折线

平滑的折线图可能看着很舒服,但它们歪曲了背后的实际数据,而且过粗的线条掩盖了真正的节点。

七、谨慎使用双轴折线图

当两组数据出现X轴代表的信息相同但Y轴不同时,为节省空间我们可能会考虑用双轴图。

但大部分双轴图难以阅读,只是感觉图表上有很多数据,但远远没有单个图表展示的清晰。

八、限制饼图的切片数量

饼图是最受欢迎但经常被误用的图表之一。在使用饼图时,首先要注意切片的数量最好保持在5-7片。

如果还有很多占比很小的切片,可以将这些全部归到“其他”切片中。

九、直接在图表上标注

如果没有正确的标注,无论图表设计的多好看都没有意义。

直接在图表上标注数据或信息对使用者来说更直观,更节省时间和精力。

十、不要在切片上标注

将数值放在切片上虽然很直观,但可能会导致很多问题,例如左侧饼图数值的可读性问题、切片太薄无法添加数值等,对比来看,右侧饼图添加标注的方式更合适。

十一、饼图切片的排序

饼图切片的排序是一个很容易忽略的问题,将饼图切片只是一个开始,通过合理的排序保证用户清晰观看图表才是关键。

常见的排序方法是将面积最大的切片放在12点钟位置,然后按顺时针降序放置第二大的切片,以此类推。

十二、避免随机性

同样的建议适用于其他类型的图表。尽量不要默认按字母顺序排序,将最大值放在顶部(水平条形图)或左侧(对于垂直条形图),以确保最重要的值占据最突出的空间,减少视线运动和阅读图表所需的时间。

十三、避免极端的环形图

环形图,又称为甜甜圈图,是饼图的一种变体,本质是饼图将中间区域挖空,用在多样品间的多种数据的比较中。

虽然环形图腾出中间区域来显示额外的信息,但牺牲清晰度走极端会让图表变得毫无用处。

十四、让数据自己说话

不必要的设计样式不仅会分散注意力,还可能导致用户对数据误解并产生错误印象,图表在设计上应避免:

  • 3D元素、阴影、渐变;
  • 斑马纹、过多的网格线;
  • 装饰性过强的斜体、粗体或衬线字体。

十五、选择与数据性质匹配的调色板

颜色是保持数据可视化有效的组成部分,在设计时考虑3种调色板类型:

  • 分类色板(左)适合显示分类数据,当你想区别不连续且内在没有顺序关系的数据时可以使用这种类型;
  • 连续色板(中)适用于需要按特定顺序放置的变量中,使用色调/亮度或两者组合创建色板。
  • 离散色板(右)是两个连续色板的组合,中间有一个中心值(通常为零)。不同的调色板会传达正值和负值。

十六、无障碍设计

根据眼科研究中心的数据,大约每12个人中就有1个色盲,图表只有在广泛受众可以访问的情况下才是成功的:

  • 在调色板中使用不同的饱和度、亮度;
  • 黑白打印可视化图表,检查对比度和可读性。

十七、注重易读性

确保图表排版在传达信息并帮助用户专注于数据,而不是分散注意力:

  • 选择字迹清晰的字体,避免使用衬线和装饰性很强的字体;
  • 避免使用斜体、粗体和全部大写;
  • 确保文本与背景形成高对比度;
  • 不要旋转文本。

十八、使用水平条形图代替旋转标注

这个简单的技巧可以确保用户能够更有效地浏览图表,而不会使他们感到紧张。

十九、建立图表库

如果你的任务是将交互式图表添加到Web和移动项目中,那么首要考虑问题是将使用什么样的图表?

基于定义的库(Highcharts)进行设计将确保易于实现,并为我们提供大量的交互想法。

二十、超越静态报告

通过更改参数、可视化类型、时间线帮助用户进行探索,得出最大价值化的结论。例如IOS Health结合使用了各种数据表示来发挥优势。



蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码ben_lanlan,报下信息,会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

文章来源:人人都是产品经理  作者:Clippp
分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



如何提升用户体验

涛涛

现代人的生活离不开应用程序,我们的手机中有着各种各样的app帮我们处理各种琐事。各大互联网公司开发多种应用商店,努力使我们的生活变得有趣,但要想提高整体的用户体验,还需要注意五点,不然再好的app也会让用户放弃使用。


1.禁止使用大段的功能介绍

我们必须要提示一下:如果一个应用程序要在手机屏幕上发挥作用——必须简单。这个应用需要使用冗长的功能介绍,才能让用户熟悉使用起来,那很可能是开发人员在这个版本中设置太多功能。用户并不介意多次更新程序,适应新版本,但他们也不可能为了使用程序而阅读长如圣经般的介绍。


2.牢记用户需求


如果想要急于求成,跳过用户调研,上线新的应用,那么失败的概率会大大增加。大多数应用开发团队都容易犯这样的错误,只拿到了用户发送给支持团队的数据。通过分析数据,就能迅速确定用户所需的功能,使用缺陷等,但是,总的来说,联系支持团队的用户是那些产生挫败感的人;那么99%(或更多)的用户从来没有和支持部门谈过?难道你不愿意让他们一直满意,而是花费时间,只让使用支持功能的1%用户满意?


即使你认为自己了解用户需求,也需要与他们进行沟通。


3.使用屏幕技术


当人们花费了近万元买了一部智能手机时,他们希望能使用手机上的所有功能。所以制作这款手机时没有任何借口在视觉内容上偷工减料(或忽视任何技术能力)。这就是用户花钱的原因,要想提高用户体验,就需要满足用户期望。


4.停用费时的设置向导


设置向导的本意是为用户提供更好的内容,更能让用户获取自己想要的。为了优化用户体验可以让用户填写一些内容,但并不意味着暴露全部隐私。最好在需要时索取,而非提前取得全部数据。


5.减少通知次


每个软件都想要发送通知,但是每一个通知都是必要的吗?每隔两秒钟就有一些应用告知用户一些无用消息,比如谁谁谁又发了微博,谁谁谁上线了,又或者谁谁谁开始直播了,可以根据用户的兴趣选取推送而不是一股脑全部告知用户,所以请尽量减少的通知消息吧!

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码ben_lanlan,报下信息,会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

文章来源:站酷  作者:马克笔留学设计

分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


B端产品设计规范之数据展示

涛涛


数据展示有哪些?



01.徽标

是收纳消息数量的样式,一般出现在图标或者头像右上角。



02.标签

数据展示里面抽取出来的共性特征,将它们转化为标签。标签样式有线框、带不透明底或者面性。



03.走马灯

相当于c端的轮播图




04.文字提示

可以出现在鼠标悬浮按钮时候的行为解释说明,也可以是文案或者导航图标的解释说明。鼠标移入时候出现移出时候消失。



05.气泡卡片

比起文字提示可以承载更多内容,相对弹窗,气泡卡片操作更轻盈。




06.标签页/选项卡

标签页可以帮助用户在一个页面内快速切换不同类型内容,提升单个页面整体的扩展性。标签本质上就是内容区的导航。



07.折叠面板

折叠面板可以更好的收纳内容区域,提高页面利用率。可以和表格结合使用,折叠表格部分详情内容,使得纵向空间更节约。




08.表格

表格是数据展示的重要内容。当有大量结构化数据需要展示时或者需要对数据进行排序、搜索分页时可以用表格进行展现。


当笔记本过小,表格展示不全时候,可以固定首尾重要信息进行滚动。


带排序的表头,可对数量或者金额进行排序。


带分组的表格,建议带边框并且用色块区分表头和内容。


单元格可编辑


批量选中时只会选中当前页,因为分页还没加载出来,为了给用户正确的引导,可以给上提示性文案,例如“已选中XX项内容”。


如果当前页批量选中的数据量不满足要求,可以改变分页器,增加当前页数据量,从而增加选项。


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码ben_lanlan,报下信息,会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

文章来源:站酷  作者:最多三分糖

分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



如何做好直播设计的体系化复盘?

涛涛

前言

“直播”作为一个大热领域,用户规模早在 2020 年就突破了 5 亿大关,在“直播+”的模式下,电商、教育甚至是医美,都能在直播领域下找到新赛道,并产生持续性获客。但就是这样一个核心领域,具体要怎么分析复盘,却鲜少看到系统化的文章。本文主要是结合我近期参与产品直播项目的思考,总结了自己的一套直播复盘方法论和大家分享。

为什么要做直播复盘?

虽然“直播+”模式已成为行业趋势,但在产品接入直播模块而产生的付费效益又不明显时,其存在的意义和价值仍时常被挑战,因此首要的就是验证其价值;

同时,新领域缺乏可复用的方法论,只有不断探索、优化、沉淀才能促进其健康化生长;

最后,在产品范围下的直播领域,定向吸引的还是产品用户为主,持续挖掘探索直播能为产品开辟的新赛道,为产品带来拉新,是“直播+”模式对于产品的直接价值体现。

如何做好直播设计的体系化复盘?

直播复盘怎么做?

直播具备快节奏性和强竞争性,在兼顾快速复盘的同时,还需要考虑阶段性的整体化的对直播数据进行监控,因此需要将直播复盘分为快速复盘和阶段复盘 2 个大方向。

1. 快速复盘

在直播结束当天或隔天对昨日数据进行快速复盘,此时重点关注单期直播下的直观数据表现和用户反馈。目的是获得沉淀当天直播的经验并快速应用至后续直播中,是一个不断 PDCA 的过程。

在复盘维度上,可以分为数据侧和用户侧:

数据侧中我们重点聚焦本期的数据表现,同时横向对比其他直播期,去明确本期的数据表现

1)横向对比时,需要将直播关注的 3 大核心数据(总人数、最高在线人数、评论人数、在线时长均值)与其他期对比,明确该期直播的“优劣”。

如何做好直播设计的体系化复盘?

当期直播核心数据

2)聚焦本期时,重点关注直播数据的整体在线人数变化趋势,定位到最高在线点,和直播内容拟合,能够帮助我们定位直播的“高光点”。

用户侧中则更关注主播在播、用户在听和答的过程,包含:

  • 直播过程中,用户情绪、反馈异常的节点(如消极发言等),定位用户可能存在的痛点。
  • 固定同学作为“直播观众”时,察觉到的异常问题(如信息衔接不自然等),及时复盘。
  • 在直播间的互动评论中,呼声最高的内容,可以作为后续直播可以“返场”的内容,纳入直播内容需求池中。

2. 阶段复盘

在累计多场直播后,此时最需要的就是阶段性的复盘,从宏观角度对多期直播进行收敛分析,能够帮助我们明确直播对于产品的核心价值,并定位核心用户圈层、吸引点及直播应该要有的“节奏”。

在阶段复盘中,除了数据侧、用户侧外,我们还需要关注市场侧:

数据侧—不同于快速复盘,数据侧我们关注整体宏观角度上直播对产品的价值,以及直播整体的数据表现,热点分布等

1)从直播对产品价值定位来说,在未探索付费的情况下,直播能为产品做的就是吸引新用户,增加用户活跃、延长用户在产品内停留的时长上。

如何做好直播设计的体系化复盘?

价值定位时关注的数据范围

在明确价值后,就应该明确后续要如何把直播做的更好,这里数据上可以分为 2 个大的方向,一是热点分析,二是直播节奏分析。

2)热点分析上,需要从单期、分类、词项拆解上看。首先,单期直播就是简单地对单期直播数据进行排序,找到“好”的直播提炼其特征性;其次,分类分析上关注各类直播数据间的横向对比,能从分类数据对比上,看出哪一类直播更吸引用户;最后,通过对每期直播的标题进行词项拆解,筛除掉无意义的词项,再乘以对应期直播的人数,对每个出现 2 次及以上的词项数据取出其对应的单期直播人数均值,即可定位到用户最关注、最能吸引用户的核心关键词。

如何做好直播设计的体系化复盘?

热点分析

3)直播节奏分析上,得益于阶段性复盘的庞大数据量,我们可以聚类出多期直播聚类下的直播趋势线,在趋势线上,亦关注 3 大核心点 “拉新、增长、流失”。

a. 用户进入直播的高峰期(即新增高峰),可用于定位直播亮点,并对应布局以留住用户

如何做好直播设计的体系化复盘?

用户进入直播节奏分析

b. 通过直播数据排序后的高于中位数直播、低于中位数直播的 2 种直播数据走势的对比,我们能够看出好的直播应有的数据走势应该是什么样的。以我这次分析的直播为例,能够直观看出,“差”的直播在增长黄金期都“爬”的很慢,而在黄金期后直播数据逐渐平缓,“差”的直播数据就成了定局。因此要做的就是在增长黄金期,去尽量促进增长。

如何做好直播设计的体系化复盘?

用户流入流出关系分析

c. 那么在增长黄金期,从产品策略来看,要做的是留住用户?还是尽量去拉新?从数据上,我们有 2 种方式判别,分别是相关性分析和假设分析。在相关性分析中,将新增人数/流失率对标最高在线人数,以数据模型分析其相关性,从相关系数来看哪个指标与最高在线人数相关性最高,即影响最大;在假设分析中,我们可以将“低于中位数”的直播数据中的新增人数/流失率分别对标“高于中位数”直播的数据,其他保持不变,看哪种情况下,最高在线人数是更高,数据是更好的,就可以定位出更应该在哪块发力。

用户侧—要明确直播受众及用户圈层,并针对这部分受众的观看体验,进行服务体验走查,更能够帮我们明确后续业务重心、范围及宣传模式。

在用户圈层上,我们对观众数据清洗,从年龄、性别、地域、渠道等各项维度去定位观众的特征。同时,考虑到直播本身是以产品为载体,其用户圈层基本上与产品本身重合,但会存在一定差异性。因此,此处可以结合 TGI 分析,可以定位到直播用户圈层相较于产品来说的差异点,从而更针对受众进行直播内容调整。

如何做好直播设计的体系化复盘?

用户圈层分析

同时,直播本身因其特殊性质,也可类比至服务体验设计的思维,因此在用户侧分析时,从直播前-中-后 3 个大环节上分析用户行为、需求、痛点、快点,从而定位到各个环节直播优化的机会点,推进优化。

如何做好直播设计的体系化复盘?

直播-体验地图

市场侧—在市场分析时,我们不仅需要关注那些在直播领域做的好的同类竞品,同时也要去多分析在受众群体中,最近的热门话题是什么,有助于后续在宣发时引出直播核心话题,也能够带领我们思考直播的新赛道,以协助产品拓宽其用户圈层。

小结

直播作为互联网新赛道,直播+的模式可用于产品宣发、获客、促活等各个方面,挑战与机遇并存。但正因为是新赛道,也相对缺乏体系化的方法论。本文主要是分享我在工作中沉淀下来的直播复盘方法论,也欢迎大家有什么见解或者想法也可以与我分享。

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码ben_lanlan,报下信息,会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

文章来源:优设  作者:番茄

分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务




CORS和JSONP的区别,如何解决跨域问题?

前端达人

在我们了解JSONP 和 CORS 之前我们先明确一下:

我们为什么要使用cors和jsonp呢?

实际上,cors和jsonp都是用于解决跨域问题,当两个页面的协议、域名、端口号中有一个不一致时就存在了跨域,一旦出现跨域,浏览器发送跨域请求后,请求回来的数据都会被浏览器所拦截,准备一张图给大家看看:

 

核心点:如何实现跨域数据请求?(⭐⭐⭐⭐⭐)

现下实现跨域数据请求,最主要的两种解决方案分别是 JSONP 和 CORS 

JSONP  出现的早,兼容性好(兼容低版本 IE )。是前端程序员为了解决跨域问题,被迫想出来的一种 临时解决方案,最主要的缺点 是只支持 GET 请求,不支持 POST 请求。
CORS  出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请 求。缺点 是不兼容某些低版本的浏览器。

什么是JSONP(⭐⭐⭐)

JSONP (JSON with Padding) 是 JSON 的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

JSONP的实现原理(⭐⭐⭐) 

  1. 概念:浏览器端通过 <script> 标签的 src 属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP

  2. 特点: 

   JSONP 不属于真正的 Ajax 请求,因为它没有使用 XMLHttpRequest 这个对象

    JSONP 仅支持 GET 请求,不支持 POSTPUTDELETE 等请求

什么是CORS(⭐⭐⭐⭐⭐)

  1. CORS (跨域资源共享) 由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器 是否阻止前端 JS 代码跨域获取资源

  2. 浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制

 

 

下面分别向大家演示通过CORS和JSONP实现跨域的案例:

一、通过CORS中间件解决跨域问题 :

index.html文件代码演示:


    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script src="jquery.min.js"></script>
  9. </head>
  10. <body>
  11. <button class="get">get请求</button>
  12. <button class="post">post请求</button>
  13. <script>
  14. $('.get').on('click', function() {
  15. $.ajax({
  16. method: 'get',
  17. url: 'http://127.0.0.1/api/get?name=hua&age=18',
  18. success: function(res) {
  19. console.log(res);
  20. }
  21. })
  22. })
  23. $('.post').on('click', function() {
  24. $.ajax({
  25. method: 'post',
  26. url: 'http://127.0.0.1/api/post',
  27. data: {
  28. name: 'lajitong',
  29. age: '111'
  30. },
  31. success: function(res) {
  32. console.log(res);
  33. }
  34. })
  35. })
  36. </script>
  37. </body>
  38. </html>

此时会出现跨域问题,我们需要使用 cors 中间件解决跨域问题

  1. cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题

  2. 使用步骤

    • 安装中间件: npm install cors

    • 导入中间件: const cors = require('cors')

    • 配置中间件: 在路由之前调用app.use(cors())

  3. express接口案例代码


    
  1. // 导入 express 模块
  2. const express = require('express')
  3. // 创建 express 的服务器实例
  4. const app = express()
  5. // 导入中间件
  6. const cors = require('cors')
  7. // 配置中间件
  8. app.use(cors())
  9. // 配置解析表单数据的中间件
  10. app.use(express.urlencoded({ extended: false }))
  11. // 导入路由模块(被单独分离后导入)
  12. const router = require('./apiRouter')
  13. // 把路由模块,注册到 app 上
  14. app.use('/api', router)
  15. // 调用 app.listen 方法,指定端口号并启动 web 服务器
  16. app.listen(80, () => {
  17. console.log('http://127.0.0.1')
  18. })

apiRouter路由文件代码:


    
  1. const express = require('express');
  2. const router = express.Router();
  3. router.get('/get', (req, res) => {
  4. const query = req.query;
  5. res.send({
  6. status: 0,
  7. msg: 'get请求成功',
  8. data: query
  9. })
  10. })
  11. router.post('/post', (req, res) => {
  12. // const body = req.body; //获取客户端请求的数据
  13. res.send({
  14. status: 0,
  15. msg: 'post请求成功',
  16. data: req.body
  17. })
  18. })
  19. module.exports = router;

在终端中运行express接口代码后打开index.html文件并点击get及post按钮得到请求结果:

 二、通过JSONP中间件解决跨域问题 :

创建 JSONP 接口的注意事项

  1. 如果项目中已经配置了 CORS 跨域资源共享,为了防止冲突,必须在配置 CORS 中间件之前声明 JSONP 的接口

    否则 JSONP 接口会被处理成开启了 CORS 的接口

  2. 实现步骤:

        (1)获取客户端发送过来的回调函数的名字

        (2)得到要通过 JSONP 形式发送给客户端的数据

        (3)根据前两步得到的数据,拼接出一个函数调用的字符串

        (4)把上一步拼接得到的字符串,响应给客户端的 <script> 标签进行解析执行

案例代码如下:


    
  1. //导入express模块
  2. const express = require('express');
  3. //创建express服务器实例
  4. const app = express();
  5. //挂载路由
  6. app.get('/jsonp', (req, res) => {
  7. // 通过解构req.query客户端通过查询字符串的形式发送到客户端的参数fn
  8. const { callback } = req.query
  9. //在服务器端定义一个obj对象
  10. const obj = {
  11. uname: 'zjj',
  12. age: '18'
  13. }
  14. //obj对象转为res.send可处理的字符串形式后从服务器端相应回调函数至客户端
  15. res.send(`${callback}(${JSON.stringify(obj)})`)
  16. })
  17. app.listen(80, () => {
  18. console.log('http://127.0.0.1');
  19. })

创建jsonp.html客户端来接收服务器端响应过来的回调函数,代码如下:

url中callback=fn为客户端发送请求携带的参数 既服务器端中的req.query.callback


    
  1. <script>
  2. function fn(res) {
  3. console.log(res);
  4. }
  5. </script>
  6. <script src="http://127.0.0.1/jsonp?callback=fn"></script>




蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档