首页

Struts2中转发和重定向的区别以及实现方法

seo达人

Struts2中转发和重定向的区别以及实现方法

最近遇到一个问题,就是在设置struts2的拦截器以后,想要访问必须登录,想要的效果是转到登录页面,也就是转到xxx.jsp,但是发现没有转到,而是action结尾的,后来发现是因为在struts.xml里面配置的时候,没有在result中配置type属性,struts默认的是重定向,就是网址不变,解决办法就是在result中加type=”redirect”,就可以了



转发和重定向的区别:



重定向是不共享request的东西,重定向后的页面中无法接收request里的东西,另外dispatcher结果类型的default属性为TRUE,故<result-          type/>缺省为dispatcher 所以如果没有设置type属性的话,那么默认的是请求转发,就是说你要是什么都不写的话,默认就是这样的

1

<result name="list" type="dispatcher">/admin/jsp/userAction/list.jsp</result>

1

重定向的两个属性: 

redirect是在处理完当前Action之后,重定向到另外一个实际的物理资源,以.jsp结尾这样的 

redirectAction也是重定向,但它重定向到的是另外一个Action,就是以action结尾这样的 

只要是重定向,那么之前凡是保存在request里面的东西就全都消失了 

因为重定向实际是发送第二个请求,故请求中的东西也就不会出现在第二个请求里面了 

也就是说重定向是不共享request的东西,重定向后的页面中无法接收request里的东西,

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

Sketch 58 Beta版本探秘,看看都有什么新功能!

雪涛

Sketch 58 Beta 版本已于近期推出(其实最近一段时间已更新了好几个测试版),官方终于推出 Smart Layout 智能布局,让 Symbol 组件获得响应功能,变得更加灵活和强大。

之前我们只能使用第三方插件来制作响应式组件,比如之前介绍的 Kitchen 和 Anima。不过毕竟不是官方亲生的,难免会包含一些 bug 和不足。

比如 Kitchen 插件在制作 Symbol 组件的时候,其自动排版功能会出错。Anima 插件对上传到蓝湖的标注会有显示问题。关键是在团队协作的时候,其他使用源文件的同学也必须安装对应的插件,否则没有效果。

那么这次 Sketch 58 Beta 版本新推出的 Smart Layout 智能布局功能,能否解决长期困扰设计师的响应布局问题呢?一起来看下。

SketchBeta版本下载

如果想体验 Sketch Beta 版本,请进入 Sketch 测试版主页下载→https://www.sketch.com/beta/。但是要记住,一定不要用在自己的正式文件中,防止修改后,低版本打不开。

Sketch 58 要求 Mac 系统版本是 macOS High Sierra 10.13.4 及以上,下面是 Sketch 各大版本对应的 Mac 系统版本,如果遇到新版的 Sketch 打不开就需要检查下自己的系统版本。

  • Sketch52-58系列版本需要macOS High Sierra 10.13.4及以上
  • Sketch51系列版本需要macOS Sierra 10.12.2及以上
  • Sketch50系列版本需要OS X El Capitan 10.11.2及以上

Smart Layout智能布局介绍

本次 Sketch 58 Beta 最大的更新就是 Smart Layout。

在新建 Symbol 组件时,弹窗新增 Layout 选项,总共有 7 个属性,分别对应不同的图标,下面是每个属性的简单介绍。

1. No Layout

正常布局,也就是和原先一样,没有特殊效果。

2. Left to Right Layout

赋予 Symbol 组件智能布局效果,组件尺寸会根据内容变化,方向是水平从左往右布局。

3. Horizontally Center Layout

同上,方向是中间往左右两端布局。

4. Right to Left Layout

同上,方向是从右往左布局。

5. Top to Bottom Layout

赋予 Symbol 组件智能布局效果,组件尺寸会根据内容变化,方向是垂直从上往下布局。

6. Vertically Center Layout

同上,方向是中间往上下两端布局。

7. Bottom to Top Layout

同上,方向是从下往上布局。

另外在选择好 Layout 属性后,Symbol 页面的画板组件图标会发生变化,除了 No Layout 布局还是之前的画板图标之外,其余 6 个都有对应的新图标,看下图。

此外,选择画板后,右侧的属性面板中会新增布局选择功能,包含上面讲的7种属性,可随时对 Layout 布局进行更改。

看上面的描述还是比较迷惑,实际上智能布局简单来说,就是赋予 Symbol 组件内容边距的功能,尺寸随内容变化而变化,有点类似于前端 CSS 中的 padding 属性。下面用实际例子展示。

制作弹性按钮

以前我们使用过 Kitchen 和 Anima 制作过弹性按钮。需求是,文字两端的边距(即CSS中的padding)保持固定,文字数量不固定,按钮宽度随文字内容走。

那么在 Sketch 58 中,我们先制作一个按钮,文字两端的边距是 20。

转化为 Symbol,出现弹窗,在新增的 Layout 下拉中,选择 Left to Right Layout,这样文字变化时,左边是固定不动的,内容往右边延展。

这样一个弹性按钮就做好了,不管文字有多少,两端边距永远保持固定 20。和前端 CSS 中的 padding-left 和 padding-right 功能一样。

如果这个时候我们再拉伸 Symbol,右侧 Overrides 会出现一个新的图标:缩小实例以适配内容。点击后,被拉伸的组件会还原为文字内容长度。

注意,这个和原先的重设覆盖层图标不同,不会清除覆盖的文本内容,只会还原为适合内容大小。

以上是从左往右的布局,水平两端和从右往左也是一样的道理,只是方向不一样,下图是从右往左的布局。

这就是智能布局的主要功能,赋予 Symbol 组件 CSS 代码 padding 属性,具备响应特征。还需要注意的是,智能布局目前只针对 Symbol 组件,Kitchen 插件是可以作用于普通组的。

制作弹性按钮组

上面是单个组件的智能布局,如果是嵌套组件呢?也是可以的,一起试下。

我们把刚才做的按钮横向分布三个,再一起做成新的按钮组 Symbol 组件,结构看下图。

新的按钮组内,每个按钮已经是响应式的,那么做成组后就会保持组内元素的间距固定,更改下文字内容看下图。

非常棒,已经满足了我们刚开始的需求。但是不建议嵌套过多,要保持组件化设计思维。当然了,间距问题,Sketch 57 已经提供了多元素间距调整功能,只多了一步,但是不用把整体再次转化 Symbol,大家可以根据自己的需要灵活选择。

制作信息卡片

以上讲的是水平方向布局,同理垂直方向布局道理也一样,我们以最常见的信息卡片为例子。一般情况下卡片图片不变,标题和内容文字的不固定会导致卡片整体高度也会发生变化。利用智能布局我们可以让卡片变成响应式扩展。

确定好上下左右的间距,例子中用的 16,然后建立组件,Layout 选择从上往下布局,这样标题和内容文字增多,上下的间距是保持不变的,内容高度自动增加。

总结

以上就是 Sketch 58 Beta 版本新增的 Smart Layout 智能布局介绍。关于这个新功能,我们还可以做很多响应式的组件,提升设计效率。Sketch 的更新速度也在加快,很多之前第三方插件才可以实现的效果也被官方一一收入囊中。希望 Sketch 的发展越来越好,成为设计师真正的设计利器。

58 版本的欢迎界面也做了大更新,至于好不好看就因人而异了。最后来一睹芳容。

文章来源:优设

使用 vue 1.0.3 $set 函数遇到的坑

seo达人

vue 1.0.3  中 $set 函数是动态改变或添加一个 data 中的属性值时 属性 key 不可以使用纯数字。



例如:



var app = new Vue({

     el:"#app",

     data:{

         test:{

             k1:'v1',

             k2:'v2'

         }

     },

     methods:{

         changeTestValue:function{

             // 动态改变 test 中某一属性的值

             var key = 'test.k1';  // 改变 test 属性中的 k1 的值

             this.$set(key,'changev1');  // 此处执行没有问题

            // 改变 整个 test 的值可以使用

            this.$set('test',{k1:'change-demo-v1',k2:'change-demo-v2'});   // 此处执行没有问题

            // 动态给 test 增加一个属性  k3

            this.$set('test.k3','test-add-value3');   // 此处执行没有问题

 

 

            // 此处有坑 当你的 属性为全数字的时候,则 函数无效,不报错,但是也添加不上值。

            // 例如

            this.$set('test.123','test-add-123');  // 此处执行不报错,但是也没有效果。

 

 

            // 所以在使用老版本vue的时候尽量避免 属性 key 未纯数字,或其他特殊字符。

         }

     }

});



除了这个坑以外还有另外一个坑,不过没有具体试验,

watch 监听某一值得变化,好像有点问题, 实际结果是只要 data 中的任意一个值发生变化都会被捕捉到。







最后还是使用 vue 2.x  以上版本吧,bug 少很多。







另外 $set 函数在2.x 中使用方式有所变化。







this.$set(target,key,obj);



target 对象类型,是需要赋值或修改的对象,



key  是字符串类型, 是 target 对象的属性



obj  可以是字符串,可以是对象类型,是 你要修改的或增加的值


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

风靡社交圈的产品「绿洲」,有哪些值得关注的设计细节?

雪涛

这几天,各个产品群设计群又被「绿洲」的话题刷屏了,自从8月29日新浪悄悄上架了这款产品后,一时间中国版ins、意图称霸图片社交、趁小红书下架抢占用户等等说服层出不穷。今天我们就从一个设计师的角度,看看绿洲这款产品有什么不同。

绿洲是什么

绿洲是一款社交产品,从已经看到的产品功能和内容上,类似ins,也就是说他是一款图片社交产品,由新浪推出,目前处于内测阶段,除官方邀请的kol外只能通过邀请码注册使用。

社交产品在国内难做大家都知道,原因也不必再说,但社交产品一旦做成产生的巨大利益和助推力又让国内大大小小的公司都在向这个宝藏发起冲击。那么为什么新浪选择的是图片社交产品呢?

为什么会选择图片社交

首先是基于国内市场,还没有出现一家独大的图片社交产品,不像国外已经有了ins,国内的图片社交领域勉强还能算作是「蓝海」,加上最近小红书下架导致市场有短暂的空白,大批kol和内容生产者出走。也正是推出这款产品的良好时机。

当然也有一种说法是:国内的社交产品形态存在「跳代」的现象,从文字社交直接跳到了视频社交,并已经有了很成熟、用户规模极大的产品抖音,所以从产品发展形态来看,图片社交产品在国内并没有什么生存土壤。这里我直接说出自己的观点:我认为图片社交在国内还是有机会的,而且机会不小。对此我有以下几个维度的思考:

1. 信息含量和传达效率

首先不可否认的是图片的信息含量是远远大于文字的,使用图片能够更的传达信息和更丰富的情感,想一想过去很多伟大的文学作品往往需要用一本书来体现某些情感和精神。但是在科技社会里,往往是一张摄影作品更能震撼人心,图片中包含的信息更加直观,人物、场景、颜色、故事都可以直接呈现在用户面前,而不需要通过文字进行描写,也不需要运用很多写作技巧进行铺垫。这并不是说图片比文字更优秀,而是说图片的形态在互联网产品中可以更的传达信息和情感。

说到这可能有朋友会说:图片的信息和情感的传达更,那视频也同样比图片的信息含量更多,更,为什么图片社交还有机会呢?这就要说到下一个维度—内容生产门槛。

2. 内容生产门槛

无论是图片社交还是视频社交,内容都是产品中极重要的一部分,例如现在大家在看抖音时,大部分高质量内容都是由专业的内容生产者制作的,其中涉及到选题、剧本、拍摄、剪辑、后期、压缩等等流程,即使不是专业的团队生产也是身兼数职的多面手生产者。流程一长,工作量也就大大增加了。工作量一增加,门槛就会变高。如果不是为了靠抖音赚钱、如果不是为了增粉变现,又有多少人能投入这么多精力和时间去生产内容?内容不多、质量不高又怎么吸引更多用户来使用-参与-生产最后形成闭环?

绿洲则不是这样,虽然用户可以上传视频,但主要的内容还是图片,拍一张图片的各种成本要比拍一段视频小太多啦,结果就是有更多的内容生产者可以参与进来,而不是被高门槛拦在产品之外,当你生产了一段内容,至少要发给几个亲朋好友来看看吧?即使只在产品内部发个动态,如果有人为你点赞、评论、又关注了你,至少再拍一点的动力会大一些吧?这样循环下去,内容、用户就全部都有了。举个极端一点的例子,如果微信只能发图片,那么还会有这么多人使用吗?原因也是图片的生产成本要大于文字(非文学作品的文字)。所以我认为,内容生产门槛也是绿洲的优势之一。

3. 信息接收程度

最后一点则是大众用户的信息接受程度。我们可能从新闻报道上经常能看到体育记录的突破,例如几十年前科学家预言了人类短跑极限早就被突破几十次了。或者是看到人类平均寿命在过去几百年的时间里提高了几十岁。这里我想说的是:当互联网尤其是移动互联网普及之后,人类对于信息可接收量增加了多少?过去看纸质书和现在拿着手机,每天阅读文字图片视频等等能达到过去的多少倍?这里我没有找到专业机构的研究报告。但是这个增长程度我想大家的意见应该会十分一致。

信息接收能力的提高会倒逼着改变产品形态、过去我们每天只能接收2000个文字和50张图片,所以我们习惯看报纸。现在我们每天能接受10000个文字和300张图片,所以我们在用头条用微信用微信用抖音。当用户有了适应一项改变的基础,那么必然会出现满足用户这种进化的产品。抖音是,绿洲可能也是。

4. 磨刀霍霍的kol和网红

前几年无论公众号、头条号、直播很是催生了一批实现财务自由的幸运者们,但更多的确实没有抓住平台早期红利的玩家,在众多自媒体和直播平台都成熟之后,想要从中获利是越来越难了。这时候出现了一个新兴的、并且很有潜力的新平台。那这些错过了上一波机会的预备役kol和网红们会不会蜂拥而至呢?而更多的现有kol和网红为了巩固自己的地位、扩大影响力和粉丝规模也同样会去参与一番。去了之后为了自己的利益更是会给更多人安利这个产品。

说他有潜力是因为它占据的天时、地利与人和。天时已经说过,市场潜力巨大又缝小红书下架,地利则是国内暂无一家独大的图片社交产品,人和则是拥有几亿活跃用户的微博作为后盾。如此的产品,再加上利益驱动。想必内容方面已经问题不大了。

5. 内测+邀请的机制

这几天下载了绿洲的朋友们应该都知道,如果你没有邀请码的话即使下载了也是不能注册的,整个产品还处于「内测阶段」 。只有前期官方邀请的部分kol和少量内测用户才能使用,每个内测用户又只能邀请一定数量的更多用户。并且整体内测数量也有限制。截止9月4日下午内测人数已经满了,之后即使有邀请码也不能注册使用。那么这个内测+邀请机制有什么好处呢?

有种说法是饥饿营销,利用用户越得不到越想要的心理来获取更多用户。但这种说法有点说不通,因为内测总人数是有限制的。并且现在不是几年前了,可能今天你内测限制注册人数那明天用户就把你忘了,毕竟现在产品这么多,娱乐活动数不胜数,已经不是十年前那个产品稀缺的时代了。我大概有两点猜想,一是产品方希望通过内容试水,看看产品在市场上的反馈,进而做出符合国内用户习惯的修改再大规模推广(嗯,之所以要做符合国内用户习惯的修改是因为他太像ins了~),二是产品方希望变「爆火三天死」为「细水长流」,之前的马桶MT、聊天宝、包括子弹短信等等产品在刚刚发布的时候都是非常火爆、用户在短短几天之内就过了百万大关,但是现在呢?还有多少人在继续用?增长曲线还敢贴出来吗?而使用了内测+邀请机制则不同,一方面可以保持用户维持一定数量的增长,一方面又不会因为用户的三分钟热度而快速冷却,对于社交产品而言,如果你身边有朋友在用,那你继续用的概率就会大很多。如果你发现你身边的朋友在用,那即使你已经卸载了也有一定可能重新下载回来再用一用,也就是用细水长流的方式不断召回之前的用户,用留存做增长。

上面说了一些我为什么认为绿洲(或其他图片社交产品)有一定生存空间的原因。下面我们来看看绿洲中一些很不错的设计细节。

一些设计细节

1. 条目巨大,更重视内容质量

用户的一条动态(在产品设计中我们一般习惯称之为条目,下面以条目称呼它)往往占据了一整屏的空间,作者使用的还是长度较长的全面屏手机依然如此。这种设计可以在一定程度上说明产品方比较重视内容。做产品设计的朋友应该都知道:条目占据的空间越大一般包含的信息量就越多,也更容易形成转化,对应到绿洲中这个转化就是点赞、评论、关注等等用户的操作。一旦用户做出这些操作,就会对产品形成更深度的使用习惯,也就有更多可能性变成活跃用户。当然条目占据空间过大同样有风险,也就是如果这一条内容的质量不够高的话用户可能会产生流失,因为用户可能并不会继续向下滑动去看下一条内容了。所以一般内容质量较高的产品条目占据的空间较大,质量较低的产品条目占据空间较小,希望一屏之中能够容纳更多数量的条目,用户数量换质量希望其中能有一条对用户形成转化。所以绿洲的这个设计细节作者猜测是产品方重视内容的体现。

2. 上传图片,实时看到效果

如下图:

当我们在上传图片时,页面上部为图片的放大展示图,页面下部分为缩略图,用户可以在选择图片时实时看到自己选择的图片的细节,举个例子,如果某漂亮妹子想发张自拍,但是相机里保存的是几十张连拍照片,此时她就可以在选择图片时直接看到自己当前选择的图片是否是自己最满意的一张。而不需要上传后才能看到,或是切换到系统相册中去查看,再记住那张自己最满意的照片的位置再回来重新上传。

我们常见的产品中上传照片时一般都是直接显示缩略图,好处是页面效率高一屏可以展示更多图片,坏处是不能直接看到照片的细节。这种设计比较好的平衡了这个问题。关于上传图片的优秀设计我们前几天还分享了ZAO里面的一个设计案例,下图是ZAO核心流程中的两个页面,是选择「影视剧片段」和「上传替换素材」的页面:

在此页面选择要替换的人物,点击后进入下图上传素材,选择从相册选择。

我们可以看到,当我们选择从相册上传素材进行替换时,系统已经自动对相册内的图片进行了判断,在用户上传照片之前就对照片清晰度是否合适进行了提示,而不是上传后再给一个弹框。

作者对这个设计细节大致想法如下:

  • 提高操作效率
  • 避免上传后再进行提示打断用户自然的操作流程。
  • 避免因操作与预期不符产生的转化率降低
  • 加快内容生产速度,同时也就加快了产品传播速度
  • 避免因上传素材质量差而导致平台内容平均质量下降
  • 大家可以看到上图中一张共享单车的照片的清晰度是满足要求的,但是很明显我不能用它替换角色 。如果加上人脸检测的话效率会高(当然成本也会更高)。

与上面案例相关的东西作者还想起了闲鱼:

一是闲鱼中,当用户上传的商品图片比较模糊时系统会提示用户重新上传,以提高二手物品的卖出速度。这里的设计是在用户上传图片进行提示,作者觉得就没有ZAO中这个设计体验更好。

3. 更强、更方便的互动方式

社交产品中,用户之间的互动率是一个十分重要的指标,对内容的点赞评论可以很大程度上加强用户粘性,使用户与用户之间产生关系链,这样用户流失的概率就会小很多。一般的产品中常见的功能像点赞评论在绿洲里也有了不一样的变化,并且体验还真的不错,如下:

当用户对某一条消息产生了互动的倾向时,可以直接使用三个表情表示不同的情绪,分别是爱心、鼓掌和笑哭,如果想要评论的话只需要点击WOW按钮系统就可以自动生成一句评论,不需要用户自己思考写什么内容,这样用户进行评论操作的成本就大大的降低了。如果对生成的评论不满意的话还可以再次点击生成不同的评论。

4. 不足的用户认知负荷

当然作者同事也看到了体验不是很好的设计细节,如下图产品中使用了太多无文字按钮,导致根本不知道这些都是什么功能,绿洲对自己的介绍是更清爽的朋友圈,如果说是为了让界面更干净简约才使用了这样设计的话我觉得有些本末倒置了,国内用过ins的用户毕竟还是少数,对于大部分用火狐来说绿洲还是一款陌生的产品,在陌生的产品中使用这种不能明确表达功能含义的无文字按钮则让用户十分迷茫,大大增加了认知负荷。

昨天晚上作者在家附近的面馆吃饭,正在等着自己的油泼面、羊肉串、拍黄瓜、小酥肉、酸梅汤的时候看到了一件事:某50岁左右的大叔点菜说想要一份凉皮。

服务员问:您是要麻酱凉皮的还是秘制凉皮?

大叔犹豫一下,问:秘制凉皮是什么的?

服务员答:就是有凉皮和面筋掺一块,放上醋、盐、香油、辣子,酸甜口的可辣可不辣。

大叔继续犹豫了一下说:那给我来个麻酱凉皮吧。

故事到这开始有点意思了,这个用户(大叔)对秘制凉皮是没有概念的,虽然经过服务员解释之后明白了是什么,也知道了口味,但是对于「秘制凉皮」这个概念的熟悉程度还是比较低,所以最终没有选择它。这和我们在进行产品设计时对一些文案的设计很像。大家第一眼看过之后能明白是什么意思吗?反正我是没有明白。不明白就会产生认知负荷。也就会影响向下的转化率。当用户点击几次没有找到自己想要的东西之后,他也就走了,去哪了呢?可能是「商城」「历史文章」「限时促销」这些他明白是什么意思的地方。

你只是绿洲,你还不是微信,这样的设计有些为时过早了。

昨天我故意吃的比较慢,观察了一下麻酱凉皮和秘制凉皮的购买人数,在大约40分钟的时间里,大约有7人选择了麻酱凉皮,2人选择了秘制凉皮。服务员大约解释了4次什么是秘制凉皮,每次大约需要20秒,加上顾客犹豫的时间,这40分钟里服务员大约多花了3分钟时间解释、等待用户做选择。

如果把这种场景放到我们的产品设计中则意味着更低的效率、更少的使用时间、更低的转化率。以及推出新功能之后更少的使用率。现在很多产品中对功能的命名都基本一致、一些常规图标的样式也都基本一样。目的也就是为了减轻用户的认知负荷。

转发和重定向的区别

seo达人

简单介绍

多个页面和 servlet 组成了一个基于 Java 的 web 应用程序。JSP 使用转发和重定向两种方式将控制权从一个 servlet 传递到另一个 servlet 或者 JSP。



转发(Forward)方法: 将请求从一个 servlet 转发到 web 应用程序中的另一个资源,这个资源可以是一个 servlet、JSP 页面、或者 HTML 文件。



重定向(Redirect)方法: 方法将请求重定向到另一个 web 应用程序。使用转发( Forward )方法无法完成此操作。如果一个重定向命中了同一个 web 应用程序的不同资源,那么它使用的 URL 将与原始请求的 URL 不同。如果你不想响应一个请求,你可以将请求重定向到一个不同的 URL,然后浏览器将会将你的新请求重定向到你提供的新的 URL。这篇文章详细解释了两种方式的不同之处。



什么是转发(Forward)

在基于 web 的系统或者应用程序中,通常需要在不同的资源或 JSP 之间转移控制权。例如:你如希望从电子商务网站下单,则需要先进行注册,然后才可以继续。如果你还未在他们的系统中注册,那么购物车界面可能会将控制权转移到负责注册过程的 JSP 表单。转发( Forward )方法即是用于此目的。它用于将请求从一个 JSP 转发到统一上下文中的另一个资源。



什么是重定向(Redirect)

此方法也用于转发 HTTP 请求,但与转发( Forward )不同的是:它是一个两步过程,其中重定向发生在客户端到不同的应用程序。Redirect 方法将用户重定向到新的 URL。客户端的浏览器会自动对来自服务器中的重定向表头中指定的 URL 发出新的请求。它需要与客户机进行往返通讯,因此相对来说会比转发( Forward )方法慢些。



转发(Forward)与重定向(Redirect)区别

转发(Forward)与重定向(Redirect)的描述

Forward() 方法用于将请求从一个 JSP 转发到另一个 JSP,或从一个 JSP 转发到另一个 servlet,或从一个 JSP 转发到 web 应用程序的另一个资源。控制是在容器的内部传递的,浏览器/客户机不参与此过程。Forward( )方法在 RequestDispatcher 中声明。



Sendredirect () 方法在 HttPServletResponse 中声明,用于将客户端请求重定向到不同服务器或上下文中可用的不同 URL。 通过重定向,您可以将浏览器重定向到完全不同的应用程序。



客户端是否参与转发(Forward)和重定向(Redirect)

这两种方法之间的一个关键区别是 web 容器在 Forward() 情况中处理了所有的内部进程,而且 URL 在客户端的浏览器中不会改变,因此客户端/浏览器不会参与其中,从而使它们完全不知道动作已经发生。



而在 Sendredirect () 的情况中,该方法设置适合的头部信息和正文内容以将请求重定向到不同的 URL 中,浏览器付负责将新的请求发送到客户端可见的 URL。



执行控制

当在请求时执行 Forward() 方法,当前的请求会被转发到另一个 JSP 页面,对当前 JSP 的处理也会被终止。请求可能会被转发到另一个用 Java 编程语言编写的 servlet,或者一个静态的 HTML 页面。



一个 SendRedirect() 请求只是简单告知浏览器转到另一个 URL,将执行控制发送到 web 应用程序之外。它使用一个两步的过程来指示浏览器的 URL 发出另一个将控制转发到另一个客户端的请求。



速度

Forward () 在服务器内运行,执行速度比 SendRedirect () 快。



重定向必须通过浏览器,然后等待浏览器发出新的 HTTP 请求。 一个重定向使得服务器发送 HTTP 响应状态代码 302 和一个包含新的 URL 的位置头到浏览器,并且在浏览器收到状态代码 302 之后,它对位置头中的 URL 发出一个新的请求。 这需要与客户机进行往返通信,这使得它比 Forward () 相对慢一些。



转发(Forward)和重定向(Redirect)比较图表

转发(Forward) 重定向(Redirect)

用于将请求从一个 JSP 转发到另一个 JSP,或从一个 JSP 转发到另一个 servlet,或从一个 JSP 转发到 web 应用程序的另一个资源。 用于将客户端请求重定向到不同服务器或上下文中可用的不同 URL。

Forward( )方法在 RequestDispatcher 中声明。 Sendredirect () 方法在 HttPServletResponse 中声明

不涉及客户端/浏览器,web 容器在内部处理该过程。 当客户端将 URL 作为一个新的请求后,控制权将会转移至客户端或浏览器。

当一个组件执行业务逻辑并与另一个组件共享结果时,它最有效。 当客户端应从一个页面重定向到另一页面时,此方法效果最佳。

它在服务器内运行,并且比重定向执行得更快。 它比转发慢,因为它需要与客户端进行往返通信。

使用时,原来的 URL 请求不变。 原始的 URL 请求会改变。

两种资源都必须属于同一上下文。 将请求重定向到不属于当前上下文的其它 URL。

转发(Forward)和重定向(Redirect)总结

学习转发方法和重定向方法之间的区别是 Java 开发人员最重要的部分之一。 虽然控制器可以在处理请求结束时执行转发(Forward)或重定向(Redirect)方法,但它们有自己的一组用途。



大多数情况下,您会使用 Forward () 方法,因为它比 SendRedirect () 稍微快一点,而后者实际上需要与客户机进行往返通信,使其比 Forward() 更慢。 通过重定向,你可以将浏览器导向到另一个应用程序。 这是转发无法做到的。



简而言之,当一个组件必须执行业务逻辑并与另一个组件共享结果时,转发(Forward)工作效果最好,而当客户端应该从一个页面重定向到另一个页面时,重定向(Redirect)工作效果最好。



以上内容翻译自:

Difference Between Forward and Redirect。

能力有限,还望斧正。

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

敏捷用研的最佳实践—如何让好的设计快速落地

雪涛

2019年7月20日,UXRen北京举办了《如何通过体验设计赋能产品增长》的沙龙分享,本文基于嘉宾 何晓頔(搜狗高级用户研究工程师)的现场分享总结而成。

何晓頔2015年开始从事用研工作,2018年加入搜狗,目前在搜狗搜索担任用户研究工程师;期间支持搜狗搜索相关产品的用户研究工作,完成搜狗阅读app、搜狗搜索app、搜狗图片搜索改版研究,搜狗医疗搜索系列研究,搜狗翻译app调研等项目;擅长全局思考问题,综合考虑各方诉求,通过研究方法的熟练运用,需求的深度解读,结果的产出,不断提升用研的影响力及价值。

 

沙龙笔记:

1. 为什么要敏捷用研

由于用研资源的紧张,传统研究模式周期长,使得用研游离在项目边缘,融入难,导致时效性跟不上整个项目的推进,出现信息不对等的情况,从而造成研究方向的偏差,而且研究结果也会和设计、产品的需求脱节,造成落地难的问题。

敏捷用研可以很好的解决这个问题,它可以很好地融入在项目的各个阶段中,能够在3-5天内地完成调研需求,真正融入到整个项目的流程中,在每个阶段都以结果导向的解决问题,形成每个阶段的连接器。所以说他以用户思维为核心,通过用研的驱动性,增加用户在整个项目中的参与度和体验感,不仅能够实现成本的减少,还能提高响应的效率,实现信息层面的对等,还原用户的真情实感,性价比高的同时还提升了用研的价值。

敏捷用研可以在敏捷项目的各环节中发挥作用,而且在不同阶段可以有针对性的解决问题。

  1. 概念验证:
    在规划阶段可以进行概念的验证,挖掘用户需求,以矫正概念方向;
  2. 方案验证:
    开发阶段可以对方案进行验证,对方案进行优化,提升效用;
  3. 体验评估:
    测试阶段可以进行体验评估,以减少产品的使用问题,及时进行优化调整;
  4. 改版调研:
    迭代阶段可以进行改版测的调研,以获取用户对改版效果的评价,收集需求,为迭代提供需求输入。

 

2. 敏捷用研案例:阅读书城改版研究

2.1 改版前

需求分析

  • 明确改版目标:如何提高首页CTR
  • 沟通当前产品出现的问题:书城页改版时间已久,现有的产品功能及形态已不能满足用户需求

用户点击行为研究

  • 了解用户对旧版书城页的浏览及访问行为
  • 了解首页各模块流量分布(点击热力图)

书城结构布局研究

  • 分析书城页的结构布局,产品功能点,产品交互、视觉、运营亮点
  • 找到旧版书城页问题
  • 竞品分析:QQ阅读、掌阅、书旗

2.2 改版中

用户需求挖掘

  • 挖掘用户阅读小说的习惯、用户阅读的心理模型、用户找书的场景及途径
  • 用户在app中找书的痛点,探索可能的机会点
  • 方法:用户体验地图

搜索行为探索

  • 用户搜索时找书难、模糊搜索找不到书
  • 了解用户日搜索query分类、 query与书单的匹配度,搜索请求量等相关用户搜索需求

2.3 改版后:改版效果评估

  • 整体CTR改版效果
  • 各改版模块CTR

2.4 项目合作模式

 

3.   敏捷用研经验

3.1 招募策略——健全流程

招募问卷设计

  • 招募问卷模板化
  • 设置预先摸底的问题

招募渠道

  • 充分利用用户群
  • 完善内部招募渠道
  • 周围朋友

招募用户特征及数量

  • 根据实时调研结论,不断调整
  • 5个用户为基础,随着研究需要逐渐增加

奖励机制

  • 在能力范围内,提供有一定吸引力的奖品

3.2 研究策略——模板化、透明化

模板化:搭建问题包,分门别类、系统整理,随时调用、整合

  • 访谈提纲设计模板化
  • 问卷设计模板化
  • 数据分析模板化

过程透明:边访谈边总结,根据需求,随时调整、直到数据样本趋于稳定

 

3.3 沟通策略——循序渐进

结合迭代研究模式,从小范围调研起步,与客户及时共享研究进度和成果,循序渐进:

  • 随时响应
  • 尽早汇报
  • 持续沟通
  • 忽略形式

3.4  参与策略

  • 全民调研,整合设计和产品资源,配合进行研究,提升效率

3.5 小结

敏捷调研不是为了快而快,而是快速解决产品需求和设计问题打造好的体验!

【Q&A】 宝珠、殷朝、何晓頔答现场观众问

问题1:内部用户招募。国企,公司logo优化调研, 因为时间和成本的关系,邀约的是公司的内部员工(年龄集中在40-50岁区间段),调研的结果内部员工更偏好原logo的微小变化的版本,与设计方期望差别非常大,想知道是否是不应该找内部员工测试。

回答:就上述问题,不建议找内部员工测试。

内部招募是一种短平快的用户招聘渠道,但是,

  1. 内部招募需要考虑公司的特点和情况,内部招募更多适用于内部用户与实际用户层贴合度高的情况,且如果调研方有资源,对时间成本要求不是非常高的情况下,还是建议找真实的潜在的用户。
  2. 内部招募需要考虑测试内容和人口学的关系,比如上述调研的问题在于logo类调研不适宜找内部员工做调研,因为对品牌认知评价来讲,公司员工的属性本身就是一种较大的影响变量,会影响品牌认知评价判断。

 

问题2:概念测试。概念型产品可以用电话访谈的形式进行测试么

回答:概念型产品,由于属于市场上未出现产品,很难在电话中通过语言描述的方式让用户理解和想象出来,因此,概念类测试不建议用问卷和电话访谈的方式,建议通过面对面访谈+高保真原型展示的方式进行测试,如果实在满足不了高保真,哪怕线框的示意图都比单薄的语言描述更强。

 

问题3:用研考核机制。用研的输出建议,有些被采纳,有些不被采纳,采纳的建议到产品成型很多已不是建议的“原型”了,如何衡量用研结果的直接作用。

回答:

  1. 摆正心态,用研不是万能的,是用户和公司之间能保持连接的纽带,用户侧的信息输出,建议采纳过程中需求方需要考虑的问题很多,产品KPI、产品的方向、设计的合理性、开发资源等等。
  2. 用研和需求方之间不是对立的,衡量用研结果的价值不应该是去“抢功劳”,跟合作方在价值上“分清楚”来证明自己的价值,而是与你的合作方“和谐相处”,通过“共创式研究”,以共赢的方式分享结果。
  3. 用研KPI设定:
    1)资源角度,KPI定为服务满意度,即把自己当做“甲方”里的“乙方”,需求方给用研的满意度评价(如邮件、正式的夸张、满意度调研,不限形式);

  1. 2)OKR的角度,用研的核心价值为“洞察”,回溯哪些洞察结果可以服务到公司的大目标上。这里依然需要注意的是,用研的定位更多为服务型的“资源”,“资源”必须嫁接在业务上,不要隔离业务衡量用研的价值,用研的价值更多体现上帮助其他部门做“洞察”上,无法决策后期需求方的产出方向,但只要是“有意义的洞察”都是有价值的。                文章来源:uxren

全球都在用的Booking,是如何做设计改版升级的?

雪涛

每一次学习改版案例,不仅仅只是去看在视觉层面的变化,更多的应该是要学习到作者改版背后的思考。为什么要这么改,原因是什么,目的又是什么,怎么做,有哪些限制等等,有很多东西要去思考。所以,带着问题并结合自己实际中所做的项目来看案例,应该会是一个很有收获的过程。

项目背景

Booking.com缤客 是一家荷兰初创公司,并已经发展成为全球最大的旅游电子商务公司之一。
在Booking上,旅客可以选择世界上任何一处的住宿地点,包括公寓,度假酒店,民宿,五星级豪华度假村,树屋甚至冰屋等等。每天,通过平台预订的房间数超过155万。无论是商务旅行还是休闲旅行,人们都可以快速轻松地预订到理想的住处。

竞品分析

自从Booking发布以来,许多竞争对手都采用类似的商业模式疯狂跟进,抢占市场,并且在某些方面比Booking本身做的还好。

在调研的前期阶段,我去搜集了一些竞争对手和类似的平台,分析UI,用户体验,用户地图,信息架构和关键功能。但是我并不会花太多时间过于深入的去分析这些产品,因为我希望将重点放在Booking这个产品本身的诉求上。

使用场景

在之前的调研过程中,我发现了许多不同的使用场景,经过汇总归集,我集中关注以下3个场景:

  • 场景1:用户知道其行程的日期和目的地(默认场景)
  • 场景2:用户明确了日期但对其旅行的目的地不清楚
  • 场景3:用户知道目的地但不确定其旅行日期

典型用户

在进一步的研究中,我明确了4位具有不同需求和不同目标的典型用户,这些数据对于改善不同用户的体验非常有用。

这个分析的目的是通过梳理最佳的用户流程并提升产品体验,来为不同需求的用户提供最好的用户体验。

△ 数据来源:在线研究和用户访谈(30个用户样本)

用户反馈

收集用户评论,从中我收到了很多有价值的反馈,这些评论中没有特别明确指出是可用性或功能性的问题。我将这些反馈分为4类(译者注:对反馈的问题进行提炼整理):

  • 预订被取消
  • App的Bug
  • 投诉的处理效率
  • 反馈的进度

毫无疑问,最相关的是预订被取消的问题。太多用户会注意到不合理的费用或与房间的主人取得联系时遇到困难。

用户访谈

基于30个用户样本,我试图获得进一步的用户反馈,从中注意到以下的几点事实:

  • 与其他平台相比,booking的平均价格通常更高
  • 产品过于突出好评,用户很难发现一些真实的差评
  • 当房屋主人接收到用户的回复时联系用户也很困难

我想引用一段话,来总结这里面遇到的问题,这段话也蛮有意思的,它说的是:

「与其他应用比较来看,套路显得有点多,会让你觉得一切看起来都蛮划算,总是想多卖一些东西给你。」

用户痛点

总结之前的分析,我提出了以下几点观点:

  • 没有一个完美的解决方案能够满足所有用户,用户需要尽可能多的掌握有用信息。
  • 没有的功能没有太多考虑到个性化需求。
  • 可以改进UI并使用户更加集中于他的目标,而不是完全「以推销为中心」
  • 优化用户与房东之间的联系问题

解决方案

从用户痛点出发,尝试找到合适的解决方案,来提升产品体验。

1. 主页

总的来说,我对首页进行了大手术。主页的搜索功能已经完全重新设计,减少过多的干扰信息。

导航:我设计了一个新的导航栏,剥离出「已保存」功能,这样用户就可以快速找到自己所收藏的商品。此外,我也优化了「交易」的模块,后面我会详细的说说这块的改动思路。

其它功能 :至于之前的版本,我保留了搜索和相关推荐的功能,重新设计界面以改善UI的可用性。

2. 社交功能

如今,社交网络在用户的生活中扮演重要的角色,那没理由在booking中做的这么差。我搞了一个新功能,允许用户关联自己的好友并查看他们的选择,包括他们的评价(喜欢/不喜欢)。我已将此功能放置到主页的下方,因为我希望在将其推广到其他模块之前收集更多有关它的数据。

3. 搜索功能

把这个功能分解为多个步骤。在输入第一个词后,即使没有指定日期或其他信息,也能显示相匹配的酒店。此外,我也加入了语音搜索,使搜索更容易。基于之前我对不同用户角色的定义,搜索的结果将根据最后的信息进行推荐:

  • 1名成人 ——背包客 ——酒店
  • 2名成人——度假夫妇——酒店,宾馆或B&B(某种酒店形式)
  • 2名成人+儿童——家庭——民宿公寓或酒店
  • 1名成人+商务选择——商人——酒店

4. 列表页面

列表页针对易用性方面做了整体的优化:

  • 我将筛选功能从3个按钮更改为2个按钮以减少用户的操作步骤——将它放在页面底部,方便使用
  • 我添加了标签功能来更好的区分属性类型
  • 在第一时间向用户展示物业的主要设施特点。注意:根据不同的用户,可以智能突出显示不同人正在寻找的不同信息。
  • 我将报价的方式转换为「单晚」而不是「总价」,以便在不同商品之间进行比较

5. 详情页

我列出许多可以在详情页面中加入的修改。将总价格突出显示,以免有些隐形消费用户可能会被忽略。

增强了一个与评论相关的次要功能,允许用户通过不同标签筛选它们。

6. 交易功能

在优化开始时,我确定了操作场景2—— 「用户还不知道自己的目的地」作为优化方向。为了提供更好的用户体验,我增加了一个新的功能,用户可以在其中找到不同目的地的区间。利用筛选功能,用户可以选择最适合其需求的区间(区间 – 大陆 – 国家等…)

动效原型

最后,我还设计了一个整个项目的动效原型,把之前所有重设计的页面串联起来。

结语

由于时间限制,分析和结果是基于我的个人经验和少量数据,需要进行深入分析和其他测试,以便完善和验证解决方案。

文章来源:优设网

vue-cli3插件初体验

seo达人

vue-cli3发布自2018年8月,距离现在还不是特别久,最好搭建项目刚好用到,所以写下这篇文章,记录一下踩坑经历。

vue的作者说过,vue-cli的本质是模

版的拉取,太多的配置导致了模版的难以维护,所以重构后的版本提供了插件的功能,一个插件对应一个功能,这样避免了多个模版,也使得cli维护性得到提高,这也是本篇文章的核心介绍内容。

我对cli3的理解是,一方面扩展了cli2的核心能力 ,一方面封装了webpack逻辑和配置。在过去要去做一个cli,通常需要阅读cli2的代码,cli2的核心模块分别是 generator,prompts,template,git-repo,并用同样的方法去做一个cli,这样其实成本不小,cli3的插件就是提供了这样一种能力,你用他的规则,去做一个npm包,并发到仓库,就可以获得这种能力。

首先,先介绍一下vue-cli3,他的发布带了哪些新功能呢?我总结一下,大概有以下5点:

1.功能丰富。这点相信大家都很好理解,他实在太好用了,模版里包含了大多数业界比较新的功能,可以一键集成typescripts等类型定义工具, eslint/tslint等语法检验工具,风格规范,prettier,husky等格式化工具,还有postcss、pwa、vue-cli-server等等。

2.提高封装性和扩展性。这点指的是vue-cli-server,在过去webpack的逻辑和配置在项目里独立维护,各个项目之间就像孤岛,vue-cli-server就像一个纽带,连接起了各个项目,为项目升级webpack提供便利性,并且通过一份配置,提供个性化配置。

这里顺带扯一下vue.config.js, 这个东西就是用来个性化配置webpack的,他提供了很多的配置项,具体可以看官方文档:

https://cli.vuejs.org/zh/config/

我们挑几个常用的来讲:

configureWebpack,这个几乎是用的比较多的,简单的方法,可以通过配置的方式配置,如下所示:

 
    
  1. module.exports = {
  2. configureWebpack: {
  3. plugins: [
  4. new MyAwesomeWebpackPlugin()
  5. ]
  6. }
  7. }复制代码


这份配置,最终会被合并到原来的配置里,不会覆盖。

复杂的方法,可以往这个字段传一个函数,如下所示:

 
  1. module.exports = {
  2. configureWebpack: config => {
  3. if (process.env.NODE_ENV === 'production') {
  4. // 为生产环境修改配置...
  5. } else {
  6. // 为开发环境修改配置...
  7. }
  8. }
  9. }复制代码

这样就可以在一个函数里做一些简单的逻辑,config是webpack config,你可以直接修改config对象,也可以返回一个对象,这个对象最终也会被合并会webpack对象。

第三种方式,是通过webpack-chain来链式调用,代码如下所示:

 
  1. module.exports = {
  2. chainWebpack: config => {
  3. config.module
  4. .rule('vue')
  5. .use('vue-loader')
  6. .loader('vue-loader')
  7. .tap(options => {
  8. // 修改它的选项...
  9. return options
  10. })
  11. }
  12. }复制代码

3.提供图形化管理界面,最所周知,gui易懂,cli,vue在降低学习门槛这方面,已经是非常好了。

通过vue ui指令,可以查看编译各个模块的情况,模块依赖情况,插件的情况,非常便于管理。

4.便捷性。vue-cli-server不仅支持项目的编译,也支持单文件的编译,具体的方法可以看官网介绍。

5.提供了cli的核心能力,也就是问询,模版渲染,文件生成这几大核心功能。具体的示意图可以看如下:


以上是cli2的核心模块,需要引用hbs,inquirer.js,metalsmit等基本模块,cli3的插件机制基本帮我们封装好了,我们只需要根据插件的规范,就可以获取这种能力。

由于有的读者可能对cli2的流程比较陌生,所以我想简单描述一下cli2的工作流程,如下图所示:


首先,cli2提供init指令,执行这个指令,会去远程拿模版文件,并拉到本地用户目录的.vue-template的文件夹,然后通过meta里问题,去问你,然后生成最终模版到你执行命令的目录。

说完vue-cli2,我们来看看vue-cli3的插件是怎么样的?

首先根据插件的位置,我们分成了cli插件,和service插件。cli的插件有完整的开发目录,所能做的事情也比较多一点,service插件是一份js文件,导出一个函数。

cli插件的目录如下所示:


具体的用发可以在官网了解到:

https://cli.vuejs.org/zh/dev-guide/plugin-dev.html#cli-%E6%8F%92%E4%BB%B6

那么他们是怎么工作的呢?

cli的代码主要在@vue/cli 下面,他的大概的流程如下图所示:


@vue/cli/bin/vue.js:

 
  1. program
  2. .command('add <plugin> [pluginOptions]')
  3. .description('install a plugin and invoke its generator in an already created project')
  4. .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  5. .allowUnknownOption()
  6. .action((plugin) => {
  7. require('../lib/add')(plugin, minimist(process.argv.slice(3)))
  8. })
  9. program
  10. .command('invoke <plugin> [pluginOptions]')
  11. .description('invoke the generator of a plugin in an already created project')
  12. .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  13. .allowUnknownOption()
  14. .action((plugin) => {
  15. require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))
  16. })复制代码

首先,执行vue指令,会执行@vue/cli/bin/vue.js,这里定义了vue add , vue invoke,vue build,vue serve,等指令,可以看出,add指令其实是包含invoke指令的,add指令主要是安装一个包,并且触发generator.js,invoke主要是触发generator.js。

然后再来看@vue/cli/lib/add.js,

 
  1. const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : 'npm')
  2. await installPackage(context, packageManager, options.registry, packageName)复制代码
 
  1. const generatorPath = resolveModule(`${packageName}/generator`, context)
  2. if (generatorPath) {
  3. invoke(pluginName, options, context)
  4. } else {
  5. log(`Plugin ${packageName} does not have a generator to invoke`)
  6. }复制代码

add.js主要安装包,然后执行invoke模块,我们再看看invoke模块做了什么。

@vue/cli/lib/invoke.js

 
    
  1. const generator = new Generator(context, {
  2. pkg,
  3. plugins: [plugin],
  4. files: await readFiles(context),
  5. completeCbs: createCompleteCbs,
  6. invoking: true
  7. })复制代码

invoke里主要实例化generator类,然后把你的插件当成参数传给类,generator类算是vue-cli的核心类了。

@vue/cli/lib/generator.js

 
  1. plugins.forEach(({ id, apply, options }) => {
  2. const api = new GeneratorAPI(id, this, options, rootOptions)
  3. apply(api, options, rootOptions, invoking)
  4. })复制代码

这个类主要负责执行你的插件,然后把generatorapi作为参数传入插件的generator.js导出的函数。

具体的vue-cli插件的开发是怎么样的呢,我写了一个demo,用在模拟多项目的ci模版管理,通常每个项目都有一份.gitlab-ci.yml模版,所以我们一般可以抽出一个公共的ci模版来管理,这里我用cli插件来管理,真正的项目可能不具备可行性,这里我只是用来写一个例子。



目录结构大概如上所示,执行vue add foo后,就会出现propmts对话框,然后选择答案后,就会根据配置生成模版到你的根目录下。


_gitlab-ci.yml ,根据问题选择是否用私有npm仓库:

 
  1. script:
  2. <%_ if (options.config === 'npm') { _%>
  3. - nrm add companynpm http://xxx.y.cn:XXXXX/
  4. - nrm use companynpm
  5. <%_ } _%>复制代码

prompts.js,主要一些问题的设计:

 
  1. module.exports = [
  2. {
  3. name: 'config',
  4. type: 'list',
  5. message: `是否需要切换内部源:`,
  6. choices: [
  7. {
  8. name: '需要',
  9. value: 'npm',
  10. short: ''
  11. },
  12. {
  13. name: '不需要',
  14. value: 'npm',
  15. short: ''
  16. }
  17. ]
  18. }
  19. ]复制代码

generator.js 这个模块很简单,直接渲染模版

 
  1. module.exports = (api, options, rootOptions) => {
  2. // 复制并用 ejs 渲染 `./template` 内所有的文件
  3. api.render('./template')
  4. }复制代码

service插件主要放在项目本地,是一份js代码,然后导出一个函数,通过package.json配置指向这个js文件的路径,


service主要依赖的代码在@vue/cli-service里,首先先执行@vue/cli-service/bin/vue-cli-service.js文件,


 
  1. const Service = require('../lib/Service')
  2. const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
  3. .....
  4. service.run(command, args, rawArgv).catch(err => {
  5. error(err)
  6. process.exit(1)
  7. })复制代码

该文件实例化Service类,这个类是service插件的核心类,然后再执行run方法。

再来看看@vue/cli-service/lib/Service.js的代码:

首先构造函数执行resolvePlugin,把官方提供的插件和项目里的插件都加载进来,

 
  1. constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {
  2. this.plugins = this.resolvePlugins(plugins, useBuiltIn)
  3. }复制代码

resolvePlugin这个函数主要在这里引入本地的插件:

 
  1. resolvePlugins (inlinePlugins, useBuiltIn) {
  2. // Local plugins
  3. if (this.pkg.vuePlugins && this.pkg.vuePlugins.service) {
  4. const files = this.pkg.vuePlugins.service
  5. if (!Array.isArray(files)) {
  6. throw new Error(`Invalid type for option 'vuePlugins.service', expected 'array' but got ${typeof files}.`)
  7. }
  8. plugins = plugins.concat(files.map(file => ({
  9. id: `local:${file}`,
  10. apply: loadModule(file, this.pkgContext)
  11. })))
  12. }
  13. return plugins
  14. }复制代码

run方法又会执行init方法,在该方法内部执行插件:

 
  1. init (mode = process.env.VUE_CLI_MODE) {
  2. // apply plugins.
  3. this.plugins.forEach(({ id, apply }) => {
  4. apply(new PluginAPI(id, this), this.projectOptions)
  5. }
  6. }复制代码


那么service插件要如何来实践,我们来看如下的例子:

首先在package.json配置一下,指向本地的插件my-service.js

 
  1. "vuePlugins": {
  2. "service": [
  3. "my-service.js"
  4. ]
  5. }复制代码

my-service.js的代码如下所示:

 
  1. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  2. const webpack = require('webpack');
  3. module.exports = (api, projectOptions) => {
  4. api.registerCommand(
  5. 'analyze',
  6. {
  7. description: 'start analyze server',
  8. },
  9. (args) => {
  10. // 注册 `vue-cli-service analyze`
  11. let options = projectOptions.pluginOptions.demoOptions
  12. console.log(options);
  13. // resolve webpack config
  14. const webpackConfig = api.resolveWebpackConfig();
  15. webpackConfig.plugins.push(new BundleAnalyzerPlugin());
  16. webpack(webpackConfig,(err,stats)=>{
  17. if(!err) console.log('打包成功')
  18. })
  19. },
  20. );
  21. };复制代码

该插件主要扩展vue-cli-service的指令,加了analyze指令,这个指令主要会向webpack的配置增加一个BundleAnalyzerPlugin的插件,用来分析包的大小,当然,这里也是没有太大的现实可行性的,vue-cli 提供了vue ui的Gui界面让你看到打包后各个模块的大小,或者cli的命令,vue-cli-service build --report,也能生一个报告,效果也是一样。


至此,vue-cli和service插件的使用和实现都介绍完了,如果有哪里写的不到位,希望各位大神能提出指正

图解WWDC 设计分会:映射与可供性

雪涛

映射-Mapping

在去餐厅用餐之前,我们还有些时间再了解一项基础设计原理。让我们回头看看在「邻近性」原理当中提到的灯光明暗控制开关。你能仅通过最左侧这个开关的样式看出它所控制的灯光明暗度吗?

如下图这样又如何?

我们之所以能从后者当中进行判断,所依据的就是映射关系。所谓「映射」,即是指,将被控对象的行为规律体现到控件自身的操作方式中,譬如开关把手的上升和下降,对应着灯光亮度的升高和降低。

映射同样体现在多个控件的布局当中,它们的次序应该能够反映出多个被控对象之间的相对位置关系。

我们假设这三个开关用于控制卧室天花板上的三盏灯。依据映射关系而设计的开关位置应该能够帮助人们快速判断出它们各自控制着哪一盏灯。映射原理有助于设计师对控件的类型、位置和次序进行决策。

当映射关系不明确时,我们通常需要依靠文本标签才能理解开关与灯之间的对应关系。这并非完美的解决方案,因为阅读和理解文字需要花费时间和精力,同时人们也难以依靠记忆进行快速操作。

在界面设计当中,映射关系也体现在控件类型的选择上。例如通过滑块(slider)控制文本的横向字间距就是很符合直觉的交互方式。而相比于滑块或是步进控件(stepper),旋钮则更适于旋转操作。

当然,最直接的映射才是最好的映射。为人们提供直接操作目标对象的能力是最为简单、精准、符合直觉的解决方案。macOS 上的鼠标指针操作,或 iOS 当中的手势操作,都可以为人们带来直接操作的体验。

可供性-Affordance

不知各位如何,我是很饿了,这就准备下楼去吃饭。我们在大堂见,然后一起去餐厅。

坐在餐桌前,你会看到面前摆放着一个空盘子。我们能用这个盘子做什么?显然,放些食物在里面。除此之外呢?

盘子很光滑,可以旋转或是滑来滑去。

盘子有一圈宽边,可以抓着拎起来。

我们对于如何与这个盘子进行互动的观点便是可供性的体现。换句话说,盘子的外形特征为我们提供了如何与之进行互动的视觉及触觉线索,使我们意识到哪些交互行为可行,哪些不可行。我们会意识到要将食物放进去,或是将它滑到其他地方。但我们通常不会想要倒水进去,然后端起来喝。

可供性并非物体自身所具备的属性,它更多是在代表行为主体与目标对象之间的互动关系。可供性会因行为主体的差异而有所不同。举个极端些的例子,对我而言,飞盘可以用来抓住或扔出去,而对我的狗来说,飞盘就是单单用来叼的。不过另一方面,碟子对我和我的狗来说都是用来盛放食物的。

由于可供性所具有的主观特性,一个人能感知到的交互特性在另一个人看来则未必如此。当可供性所传达的交互特性与人们的常规行为有着高度关联时,人们会更加容易感知到。

例如,我其实可以把碟子当作茶托,这会是个不错的茶托。但我猜我们大家日常很少真的这样去做,因此我会更乐于将碟子视为盛放食物的容器,而非将水杯放在里面。

我们能从我们所互动过的任何环境及事物当中感知到可达性。当我们走进餐厅时,门的大小及形状可以传达出供人穿过的特性,连续的地面使我们意识到可以在上面安稳地行走。

椅子的造型暗示我们可以坐下,桌子的构造令我们明白可以将物品摆放在上面。

人造物品当中都包含有传达可供性的视觉线索,使人们明白哪些行为可行。清晰的、显而易见的视觉线索可以帮助人们迅速了解如何与之进行互动。

对于 app 界面设计而言也是同样的道理。滑块控件由把手和滑轨构成,暗示着拖拽的特性。

旋钮的样式意味着可以旋转。

按钮则一目了然地传达着可点击的特征。

在以上每一个例子当中,可供性的传达效率都是极高的。事实上,随着时间的推移,我们会越发适应于抽象度不断提升的可供性传达形式。我们所熟悉的界面当中的按钮,无非是现实世界里真实按钮的高度抽象化版本;那四个圆角足以将虚拟与现实两个版本的同一种物体关联起来。

同理,滑块把手周围那细微的投影效果也足以让我们意识到其独立于滑轨之上的操作特性。

而且,仅有的这一点点视觉线索可能都不是必需的,对于很多人来说,一条直线上的一个实心圆足矣传达滑动操作的可供性了。

有时候,可供性也可以通过动效进行传达。在天气 app 中点击主体内容,界面整体便会稍稍上升,暗示着可以通过滚屏来查看更多内容。

无论你使用何种方法,都必须确保 app 界面能够清晰准确地传达其自身的交互特性,否则,人们将困惑于如何与之互动。他们很可能会以错误的方式进行操作,然后发现无果,进而将控件理解成不可交互的元素,app 的可用性也会因此而受损。

vue1.0和vue2.0的区别

seo达人

一、生命周期钩子的差别



    vue1.0的生命周期如下:



    



    



    vue2.0的生命周期如下:



    



    



    用一张表格来做对比:



    



二、代码片段



    在vue1.0中可以在template编写时出现:



<template>

   <div>第一行</div>

   <div>第二行</div>

</template>

    在vue2.0中在template编写时,必须只有一个根元素,否则会报错。



<template>

   <div id='root'>

      <div>这是第一行</div>

      <div>这是第二行</div>

   </div>

</template>

三、for循环遍历数组、对象时的参数顺序的变更,遍历数组之前是(index,value),现在是(value,index);对象的之前是(key,value),现在是(value,key).



    移除了$index和$key两个隐式声明变量,以便在v-for中显式声明。



    之前的track-by已经替换为key来代替



    v-for的循环范围也发生了改变,之前v-for='item in 10',范围为0-9,现在是:1-10。







四、Props 的参数



    1、如果需要检查 prop 的值,创建一个内部的 computed 值,而不再在 props 内部去定义coerce。



    之前是:



props: {

  username: {

    type: String,

    coerce: function (value) {

      return value

        .toLowerCase()

        .replace(/\s+/, '-')

    }

  }

}

    现在改成用computed来代替:

props: {

  username: String,

},

computed: {

  normalizedUsername: function () {

    return this.username

      .toLowerCase()

      .replace(/\s+/, '-')

  }

}

    这样有一些好处:



        可以对保持原始 prop 值的操作权限。



        通过给予验证后的值一个不同的命名,强制开发者使用显式申明。



    2、twoWay参数的移除,v-bind 的 .once和.sync 修饰符 移除



            Props 现在只能单向传递。为了对父组件产生反向影响,子组件需要显式地传递一个事件而不是依赖于隐式地双向绑定。



    3、



五、计算属性



cache: false 弃用,在 Vue 未来的大版本中,计算属性的缓存验证将会被移除。把不缓存的计算属性转换为方法可以得到和之前相同的结果。    

六、Built-In 指令



v-bind 真/假值 变更;在2.0中使用 v-bind 时,只有 null, undefined,和 false 被看作是假。这意味着,0 和空字符串将被作为真值渲染。比如 v-bind:draggable="''" 将被渲染为 draggable="true";

用 v-on 监听原生事件 变更,现在在组件上使用 v-on 只会监听自定义事件 (组件用 $emit 触发的事件)。如果要监听根元素的原生事件,可以使用 .native 修饰符;

带有 debounce 的 v-model移除;

使用 lazy 或者 number 参数的 v-model ,替换;

使用内联 value的v-model 移除;

v-model with v-for Iterated Primitive Values 移除;

带有 !important 的v-bind:style 移除;

v-el 和v-ref 替换,简单起见,v-el 和 v-ref 合并为一个 ref 属性了,可以在组件实例中通过 $refs 来调用;

v-show后面使用v-else 移除。    

七、自定义指令



自定义指令 简化;    

八、过渡



transition 参数 替换,Vue 的过渡系统有了彻底的改变,现在通过使用 <transition> 和 <transition-group> 来包裹元素实现过渡效果,而不再使用 transition 属性;

可复用的过渡 Vue.transition 替换,在新的过渡系统中,可以通过模板复用过渡效果;

过渡的 stagger 参数 移除。    

九、事件



events 选项 移除,事件处理器现在在created钩子中被注册;

events 选项 移除Vue.directive('on').keyCodes 替换,新的简明配置 keyCodes 的方式是通过 Vue.config.keyCodes;

$dispatch 和 $broadcast 替换,可使用Vuex。    

十、过滤器



插入文本之外的过滤器 移除;

过滤器参数符号 变更   现在过滤器参数形式可以更好地与 js 函数调用方式一致,因此不用再用空格分隔参数,现在用圆括号括起来并用逗号分隔。

内置文本过滤器 移除,替换 json 过滤器;替换 capitalize 过滤器;替换 uppercase 过滤器;替换 lowercase 过滤器;替换 pluralize 过滤器。

双向过滤器 替换。

十一、插槽



重名的插槽 移除;

通过具名 <slot> 插入的片段不再保持 slot 的参数。请用一个包裹元素来控制样式    

十二、特殊属性



keep-alive 属性替换,不再是一个特殊属性,而是一个包裹组件。    

十三、计算插值



 属性内部的计算插值 移除;

HTML计算插值 移除,取代的是v-html指令;

单次绑定替换成v-once。  

十四、响应



vm.$watch   换成    update生命周期钩子;

Array.prototype.$set弃用,用Vue.set代替

Array.prototype.$remove 移除  用 Array.prototype.splice 替代;

Vue.set 和 Vue.delete 移除;

替换vm.$data 移除;

vm.$get 移除,可以直接取回响应数据。

十五、围绕DOM的实例方法



vm.$appendTo 移除;

vm.$before 移除;

vm.$after 移除;

vm.$remove 移除。    

十六、底层实例方法



vm.$eval 移除;

vm.$interpolate 移除;

vm.$log 移除    

十七、实例DOM选项



replace: false 移除,现在组件总是会替换掉他们被绑定的元素。为了模仿,可以用一个将要替换元素类似的元素将根组件包裹起来。    

十八、全局配置



Vue.config.debug移除,因为警告信息将默认在堆栈信息里输出;

Vue.config.async移除,异步操作现在需要渲染性能的支持;

Vue.config.delimiters移除,可以在使用自定义分隔符时避免影响第三方模板;

Vue.config.unsafeDelimiters移除,HTML的插值替换为v-html。    

十九、全局API



带el的Vue.extend移除;

Vue.elementDirective移除;

Vue.partial移除。


日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档