首頁

后臺返回json數據給前臺和前臺解析json數據(總結)

seo達人

后臺返回json數據給前臺和前臺解析json數據(總結)

一般來說web開發(fā)中,前臺采用json數據提交給后臺,后臺處理數據以后返回json數據給前臺,前臺解析json,顯示數據。

總而言之,前后臺直接交換的數據格式最常用的非json數據無疑了。

這里就總結一些json數據的前后臺處理方式。



1.JSON數據

JSON(JavaScript Object Notation, JS 對象簡譜)



是一種輕量級的數據交換格式,比xml更輕巧(由于 JSON 所使用的字符要比 XML 少得多,可以大大得節(jié)約傳輸數據所占用的帶寬)。



json是javascript原生格式,就是說在javascript中處理json數據,需要引用其他API或工具包。



簡潔和清晰的層次結構使得 JSON 成為理想的數據交換語言。 易于人閱讀和編寫,同時也易于機器解析和生成,并有效地提升網絡傳輸效率。



只需要記?。?br />
Json是一種文本字符串!被存儲在responseText屬性中,而讀取json數據可以使用javascript的eval函數來解析json。



2.json規(guī)則:

在 JS 語言中,一切都是對象,對象是一個無序的 “鍵/值” 對集合。

因此,任何支持的類型都可以通過 JSON 來表示,例如字符串、數字、對象、數組等。但是對象和數組是比較特殊且常用的兩種類型:

? 對象表示為鍵值對.

? 數據由逗號分隔.

? 花括號{}保存對象.

? 方括號[]保存數組.



鍵/值對組合中的鍵名寫在前面并用雙引號 “” 包裹,使用冒號 : 分隔,然后緊接著值:



{"firstName": "Json"}

1

這很容易理解,等價于這條 JavaScript 語句:



{firstName : "Json"}

1

對象在 JS 中是使用花括號包裹 {} 起來的內容,數據結構為 {key1:value1, key2:value2, …} 的鍵值對結構。



在面向對象的語言中,key 為對象的屬性,value 為對應的值。



鍵名可以使用整數和字符串來表示,值的類型可以是任意類型。



數組在 JS 中是方括號 [] 包裹起來的內容,數據結構為 [“java”, “javascript”, “vb”, …] 的索引結構。



在 JS 中,數組是一種比較特殊的數據類型,它也可以像對象那樣使用鍵值對,但還是索引使用得多。同樣,鍵名可以使用整數和字符串來表示,值的類型可以是任意類型。



3.JSON 與 JS 對象的關系:

很多人搞不清楚 JSON 和 Js 對象的關系,甚至連誰是誰都不清楚。其實,可以這么理解:

JSON 是 JS 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質是一個字符串。

如:



var obj = {a: 'Hello', b: 'World'};    //這是一個對象,注意鍵名也是可以使用引號包裹的

var json = '{"a": "Hello", "b": "World"}';  //這是一個 JSON 字符串,本質是一個字符串

1

2

4.后臺返回json數據

一般來說,使用JsonObject來將Java類型數據轉換成Json類型,首先要下載該庫相關的jar包,下載地址如下:



json-jar包下載



JsonObject的使用:

后臺controller部分代碼:



JSONObject object = new JSONObject();  //創(chuàng)建Json對象

object.put("username", "張三");         //設置Json對象的屬性

object.put("password", "123456");

System.out.println(object.toString());  //調用toString方法將json對象轉換成json字符串



//把json數據返回給瀏覽器:

PrintWriter out = cu.getWriterOut(response);

out.print(object.toString());

//或者

response.getWriter().write(jsonObject.toString());



1

2

3

4

5

6

7

8

9

10

11

5.在JavaScript代碼中接收Json數據:

假設result為瀏覽器得到的json數據,可以使用以下js代碼可以將json對象轉換為字符串。



比如:



通過$.get從后臺獲取了一段json串{“id”:“1”,“name”:“ww”},然后要拿到這里面的id和name值:



注意!注意!注意!

如果你直接這么寫!



$.get(url,

     function(data) {

       alert("ID:" + data.id + "\nName:" + data.name);

     });

1

2

3

4

直接這樣寫的話,界面會alert提示undefined,因為沒能正確解析返回的字符串。



圖示:





解決方案:



1、 需要用eval()函數



將返回的串轉化成可用的strig串,eval(data),但是因為原串里面是以{}開始和結束的,會被認為是可執(zhí)行方法,因此需要加上()包圍起來,最終形成:



var jsonobj= eval('(' + data + ')');  // 把JSON字符串解析為javascript對象

1

然后再



alert("ID:" + jsonobj.id + "\nName:" + jsonobj.name);

1

各種正常的按key取值,就能正常顯示了。



2、獲取的時候就直接表示返回的是json格式,用.getJSON代替 .getJSON代替.getJSON代替.get,其他代碼不變,也能正常獲取。



也可以直接獲取json對象的屬性,如下:console.log(result.username);



前端js代碼:



$.ajax({

url: url,

type: "POST",

data: parameters,

dataType:"json",

async: false,

success: function(result){

var newData = JSON.stringify(result);    //將json對象轉換為字符串

newData = eval("("+newData+")");   /解析json



var annualDays = newData.annualDays;

var entryDate = newData.entryDate;



$("input[name='extendDataFormInfo.value(fd_shengyu_nianjia)']").val(annualDays);

$("input[name='extendDataFormInfo.value(fd_ruzhi_date)']").val(entryDate);



}});



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

ps: 注意注釋中的代碼,如果少了這一句,那么直接alert(result);得到的結果會是







所以在這里stringfy()的作用是用于從一個對象解析出字符串

加上了var newData = JSON.stringify(result);這句,然后你再alert(newData);

得到的就會是你想要的結果,如下:





另外:

如果返回的json數據格式不是很規(guī)范的解決辦法:



判斷后臺返回的數據格式是否字符串,是則轉,不是則不轉?



  var $obj = (typeof data.content == 'string') ? JSON.parse(data.content):data.content

1

總結:



前臺發(fā)送請求,并且設置數據為json格式‘

    $.ajax({

    url:"selectByid.",

    datatype:'json',

    data:{id:id}, // 發(fā)送數據 

1

2

3

4

數據回調函數

success:function(data){

alert(data);

var json = eval("("+data+")");//將json類型字符串轉換為json對象

alert("hjf"+json.name);

1

2

3

4

給對應的input賦值:

$("#id").val(json.id),

$("#name").val(json.name),

$("#age").val(json.age);

1

2

3

后臺代碼:返回json數據

response.getWriter().print(str);    //將數據返回前臺ajax

1

6.前端ajax接不到json解決?

在前臺:



async:false,                //加上這個屬性就好了

1

7.返回的json字符串中有轉義符解決?

比如:



"result":"{\"id\":\"60\",\"qid\":\"1\",\"bazi\":\"baiz\",\"shenxiao\":\"\",\"xingzuo\":\"\",\"wuge\":\"\",\"jianyi\":\"\",}"

1

這樣我們我們使用JSON.parse(result) ,直接轉化為json的話是會報錯的。



解決方法:

我們先把轉義符用正則表達式去掉,



   var string = result.replace("/\","");

   var getDataArray = JSON.parse(string)

1

2

這樣就OK了,不過要注意有時候也是需要指定返回數據類型的

dataType:“json”



8.使用其他的json依賴包方式:

引入阿里巴巴的json依賴包:



    <dependency>

     <groupId>com.alibaba</groupId>

     <artifactId>fastjson</artifactId>

     <version>1.2.9</version>

    </dependency>

1

2

3

4

5

模擬后臺:



    String params="{\"channelCode\":\"bbb\",\"accountNo\":\"121300000932\",\"message\":\"字符信息解密成功\",\"status\":\"1\"}";

    JSONObject pa=JSONObject.parseObject(params);

    System.out.println(pa.getString("message"));

1

2

3

結果:





或者:

引入net.sf.json-lib依賴包:



    <dependency>

      <groupId>net.sf.json-lib</groupId>

      <artifactId>json-lib</artifactId>

      <version>2.4</version>  

      <classifier>jdk15</classifier>

    </dependency>

1

2

3

4

5

6

后臺:



String params="{\"channelCode\":\"ccy\",\"accountNo\":\"121300000932\",\"message\":\"字符信息解密成功\",\"status\":\"1\"}";

JSONObject pa=JSONObject.fromObject(params);

String accountNo=pa.getString("accountNo");

System.out.println(accountNo);

1

2

3

4

結果:





9.后臺對象轉換json數據返回給前臺

List集合轉換成json代碼:



List list = new ArrayList();

list.add( "first" );

list.add( "second" );

JSONArray jsonArray2 = JSONArray.fromObject( list );

1

2

3

4

Map集合轉換成json代碼:



  Map map = new HashMap();

map.put("name", "json");

map.put("bool", Boolean.TRUE);

map.put("int", new Integer(1));

map.put("arr", new String[] { "a", "b" });

map.put("func", "function(i){ return this.arr[i]; }");

JSONObject json = JSONObject.fromObject(map);

1

2

3

4

5

6

7

或者在項目中加入引入JSON-lib包,JSON-lib包同時依賴于以下的JAR包:

下載地址。



  1.commons-lang.jar

  2.commons-beanutils.jar

  3.commons-collections.jar

  4.commons-logging.jar 

  5.ezmorph.jar

  6.json-lib-2.2.2-jdk15.jar

1

2

3

4

5

6

用法同上



JSONObject jsonObject = JSONObject.fromObject(message);

getResponse().getWriter().write(jsonObject.toString());

1

2

當把數據轉為json后,用如上的方法發(fā)送到客戶端。前端就可以取得json數據了。(可以參考最下面的實例)



10.后臺返回數據給前臺,json中文亂碼解決方法

在實際運用場景中,當前臺發(fā)起請求后,我們需要從后臺返回數據給前臺,這時,如果返回的數據中包含中文,則經常會出現在后臺查詢出來都是好好,但是傳輸回去就莫名的亂碼了,而且即使在 web.xml 中進行編碼過濾了,但還是亂碼。



解決辦法:

只需要在 spring-mvc.xml 配置文件中配置一次就好,省去了我們重復寫的麻煩,配置內容如下:



<!--自定義消息轉換器的編碼,解決后臺傳輸json回前臺時,中文亂碼問題-->

    <mvc:annotation-driven >

        <mvc:message-converters register-defaults="true">

            <bean class="org.springframework.http.converter.StringHttpMessageConverter" >

                <property name = "supportedMediaTypes">

                    <list>

                        <value>application/json;charset=utf-8</value>

                        <value>text/html;charset=utf-8</value>

                        <!-- application 可以在任意 form 表單里面 enctype 屬性默認找到 -->

                        <value>application/x-www-form-urlencoded</value>

                    </list>

                </property>

            </bean>

            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" ></bean>

        </mvc:message-converters>

    </mvc:annotation-driven>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

加上這段配置,保存重新運行,再次訪問,會發(fā)現,原先的中文亂碼都已經正常顯示了。



方法二:在后臺的方法映射添加:



@RequestMapping(value="/getphone",produces = “text/plain;charset=utf-8”)



11.Spring MVC返回json數據的方式

  1. 采用@ResponseBody注解

    @ResponseBody 注解的作用是:



    將controller的方法返回的對象通過適當的轉換器轉換為指定的格式之后,寫入到response對象的body區(qū),通常用來返回JSON數據或者是XML數據,需要注意的呢,在使用此注解之后不會再走試圖處理器,而是直接將數據寫入到輸入流中,他的效果等同于通過response對象輸出指定格式的數據。



    使用舉例:





    使用@ResponseBody 注解返回響應體 直接將返回值序列化json

    優(yōu)點:不需要自己再處理



    再舉例:



    RequestMapping("/login")

    @ResponseBody

    public User login(User user){

    return user;

    }

    1

    2

    3

    4

    5

    使用@ResponseBody 注解返回響應體 直接將返回值序列化json。



    User字段:userName pwd,那么在前臺接收到的數據為:’{“userName”:“xxx”,“pwd”:“xxx”}’,效果等同于如下代碼:



    @RequestMapping("/login")

    public void login(User user, HttpServletResponse response){

    response.getWriter.write(JSONObject.fromObject(user).toString());

    }



    1

    2

    3

    4

    5

    需要在springmvc的配置文件xml中添加:



    <mvc:annotation-driven/>  

    1
  2. 采用工具類,進行json格式轉換帶回

    JSON-lib包是一個beans,collections,maps,java arrays 和XML和JSON互相轉換的包。在本例中,我們將使用JSONObject類創(chuàng)建JSONObject對象,然后我們打印這些對象的值。為了使用JSONObject對象,我們要引入"net.sf.json"包。為了給對象添加元素,我們要使用put()方法。



    要使程序可以運行必須引入JSON-lib包,JSON-lib包同時依賴于以下的JAR包:



    commons-lang.jar

    commons-beanutils.jar

    commons-collections.jar

    commons-logging.jar 

    ezmorph.jar

    json-lib-2.2.2-jdk15.jar

    1

    2

    3

    4

    5

    6

    效果:



    工具類:

    ResponseUtil.java



    package com.zout.utils;

    import java.io.PrintWriter;

    import javax.servlet.http.HttpServletResponse;

    import net.sf.json.JSONArray;

    import net.sf.json.JSONObject;



    /*

     
    @class_name:ResponseUtil  

     @param: EasyUi-響應工具類

     
    @return: 返回字符串格式數據、result是JSONObject對象(json對象)

     @author:Zoutao

     
    @createtime:2018年3月8日

     /

    public class ResponseUtil {

    public static void write(HttpServletResponse response, Object result)

    throws Exception {

    response.setContentType("text/html;charset=utf-8");

    response.addHeader("Access-Control-Allow-Origin", "
    ");

    PrintWriter out = response.getWriter();

    out.println(result.toString());

    System.out.println("帶回的json字符串為:"+result.toString()+"類型為:"+result.getClass().getName());

    out.flush();

    out.close();

    }



    public static void main(String[] args) throws Exception {

    /在web運用控制層中調用如下:/

    JSONObject result = new JSONObject(); //創(chuàng)建json對象

    JSONArray jsonArray = JSONArray.fromObject("name:zhangsan"); //字符串轉為json數組

    result.put("rows", jsonArray);  //放入json數組中,并起個名字

    HttpServletResponse response = null; //jsp的response對象

    ResponseUtil.write(response, result); //result寫入response帶回前臺,jsp按名字拿取。

    }

    }



    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

    后臺具體調用:



    JSONObject result = new JSONObject();

    if (resultTotal > 0) { //處理結果

    System.out.println("操作成功。");

    result.put("success",true)

    result.put("message","操作成功"); //消息語句

    } else {

    System.out.println("操作失敗。");

    result.put("success", false);

    result.put("message","操作失敗");

    }

    ResponseUtil.write(response,result); //帶回字符串+狀態(tài)碼

    return null;

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    圖:





    后臺已經通過工具類封裝為json字符串了,使用response帶回需要的數據,使用result帶回狀態(tài)字符串或狀態(tài)碼。



    前臺:

    這是當成返回一個json字符串,然后直接采取字符串截取的方式,取出消息語句message等消息。





    這是另外一種寫法:就是解析傳回來的json字符串我js的對象,然后按照key/value的取值。



      function (data) {

              var data=eval("("+data+")");  //解析json

             //alert(data.message)

                $.messager.show({

                  title:'消息',

                  msg:data.message,  //按key取值

                  timeout:1000,

                  showType:'slide',

                  height:120,

                 width:200

         });

     });

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    推薦這種方式。

    效果圖:





    以上都是后臺返回json數據給前臺和前臺解析json數據的一些總結,還有json數據的封裝,工具類的使用等等,東西有點復雜有點多,挑選自己需要的地方即可。

    另外的一些常用的web開發(fā)json:



    Json–Java數據類型對照表(映射)表


javascript基礎———原型、原型對象和原型鏈

seo達人

原型:函數中的屬性prototype,她的名字就叫原型。可以通過也只能通過prototype添加可繼承的屬性和方法

原型對象:函數中prototype中的proto 和對象中的proto

先記住原型(prototype)和原型對象(proto)

下面用代碼解釋原型、原型對象、 原型鏈

<!DOCTYPE html>

<html>

   <head>

    <meta charset="utf-8">

    <title>對象</title>

   </head>

   <body>

    <script type="text/javascript">

       //創(chuàng)建一個對象和一個函數

       var obj = {}

       console.log(obj.proto)//obj有原型對象

       function objFun (){}

       console.log(objFun.prototype) //objFun 原型

       console.log(objFun.prototype.proto) //原型中有原型對象

       console.log('*華麗的分割線***')

       // 以objFun為構造函數 (為了把構造函數和普通函數做區(qū)分,通常把構造函數名首字母大寫)

       // 添加屬性和方法

       objFun.prototype.name='saozhu'

       objFun.prototype.say = function(){

        console.log(this.name+'-騷豬')

       }

       // 創(chuàng)建實例對象1

       var obj1=new objFun()

       console.log(obj1)//打印對象 空對象

       console.log(obj1.name) //騷豬 證明obj1繼承了objFun函數的屬性

       console.log('*華麗的分割線***')

       // 此時此刻 可以理解原型鏈了: 

       console.log(obj1.proto=== objFun.prototype)

       //true 

       // 原型鏈是有實例對象的proto(原型對象)指向構造函數函數的原型(prototype)

       console.log(objFun.prototype.proto==window.Object.prototype)

       // true

       // 然后構造函數的原型的原型對象(prototype.proto)指向window.Object.protype(對象的原型)

       console.log(window.Object.prototype.proto===null)

       // 這樣的指向關系形成的鏈式關系就是原型鏈

       //鏈式查詢,查詢對象中的屬性和方法,會根據這樣的原型鏈查找,直到找到響應的屬性和方法.找到window.Object.prototype.proto還沒有值,就返回undeifne

       

    </script>

   </body>

</html>


產品思維·用戶體驗中的五個層次(下)

ui設計分享達人

昨天我們講了用戶體驗分為五個層次,從內而外分別是:

①戰(zhàn)略存在層 > ②能力圈范圍層 > ③資源結構層 > ④角色框架層 > ⑤感知層


以下案例來自于 梁寧老師的《產品思維30講》

苦思冥想,還是只有梁寧老師這個案例最為合適;


說到“搜索”,你會想到哪些呢


如果我沒猜錯,你想到的第一個詞是:“百度”

研發(fā)行業(yè)的話,可能我們用的瀏覽器應該是:“google”居多

但你是否用過古老的“yahoo”呢?



今天,我們就來說說搜索業(yè)三大巨頭的戰(zhàn)爭,

他們之間的戰(zhàn)爭,有助于我們去理解用戶體驗的五個層次


首先


Google與百度


說到百度與谷歌的競爭前,梁寧老師說了下雅虎:


我們做設計的最知道,色彩是非常重要的元素,如果以科技為關鍵詞,

我們想到的第一個詞,一定是藍色,藍色一來不會太刺眼,

又相對普遍,所以不會出現審美疲勞,

而yahoo用的是什么為主色呢,是一個我們最不會用的顏色——紫色

 


那么,假如有個用戶指著那個“紫色”的“音噗忒(input)”說:“不好用”,

他指的是什么呢?


1.是感知層,不喜歡藍色?

2.按鈕的形狀太突兀?尺寸太大?位置不合適?

3.還是說是框架層,內容的排列方式沒有令他滿意呢?


說點令人興奮的,我們在百度搜索“大樂透”,

度娘顯示的結果第一條,就是本期開獎的結果,

然后是百度百科對“大樂透”這個詞條的解釋,

其次的就是關于大樂透的各類新聞和各種“行業(yè)大師”對下期開獎結果的分析;


百度的框架的意義就是,能一步走完,絕對不讓用戶走一步半,

為什么百度能給出這么符合用戶的搜索結果呢?


雖然這個結果離不開的肯定得是百度的爬蟲技術是數以毫秒為單位的,

但百度爬蟲技術肯Google當然還是沒法比的,

最重要的什么呢,是百度不單只是去爬數據,而且他還建立數據,


當整個互聯網的數據都不多的時候,

百度做了一件Google沒有做的事,

就是我們剛才說到的“建立數據”

百度做了兩個平臺:1.百度貼吧     2.百度知道


展示下各自的裝備


一個在升級技術去爬,一個在建立數據

你覺得,誰會贏到最后呢,


你說,Google為什么不跟著做呢,

Google 的性格是絕對不會的,用梁寧老師的話來說:

“以Google的清高和耿直,不會做這樣的事,甚至當用戶有需求時,Google還會為百度導流量,給對手送彈藥”


但至此,搜索業(yè)都還是處于資源層的比拼

這一仗,百度帶著它的百度貼吧和百度知道,拿到了勝利!


但三十年河東,三十年河西

百度在移動場景下輸給微信,也是因為微信以百度戰(zhàn)勝Google同樣的方式,以公眾號的形式建設資源;



Yahoo與Google


2004年,一批華爾街精英做了搜索引擎的比評,評測結果呢,Yahoo優(yōu)于Google,Yahoo勝利,

但奇怪的是評測完之后,大家打開了Google工作,


為什么會出現這個情況呢,


他們的評測方式非常的簡單,對,就是簡單,


第一步:選幾個關鍵詞

第二步:在各個搜索引擎中搜索

第三步:將結果打印

第四步:比對結果,認為哪個好,就投一枚硬幣


最后雅虎獲得的硬幣最多

簡單吧,你閑的蛋疼也可以去試試,


那為什么雅虎會勝出呢,因為雅虎用的后臺搜索引擎也是Google的,

雅虎只是對熱門的關鍵詞做了人工優(yōu)化,

所以結果不是跟Google一樣,就是比Google好,

。。扯吧,但就是這樣。


那為什么這批精英日常還是會用Google呢,

竟然是因為框架層,因為Yahoo的設計比較喜歡高大尚,所以界面相對寬松,易看,

但缺點就是一屏只能顯示一兩條,



而谷歌的搜索結果一屏展示好幾十條,

所以對于搜索引擎這個東西來說,

我們更在乎內容,

而形式恐怕稍微次要,


在感知層差別不大的情況下,Yahoo竟然在框架層就輸了一局,恐怕很難想到吧



設計師,要有產品思維!

但在互聯網設計的今天,可能這五個層級有了一些整合,

但是,在用戶抱怨體驗不好時,你能分辨,會去分辨用戶是說哪個層級嗎?

還是說你會跟用戶講道理,說服他們呢?


銷售天然的本領就是說服,掌握各種說服的技巧:

擺事實,講道理,打比方,舉例子,要同情,裝可憐,將心比心,軟磨硬泡;

如果是現實中,或許你能說服用戶,


但作為一個互聯網產品,別說說服,你連站在旁邊說句話的資格都沒有,

何況,比起用自己的道理說服用戶,我們更應該做的,不應該是挖掘用戶真正的需求嗎?


從今天起,

不再做銷售:按我的來

而要做產品:順你的意


用戶沒有我們這么專業(yè),他的表達方式就是:情緒;

如果我們不能接受這個表達方式,就不可能挖掘到用戶的真正需求,


總結一下:

  1. 接受用戶的表達方式,通過五個層面,挖掘到用戶真正的需求;

  2. 銷售是按我的來,而產品是順你的意

取消與關閉:請在設計上區(qū)分差異

ui設計分享達人

3個方法,區(qū)分取消與關閉,避免丟失用戶正在操作的內容。

概要:區(qū)分這兩種操作,可以很大程度上能避免丟失用戶已操作的內容。在關閉視圖之前保存用戶的更改,使用文本標簽而不是“X”圖標,并在破壞性操作之前提供確認對話框。



一、讓人迷惑的“X”圖標


很久以前,“X”這個符號是用在地圖上,標記“寶藏的藏身地”。但在今天的數字化界面中,“X”符號不再用來標記位置,而是被用來取消進程,或者關閉某個臨時頁面/彈框。但是如何確定“X”代表的是“取消” or “關閉”?有的時候可以確定,有時卻模糊不清難以界定。

  

其實,主要的問題在于“X”圖標缺少了文本標簽。當同一個圖標在不同的界面,卻代表不同的含義,該圖標的可用性就會受到影響,因為用戶判斷不了到底是什么含義。



二、為什么要區(qū)分“取消”與“關閉”


當用戶單擊/點擊“X”按鈕來關閉模態(tài)彈框或視圖時,系統會完全取消該過程并清空之前所有操作,這讓人沮喪,甚至抓狂。因為用戶通常認為“X”圖標表示取消或者關閉,所以區(qū)分這兩種可能性對于交互的成功至關重要。


在某些情況下,區(qū)分取消 or 關閉并不重要。當一個彈窗占據你的大部分屏幕時,點擊“X”按鈕(盡可能快地),既可以關閉該模態(tài),也可以取消它可能觸發(fā)的任何進程。


但是,如果頁面中包含正在運行的計時器,正在播放的音頻,正在選擇多個選項標簽,或其他類型未保存的內容,那就很有必要說明“X”圖標所代表的意義。因為用戶可能打算讓計時器或音頻繼續(xù)運行,或者希望立刻應用這些選好的選項標簽,或保存正在進行的工作,同時希望關閉該視圖繼續(xù)其他操作。

 

例如:絲芙蘭在結賬過程中,使用模態(tài)窗口來展示用戶可以添加到購物車的免費商品。在以下示例中,單擊“ ADD(添加)”按鈕選擇商品后, 該按鈕直接被變成了“ Remove(移除)”,看起來似乎商品已經被添加到購物車中了。但是,實際上當用戶單擊右上角的“X”圖標后,該商品并不在購物車中。他需要再重復這個步驟,最后點擊“Done(完成)”按鈕,商品才會被加入購物車。

Sephora:單擊右上角的"X"會取消選擇這些試用商品整個過程。用戶必須先單擊“ADD”,再單擊“Done”才能將商品添加到購物車。



三、如何避免丟失用戶正在操作的內容


要避免丟失用戶正在操作的內容,首先需要確定用戶的意圖 - 取消 or 關閉 - 并提供明確的選項。有以下幾種方法:


  · 主動要求用戶確認他們的意圖

  · 使用明確的文本標簽而不是模糊圖標

  · 顯示兩個不同的按鈕:“X”圖標表示關閉視圖(可以自動保存頁面內容/操作),而“取消”則代表放棄該過程


1、要求確認


如果用戶在已經執(zhí)行操作的模態(tài)彈框或頁面視圖中,點擊“X”圖標,UI則可以在關閉視圖之前,直接詢問用戶是否應用該操作,來確認其意圖。此解決方案非常適合會破壞用戶工作的破壞性取消操作。例如,過濾器視圖可能會被意外關閉,并且關閉會導致用戶丟失其選定的選項。


這個問題在移動端界面上很常見,因為過濾器視圖占用了很大的屏幕空間,這使用戶很難或不能判斷是否已經應用了那些選擇。為了防止這種潛在的錯誤,在關閉過濾器視圖之前,跟用戶確認是否要應用這些選擇并關閉視圖,抑或是清除這些選擇。例如:下圖中,當用戶選擇后,點擊“X”圖標時,Lowes 會出現如下確認彈框。

左 :點擊"X"圖標或返回箭頭,所有的選項都會被取消,并將用戶帶回上一個頁面。右:點擊“X”后,出現一個確認對話框,確認用戶是應用還是取消篩選,然后再返回結果列表頁。

 

同樣,當用戶關閉正在進行的課程時,語言學習應用- Duolingo 會顯示一個確認對話框-課程進行中不能中途離開,除非確認“退出”。至少,該APP向用戶傳達了這一限制,同時他們也可以選擇“取消”來繼續(xù)課程。點擊“X”按鈕將結束當前課程。為了防止出錯,結束前會出現一個確認對話框。

 

缺點:

a. 雖然確認對話框在避免“X”圖標有歧義方面很有效,但它卻添加了額外的步驟;

b 用戶在按下“X”圖標之前還是不知道它到底做了什么,代表什么意思,因此他們可能會對這個操作感到疑惑。



2、使用文本標簽


不要完全依賴對話框來讓用戶確認模糊的“X”圖標,而是使用明確的文本標簽。文本可以消除歧義,并清楚地傳達將發(fā)生的操作:取消與關閉。

 

Yelp的篩選頁面在屏幕頂部提供了標有”Cancel(取消)“和”Reset(重制)“的按鈕,在底部提供了一個大大的”Apply(應用)“按鈕。類似地,Etsy中的 Filters視圖提供了“Clear(清除)”和“Done(完成)”兩個按鈕。


注意:Etsy使用“Done”而不是“Apply”,因為過濾器一經選擇就可以被應用,而這里是關于開關切換與否的建議。

(左)Yelp:Cancel、Reset 和 Apply 這三個文本標簽既直接又清晰,這樣用戶就不太可能不小心關閉視圖而丟失他們過濾器中的選擇。(右)Etsy:Clear 為用戶取消提供了一種清晰的方式。而點擊 Done 則返回到“產品列表”頁,其中的選擇已經應用。




3、關閉并保存


果必須使用“X”圖標而不是文本標簽(比如為了以節(jié)省空間,或者因為正在遵循團隊的設計語言),請謹慎使用,并在用戶完成前保存操作/內容。另外,可以提供一個單獨的“取消”按鈕,讓用戶在進程之外有一個緊急出口,并消除“X”(關閉 or 取消)在兩種含義之間的歧義。

 

例如: Gmail會自動保存在非模態(tài)窗口中填寫的郵件信息到草稿(Drafts)。這樣的好處是,用戶在需要折疊或關閉該窗口時,仍然保存原來的內容以便于下次繼續(xù)編輯。將鼠標懸停在消息窗口右上角的“X”圖標上時,會顯示一段提示:Save & Close(保存到草稿并關閉)。此外,點擊窗口右下角的“垃圾桶”圖標可以刪除該郵件 - 這個圖標離頂部的“保存和關閉”選項很遠,可以防止用戶誤點。

Gmail:Hover 透露, “X”圖標是用于關閉窗口而不是刪除草稿,它允許用戶保存并關閉消息窗口而不會丟失剛剛正在編輯的郵件。

 

對于長進程或傾向于在后臺運行的進程(如計時器),默認自動保存也是一種很好的解決方案。

 

例如,Glow Baby中,后臺運行喂食或睡眠計時器時,用戶還可以瀏覽APP的其他區(qū)域。因為這些計時器一般會運行很長一段時間。此功能還能讓用戶在APP中做其他的任務操作,例如記錄之前換尿布的時間、瀏覽文章、逛論壇等。點擊計時器視圖中的“X”圖標也只是關閉窗口并不會取消正在運行的計時器。

Glow Baby:(左)點擊運行計時器視圖中的“X”圖標,在不停止計時器的情況下取消視圖,從而允許用戶繼續(xù)使用APP記錄其他類型的事件、參與社區(qū)討論、閱讀文章等。(中)運行計時器的狀態(tài)顯示在屏幕頂部的狀態(tài)欄中。(右)在計時器暫停時點擊“X”圖標,彈出“放棄”或“取消”按鈕以確認用戶的真正意圖。


 請注意:在關閉前保存中間工作或維護正在進行的過程是主動的,但有時可能會與用戶的意圖相反:如果用戶打算通過單擊“X”按鈕取消其選擇,那自動應用這些選擇可能會令人困惑和沮喪。


這就是為什么還必須有一個單獨的“取消”按鈕,給用戶一個出口,而不是強迫他們必須關閉時自動保存。



四、結論


雖然“X”圖標會造成模棱兩可,而且經常導致可用性問題,但它不太可能馬上從所有接口中消失。設計人員應該注意“X”圖標的多重含義,消除“關閉”和“取消”之間的歧義,并提供確認對話框或自動保存等保護性措施,避免丟失任何用戶正在操作的內容。


若存在疑問,請記住:先保存,再退出。



原文作者 | Aurora Harley

編輯作者 | WanSU

原文地址 | https://www.nngroup.com/articles/cancel-vs-close/

本文版權歸原作者所有;僅供學習使用,轉載請注明出處。



五、小思考


讀上面這篇文章的一個小啟發(fā):


為什么手機驗證碼登錄微信/淘寶時,驗證碼輸入錯誤,二者都是用的模態(tài)對話框提示用戶,而不是用Toast呢?

a. 微信和淘寶的用戶群體都很龐大,幾乎橫跨所有年齡層。Toast出現又自動消失的交互體驗,用戶會感到不可控,尤其是對大齡、老齡的用戶不夠友好。

b. 也有悖于iOS人機交互指南中提到的“用戶控制”這一原則,我想這也是iOS設計語言沒有Toast這種控件的原因之一吧。

c. 而模態(tài)對話框雖然干擾性較強,但用戶可以隨時控制,在使用過程中是用戶掌握主導權。


補充:Toast這一控件,原是Android系統的控件。但自Android 5.0 推出原質化設計后,Toast就被弱化,而是將 Snackbar 作為官方推薦的控件。如今在 Material Design中更是找不到 Toast的蹤影。主要原因還是 Snackbar 在交互友好性方面比 Toast 要好,例如:支持手勢交互、支持與CoordinatorLayout聯動等。所以說 Toast都過時了呢,應該講 Snackbar。

找到本質需求:聊聊內容分類

ui設計分享達人

資訊產品為例,一段尋找本質需求的旅程。


上篇文章,聊了信息架構。


信息架構有了,得往里面放內容。具體怎么放?特別是當內容非常海量的時候,比如資訊類、購物類產品。這個時候,就離不開內容的分類了。


我們平??次⑿殴娞枺ㄙY訊類),會發(fā)現,公眾號并沒有以“科技”、“影視”等維度進行分類,但感覺還好,也沒有太多不便。


這種做法,如果放到天貓(購物類)身上,會有點無法想象——碩大一個購物商城,如果不能按照商品的性質進行分類查找,逛起來必然非常不便。


由此可見,關于內容的分類,也是不能一概而論。


那么,內容分類,到底該咋分?個人覺得,籠統的講,內容分類就是化繁為簡,從而更好的滿足用戶需求。



本文將以綜合性資訊產品(手機端、文章類)為例,探討一下如何給海量的內容進行分類。



01 尋找本質需求


內容分類,既然是為了更好的滿足用戶需求,那么,我們就從需求出發(fā),從最本質的需求出發(fā)。


所謂大道至簡,本質的需求一般都不復雜。資訊產品,解決的本質需求是什么?以下是我個人用到的方法,僅供參考。


1 厘清來龍去脈,并注意前后區(qū)別


太陽底下無新事。某種程度上,資訊類和購物類產品用到的內容分類,都有借鑒歷史。


前面提到,微信公眾號沒有科技、影視等內容頻道。不過網易新聞客戶端是有的,類似的內容頻道有幾十個。


21 世紀最初的十年,逐漸崛起的四大門戶(新浪、網易、搜狐、騰訊),也存在幾十個這樣的內容頻道,并沿用至今。


90 年代和 21 世紀初盛行的報紙,比如《參考消息》,也存在類似的內容頻道(版面),通常有 10 個左右,同樣也是沿用至今。



內容頻道這種分類方式,看起來是一脈相承了。但其實這里面有三個很大的變化。


第一,載體由報紙變成電腦、手機(手機還很特殊、被稱之為人體的器官)。


第二,報紙代表的是一個信息稀缺的時代,如今是一個信息爆炸、甚至信息泛濫的時代。


第三,報紙和四大門戶,基本上都是由專業(yè)的記者、編輯來生產內容,質量有一定保障;如今是全民創(chuàng)作時代,各種質量都有。


那么,內容頻道這種形式,如今還是最好的內容分類方式嗎?


這個問題,是要存疑的。


2 為用戶的考慮,盡量周全


由于文章太多,所以有必要按性質對文章進行分類,前臺方便展示,后臺方便管理,用戶查找起來也比較方便。站在企業(yè)的角度,這樣想,除了可能不夠深入,其他也沒啥問題。


站在用戶的角度,假設有一個從來不買彩票、也沒動過相關念頭的用戶,通常是不會去看彩票相關的內容。對用戶而言,一款資訊產品,幾十個頻道,無數篇文章,往往充斥著大量“彩票內容”。


用戶關心什么呢?個人覺得,通常而言,用戶只關心“彩票內容”以外、自己興趣以內的內容,同時還關心怎樣快速看到這些內容。


至此,我們可以嘗試總結出內容分類需要解決的本質需求了,那就是:興趣和效率。



3 把簡單牢記在心


通過前兩步,我們已經把本質需求捋出來了。這時候,保險起見,拿本質需求和本條核對一下,看看是否簡單。如果本質需求有 10 來條、甚至幾十條,通常就是不夠簡單。


為什么要強調簡單,因為誠如張小龍在《微信背后的產品觀》中所言,“越簡單的分類越易于被接受”。




02 分析本質需求


接下來,我們先剖析一下這倆本質需求,加深一下對它們的理解。


1 本質需求之一:興趣


相信大部分用戶都有這樣的感覺:感覺 A 產品的文章,比 B 產品的質量要高;同一類型的公眾號,感覺 C 號比 D 號的質量高。


關于文章的質量,個人是這么理解的:

第一,主觀上,千人千面,對于質量,每個人都有自己的標準;

第二,客觀上,也存在一些比較權威的標準來評價質量,比如豆瓣的影評書評。


不過,常常發(fā)生的情況是,即便一部電影的豆瓣評分只有 5、6 分,還是會有很多人去電影院看。


再換一個角度來看:

如果是內容自營,比如心理學科普領域的 KnowYourself(以下簡稱 KY),就能持續(xù)產出較高品質的文章;

如果是平臺型產品,像微信公眾號,準入門檻又比較低,必然是各種質量的內容都有。


而綜合性的資訊產品,普遍都是平臺型。


所以,我更愿意這樣來理解資訊文章的質量:有些用戶是“北方人”,喜歡“面食”;有些用戶是“南方人”,喜歡“米飯”。


現在回到“興趣”這個本質需求上來。


這里的興趣,是一個廣義的概念,既包含了大的方向(比如你是喜歡股票還是彩票),也包含了口味偏好(“面食”還是“米飯”)。


2 本質需求之二:效率


借效率這個話題,簡單聊一下手機的特殊性。因為,現在絕大部分用戶是通過手機來看綜合性資訊的。


情侶之間、夫妻之間、兩代人之間,有時候會聽到一個詞兒,叫“玩手機”。連幼兒園的小朋友都會對自己的父母這樣說:爸/媽,你又在玩手機了,到底誰是你的孩子?


不像電腦,手機的辦公學習屬性很弱,休閑娛樂功能又很強。所以,捧著手機,尤其是在家里,就給人留下了不干正事的刻板印象。


所以,個人猜測,大家在用手機看資訊的時候,潛意識里也會有一點休閑娛樂的感覺,即便是通過公眾號在看一些干貨文章。


所以實際上,大家也基本上是在用碎片化時間來看資訊:通勤路上;在單位、學校和家里放空的間隙;以及一些無聊的時刻。


在大家的觀念里,手機上刷朋友圈和刷資訊一樣,都不太屬于干正事。


2019 年的微信公開課,張小龍分享的一個數據很有意思。


大概是說,這么多年下來,大家微信好友的數量在增加,朋友圈的內容數量也在增加,但是大家每天花在朋友圈的時間基本是固定的,就是 30 分鐘左右。


這說明我們人類是有自我調節(jié)機制的。人類的這種自我調節(jié)機制,決定了大家每天只會花碎片時間的其中一部分,用來在手機上看資訊。


這一特性,無疑也會對“效率”提出更高的要求



03 從本質需求出發(fā),先談功能特性,再談內容分類


那就需要聚焦在興趣和效率上。以下是經過實踐檢驗,比較有效的幾點。


1 關注機制


90 年代和 21 世紀初,如果家里訂了全年的參考消息,郵遞員每天都會把這份報紙投遞到你家門口。


2010 年及以后,如果在微博上關注了參考消息。那么,參考消息的每條更新,都會出現在你的信息流里。



關注機制,是一種創(chuàng)新,也是一種“昨日重現”。


用戶所關注的賬號,通常都是自己感興趣的;在一個單一維度的關注列表里瀏覽資訊,效率也得到了很大提升


2 品牌機制


有時候在家看電視,如果沒有特別想看的節(jié)目,很多人可能就會看湖南衛(wèi)視。這就是品牌的力量了。


當然,電視臺的品牌不止湖南衛(wèi)視一家。央視和很多地方衛(wèi)視都是很不錯的品牌。


報紙盛行的 90 年代和 21 世紀初,《參考消息》、《大河報》等國家和地方的報紙,都是品牌。百花齊放,百家爭鳴。


四大門戶盛行的時代,新浪、網易、搜狐、騰訊分別都是品牌,但同時也是一個寡頭壟斷的時代。


直到博客盛行,品牌的百花齊放才開始復蘇,很多人記住了韓寒、徐靜蕾、李銀河、鄭淵潔、王石、潘石屹等各界名人。


微博的問世,品牌再次開始全面開花。


現如今,把綜合性品牌經營的最好的,當屬微信公眾號了。《人民日報》、《三聯生活周刊》等老品牌紛紛扎根公眾號,公眾號也培育了一大批諸如 KY、烏鴉電影的新品牌。這是一個千花齊放、千家爭鳴的時代。


通過品牌,用戶可以省心而的看到自己感興趣的資訊內容。


3 品牌和頻道合二為一


在家里,我外甥喜歡看金鷹卡通頻道和卡酷少兒頻道。這倆電視臺,既是品牌,也代表了“少兒、卡通”這一類頻道。


我對心理學比較感興趣,所以我看 KY 這個公眾號比較多。KY 既是一個品牌,也代表了心理學科普領域。


金鷹卡通頻道、卡酷少兒頻道、KY,他們有個共同點:既是品牌,也是頻道。即所謂的品牌即頻道、頻道即品牌。


有了品牌和頻道的合二為一,我就不需要再去幾十個頻道里點“心理學”這個頻道、然后再去找文章看。我可以直接找 KY 的文章來看,既符合我的興趣,又很。


4 推薦機制


人是社會性動物,社交推薦,一直存在?;ヂ摼W的蓬勃發(fā)展,也帶來了機器推薦。


前文提到到《參考消息》,中學時代,我買的也不多,很多時候是從同學那兒看到的。


微博鼎盛的時代,大家開始學會一鍵轉發(fā)。


如今微信流行,大家開始在微信里分享和推薦文章。


社交推薦的,有時候你未必感興趣。這里面還有很多其他因素,不在本文論述范圍,就不贅述了。


不過,大家是可以在朋友圈、看一看里挑選感興趣的文章來看,有時候也會從好友的推薦里發(fā)現自己感興趣的內容。


然后再看機器推薦。就在前幾年,今日頭條憑借比較精準且快速的算法推薦,向用戶輸送熱點和他們感興趣的新聞,從而在資訊產品里占據一席之地。


總結一下,整體而言,關注機制、品牌機制、品牌和頻道合二為一、推薦機制,這四個功能特性,可以更好的滿足“興趣和效率”這個本質需求。



同時做到這四個方面、并且都做的不錯的綜合性資訊產品,可能就只有微信公眾號了。實際上,這篇文章,很大程度上也是以公眾號為藍本進行分析的。


這四個是功能特性。先有功能特性,再做內容分類。


微信公眾號是怎么對內容進行分類的呢?拋開推薦機制,只有一個維度,那就是訂閱號消息列表。從幾十個列表到只有一個列表,更簡單,更。


如果跳出來看,也可以理解成有 3 個維度:訂閱、朋友在看、精選。這樣就把推薦機制也包含在內了。從幾十個到 3 個,依然簡單,依然。



結語


內容頻道/版面,這一特性,被資訊產品一直保留了下來。從這一點也能看出,我們在做內容分類的時候,很多時候都會借鑒生活、借鑒歷史。


這其實是非常好的習慣,因為“藝術”來自生活。生活里流傳下來的事物,很多都經歷了歲月的洗禮。洗禮過后,大浪淘沙始見金。


然而世事紛擾,一不小心,我們可能只是借鑒了形式,而沒有借鑒到精髓。


找到那些簡單的本質需求,我們就有可能在紛紛擾擾的生活中,借鑒到最精髓的部分。然后相應的設計出比較簡單的功能特性和內容分類。


有了能更好滿足本質需求的內容分類,這款產品的發(fā)展也會更加持久。


行文至此,又到了要說再見的時候。就讓我們用下面這句話來結束本文。


太陽底下無新事,惟有經典永流傳。

別讓我思考

ui設計分享達人

《點石成金:訪客至上的網頁設計秘笈》在用戶體驗領域,可以說是一部很經典的書籍,該書于2000年出版第一版,現在已經更新到第三版,自從問世以來可以說已經將近20年了,但一直是備受推崇。這本書主要為我們介紹了產品可用性原則,并用大量的案例來闡述及運用。幾年前我讀過一次,最近再次重溫,準備做一個整理,當做自己的學習記錄。


作者史蒂夫·克魯克(簡稱Krug先生)是一名備受尊敬的可用性咨詢師,他把多年的從業(yè)經驗,以通俗易懂的方式凝結成此書,并且篇幅簡短,雖然作者說兩個小時就可以讀完,但如果邊讀邊思考的話,兩個小時還是不夠的,畢竟這是一本工具類書籍,不是小說。本篇文章只是我的一個學習記錄,還是非常希望大家能夠讀一讀原著的。



別讓我思考,作為Krug可用性第一定律,意味著,設計者應該盡量做到,當看到一個頁面時,應該是不言而喻,一目了然。我能明白它是什么,怎樣使用它,而不需要花費很多精力進行思考。


舉個例子,假如一個你不認識的人,就比如是你隔壁的鄰居,對你的網站毫無興趣,也幾乎不知道如何使用,但是他仍然看一眼你的主頁,就知道這是干什么的,該怎么用。


比如以下這個網站,這是我從網上隨便找的一個網站,之前從來沒有聽說過,點擊鏈接進入后的第一眼,就是很多關于車的元素,猜測一定是關于車的網站;右下角兩個大大的按鈕“找新車”“品牌找車”,那這個應該是賣車網站,八九不離十了。先不說下面是多么雜亂不堪,起碼第一眼我就可以看出,這個網站是干什么的,該怎么用,這是最基本的。



有可能我們之前訪問過一些網站,打開后茫然不知所措,幾乎把首頁的每個地方都瀏覽過了,才知道是該怎么操作,或者某些元素看起來像按鈕,但是卻不能點擊,也沒有點擊失敗的提示...總之體驗很差。所以當我們創(chuàng)建網站時,就需要去掉這些問號。作為一個用戶,永遠不能讓我花幾秒思考,能不能點擊的問題。


當我們訪問WEB的時候,每個問號都會加重我們的認知負擔,把我們的注意力從要完成的任務上拉開。這種干擾也許很輕微,但他們會累積起來,有時候這樣的干擾不用太多,就足以讓我們抓狂。這樣會讓我們對網站失去信心。


那么哪些事情是訪問者在訪問網站時不應該花時間思考的事呢?


例如:

1、我在什么位置?

2、我該從哪里開始?

3、他們把某某放在什么地方了?

4、這個頁面上最重要的是什么?

5、為什么他們給他取這個名字?

...

我們在設計網站的前和后,可以把這些作為走查對象審視一下,慢慢的這些習慣就會變成你的潛意識,再次設計網站的時候就會自然而然的把這些因素考慮在內。


不過,有時候,特別是在進行一項嶄新的,開拓性的或者非常復雜的頁面設計時,也許只能做到自我解釋。在一個自我解釋的頁面中,用戶只需要花一點點時間去理解頁面的外觀,精心選擇的名稱,頁面布局以及少量仔細斟酌過的文字。所以,如果不能做到讓一個頁面不言而喻,那么至少應該讓它自我解釋,這個非常重要。



我們常常認為用戶會盯著每個網頁,仔細閱讀我們精心制作的文字,領會我們組織頁面的方式,然后,在點擊某個鏈接之前權衡他們的可選目標。


但是大部分情況卻是,用戶只會在每個頁面上瞥一眼,掃過一些文字,點擊第一個令他們感興趣或者大概符合他們目標的鏈接。通常,頁面上的很多部分他們都不看(想一想,你是不是這樣瀏覽網頁的呢)。


本想舉快手WEB端的例子,沒想到再次打開后發(fā)現已經改版了,而且應該是近兩個月左右的事情,可惜已經不能截圖,不過這次的改版比之前好多了。

上一版本中,幾乎有幾段整段整段的文字,雖然文采不錯,比較優(yōu)美吧,但誰有耐心看呢,總之我打開幾次,一次也沒一字一字的閱讀過。這個直接增加了用戶的負擔,降低了主要元素的層級,畫蛇添足。


所以,如果我們想設計有效的網頁,必須開始接受關于網絡使用的三個事實:


一、我們不是閱讀,而是掃描


原因有3:

1、我們總是處于忙碌之中;

2、我們知道自己不必閱讀所有內容,只對網頁中的一小部分內容感興趣,剩下的內容我們并不關心,掃描就是我們找到相關內容的方式。

3、我們善于掃描,在日常生活中,我們不管是看報紙,還是雜志,書籍,基本都是用掃描的方式,找到我們感興趣的部分。


大家想一想,我們在看報紙的時候,是不是先瀏覽一遍,然后看到哪個標題比較吸引才專心去看那篇文章,而且也不會是一字一句的去讀,而是知曉大概內容即可。


再舉個貼近的例子,打開站酷的首頁,你們會從左到右,從上到右的一字不漏的去看嗎,我們是不是用眼睛掃一遍,看到吸引你的內容,然后再點進去看詳情,對的,這就是互聯網用戶的掃描閱讀。



二、我們不做最佳選擇,而是滿意即可


在設計頁面時,我們通常假設用戶只是掃過整個頁面,考慮所有可能的選項,然后選擇一個最好的。


事實上,大多數時間里,用戶不會選擇最佳選項,而是選擇一個合理的選項,一旦發(fā)現一個鏈接,看起來似乎能跳轉到我們想去的地方,那很大的機會就會去點擊它。


原因有以下幾個:

1、我們總是處于忙碌之中,尋找最佳策略需要的時間很長。

2、如果猜錯了,也不會產生什么嚴重的后果。就算做了錯誤選擇,我們只要點擊幾次返回按鈕就好,所以,返回按鈕,是WEB端用的最多的地方。

3、對選擇進行仔細思考還不如很快多嘗試幾次。

4、猜測更有意思,猜測不會像仔細權衡那么累,而且如果猜對了,速度會更快。


當然,這并不是說用戶在點擊之前從不進行權衡,這要取決于時間上的緊迫以及其他因素。


大家想一想,現實中是不是這樣的呢。也許通往一個入口有好幾條路徑,但是第一次進入該網站的時候,不會尋找最佳路徑,而是試探的摸索,只要找到就可以了,不會刻意的找那條最捷徑的。

 

三、我們不是追根究底,而是勉強應付。


生活中,人們在使用任何東西,往往不理解它們的運作原理,甚至對它們的工作原理有完全錯誤的理解。


無論面對哪種產品,除了刻意鉆研的,很少有人會花時間閱讀說明書。相反,我們往往是貿然前進,勉強應付。


比如我們買了一臺新款電視機,幾乎從來不會把電視機的零件一個個都拆下來,完全理解了它們的工作原理后才使用,我們甚至連說明書都不看,而是拿著遙控器自己琢磨,完全沒有必要去深究。



為什么會這樣?

1、這對我們來說并不重要。對于大多數人來說,是否明白背后的工作機制并不重要,只要正常使用即可,這并不是智力低下的表現,而是我們并不關心。

2、如果發(fā)現某個事物能用,我們會一直使用它。我們一旦發(fā)現某個事物能用,很少去找更好的替代品。如果偶然發(fā)現一種更好的方法,我們會換用這種更好的方法,但很少去主動尋找更好的。


舉個我小時候的例子,上學時我用的第一只中性筆是同學給我的,雖然可以用,但我發(fā)現比較粗,不太喜歡,但是認為可以用,從來沒想過是否有稍微細一點的。當第一只筆芯用完,去文具店購買時,發(fā)現竟然還有0.35的筆芯,很意外,當然我就放棄了之前的筆芯,換作成0.35的,這樣的例子應該都會發(fā)生在每個人的生活中。


那如果人們勉強應付的時候這么多,有沒有弄明白真的那么重要嗎?答案是很重要,因為有時候可以勉強應付,但通常效率不高,而且容易出錯。


如果用戶很清楚,不是勉強應付呢?

1、他們會更容易找到自己需要的東西。

2、會更容易理解你的網站提供哪些服務。

3、你更可能引導他們到你的網站上希望他們看到的地方。

4、在你的網站上,會覺得自己更聰明,感覺更好,這樣他們就會離開讓人勉強應付的網站了。


這也是現在競品之間搶奪用戶的一個重要因素,兩個服務內容一樣的產品,一個直觀明了,一個結構比較混亂,不能很快找到目標,對于這兩個產品,那用戶該選擇哪一個呢,可想而知。



前面已經說到,現在互聯網的用戶閱讀都是掃描式閱讀,那么在這種情況下,怎樣才能讓用戶清晰理解你的網站,提高體驗。


需要注意5個方面,保證他們會很容易理解你的網站:

1、在每個頁面上建立清晰的視覺層次;

2、盡量利用習慣用法;

3、把頁面劃分成明確定義的區(qū)域;

4、明顯標識可以點擊的地方;

5、最大限度降低干擾;


前面已經說到,現在互聯網的用戶閱讀都是掃描式閱讀,那么在這種情況下,怎樣才能讓用戶清晰理解你的網站,提高體驗。


一個視覺層次清晰的頁面有3個特點:

1、越重要的部分越突出;

2、邏輯上相關的部分,視覺上也相關;

3、邏輯上包含的部分在視覺上游嵌套;

 

也可以這么說,要把版式設計的四個原則,親密,重復,對齊,對比,把這幾點做好。

 

對于習慣用法可以說是人的一種本性習慣了,這也是為什么很多競品都很相似的原因了。


舉個常見的例子,比如聊天的icon,都是一種對話框的設計,因為人們已經習慣了這種圖標設計,如果換成其他,用戶看到后會不理解這到底是什么東西。



對于設計師,很多人一直想創(chuàng)新,但是一定要秉持兩個原則:

1、創(chuàng)新的方法同樣也要不言而喻;

2、能夠為用戶帶來很大價值,值得用戶付出一點努力來學習新的方法。



Krug可用性第二定律——點擊多少次都沒關系,只要每次點擊都是無須思考的選擇。

 

文中說:WEB設計師和可用性專家一直有一個爭論,用戶在到達目標之前點擊多少次不會覺得有挫敗感,作者認為,真正的問題不是到達目標之前要點擊的次數,而是每次點擊有多艱難,需要多少思考,有多大的不確定性來判斷自己是否在進行正確的選擇。

 

所以當我們在使用目前一些成功的產品時,會感到自然而然的流暢體驗,雖然有時候因為產品體量大,沒有很快找到目標,但我們也沒有過多挫敗和煩躁。


Krug可用性第三定律——去掉每個頁面上一半的文字,然后把剩下的文字再去掉一半。


好處:

1、可以降低頁面的噪聲。

2、讓有用的內容更加突出。

3、讓頁面更簡短,讓用戶在每個頁面上一眼就能看見更多的內容,而不必滾動屏幕。

 

如果有歡迎詞,盡量減少,能不用就不用。

指示性說明盡量不用。

如果指示性說明非常冗長,用戶發(fā)現所需信息的機會很小。

我們應該通過讓每項內容不言而喻來完全消除指示性說明,當指示文字變得完全沒有必要,就應把他們全部去掉。


現在比較成功的App的引導頁都非常簡潔,因為沒有人會在進入的時候看你寫的一長段文字,等待很長時間,除非視覺性很強,比如今年美團變黃的那段視頻,視覺沖擊力很強,我看完一次后,在網上又自己找,看了幾次。所以要做到盡量減少指示性說明。



作者認為,很多網站,一旦到了第二個層次,導航會變得支離破碎,隨意發(fā)揮,以至于很難找到良好的三級導航的例子。


原因有3:

1、好的多級導航本來就很難設計,同時有很多元素需要安排到頁面中。

2、設計師即使在設計前兩個層次也常感到時間不夠。

3、第三個原因是它看起來并不重要,不是主導航,也不是二級導航,而且有一種傾向認為,當人們深入到網站的這一個層次后,會自然明白如何進行操作。

 

而且就算設計師提出需求,他們也可能拿不到,因為負責內容的通常不會想的那么深遠。


事實上,用戶在底層頁面上花的時間通常和花在頂層頁面的時間相同,除非從一開始就自頂往下進行導航設計,否則以后很難再進行添加,也很難保持一致性。


網站主頁是我們打開后第一眼看到的,也是最容易向用戶突出網站的價值等內容的,那在主頁該放什么哪些內容比較合適呢:

1、站點的標識和使命:告訴我們這是什么網站,做什么的;

2、站點層次:提供服務概貌,包括內容,功能,組織形式;

3、搜索;

4、導讀:主頁最好有“里面有精彩內容”的暗示提醒;

5、內容經常更新;

6、友情鏈接;

7、快捷方式:最常訪問的內容片斷;

8、登錄、注冊;

...


除了這些主要的,最好還要滿足這些:

1、讓我看到自己正在尋找的東西;

2、我也許感興趣的精彩內容;

3、告訴我從哪里開始;

4、建立可信度和信任感。

 

比如打開淘寶首頁,你不僅可以看到以上羅列的內容,淘寶通過算法,會自動推薦你曾經搜索過得商品,最上角的非常醒目的位置,logo動效還會告訴你最近的活動。



對于一個控件的選擇或者其他設計,很多團隊經常在無休止的討論,始終沒有決定,這樣的討論除了浪費時間,也很容易造成緊張氣氛,破壞團隊成員之間的關系,常常讓團隊無法做出關鍵的決定.


我們每個人都是用戶,和所有的用戶一樣,對網站上喜歡什么,不喜歡什么有著強烈的感覺。

 

我們往往認為我們自己喜歡的,絕大多數用戶也都喜歡。這應該是人的一種天性。

 

同時,在團隊中,由于職位不同,不同崗位的人對網站設計也有不同的看法。


比如設計師喜歡視覺上比較好看的網站,而開發(fā)卻喜歡構建新穎,有趣,功能出色的網站。所以不同的角色,不同的視角,常常造成不同的看法,繼而不停的討論,讓會議陷入僵局,當然每個人的想法并不是一層不變的,只要有足夠的證據能打動他,他的想法完全可以反過來。


一旦因個人和職位不同而造成的沖突不分勝負時,討論常常會轉化為尋找某種方式(專家的意見、焦點小組或者用戶測試)來決定絕大部分用戶喜歡或不喜歡什么,但是,找出所謂的普通用戶,就是錯誤的想法,因為,本來就沒有什么普通用戶,所有的web用戶都是的。

 

越是仔細觀察用戶,認真傾聽他們表達自己的想法,越能意識到他們對網頁的個人反應和很多不同的變量有關系。所以,試圖用一些簡單的喜好來形容用戶,既瑣碎又沒有什么作用,另一方面,好的設計會把這種復雜性考慮進去。


關于普通用戶的這個說法,最糟糕的是加強了這種看法,認為好的web設計主要是找出人們的喜好,這種想法看上去不錯。比如面包屑導航好,要么不好,彈出框好,要么不好,非黑即白。


問題是,對于大部分web設計問題來說,沒有簡單的“正確”答案,好的設計能滿足需要,也就是說,經過仔細考慮,實現和測試的設計就是好的。


例如,對于Flash的使用,如果詢問用戶,有些用戶會說他們很喜歡Flash,而另外差不多同樣數量的用戶會說他們討厭Flash。實際上,他們不喜歡的是使用不當的Flash,大而復雜的動畫,需要很長時間下載,沒有帶來任何價值。如果仔細觀察他們,很可能發(fā)現同樣是這些人,喜歡那些使用精心設計,適當并小規(guī)模使用Flash的網站,增加一些簡約的修飾,或者有用的功能,同時又不帶來麻煩。


并不是說不存在完全錯誤的方法,有些設計網頁的方法確實是完全錯誤的,只是他們往往并不是設計團隊通常爭論的那些方法。


解決這種問題的關鍵方法就是,不要再問這樣的問題“大部分人喜歡這樣的導航嗎”,正確的問題應該是“在這個頁面,這種導航會讓可能使用這個網站的大部分人產生一種良好的體驗嗎?”,然后觀察人們對它的看法和使用的方法,再不斷調整。


爭辯人們喜歡什么既浪費時間又消耗團隊的經歷,而通過測試將討論對錯轉移到什么有效,什么無效上,更容易緩和爭論,打破僵局,而且測試會讓我們看到用戶的動機,理解,反應的不同,從而讓我們不再堅持認為用戶的想法和我們的想法一樣。



在做測試時,往往很多人不清楚什么是焦點小組訪談和可用性測試的的區(qū)別,那就先科普一下。


焦點小組訪談,百度百科的解釋是這樣的:就是采用小型座談會的形式,由一個經過訓練的主持人以一種無結構、自然的形式與一個小組的具有代表性的消費者或客戶交談。從而獲得對有關問題的深入了解。


簡單來說就是一個小組圍坐在桌子周圍,主持人拋出問題,針對這一問題,被訪談人說出自己的想法,從而快速得到用戶的意見和反應。


焦點小組可以抽象的確定你的目標用戶想要什么,需要什么,喜歡什么。也可以測試出網站的理念是否有意義,價值主張是否吸引人等等。


但焦點小組只是適合用于網站設計前就應該進行的,是一個早期階段方法。


比如電視劇《我的前半生》中,段曉天因得不到主角羅子君而為難她的那個片段,就是一次焦點小組訪談。



可用性測試的百度百科解釋是這樣的:讓一群具有代表性的用戶對產品進行典型操作,同時觀察員和開發(fā)人員在一旁觀察,聆聽,做記錄。


該產品可能是一個網站,軟件,或者其他任何產品,它可能尚未成型。測試可以是早期的紙上原型測試,也可以是后期成品的測試。


簡單說就是向用戶展示一些內容,不管是網站還是原型,或是草圖,并且要求用戶說出這是什么,并用他們來完成一項特定的任務。


如果想建立一個優(yōu)秀的網站,一定要測試。為一個網站工作幾個星期會讓你失去新鮮感,因為你對網站了解的太多,很多細節(jié)都知道,所以清楚網站是否正常運作的唯一方法就是測試。


測試會提醒你,不是每個人的想法都和你一樣,會和你用同樣的方法使用網站。


要記住,測試一個用戶比不做測試好一百倍。測試總是會有效果,哪怕對錯誤的用戶做一次糟糕的測試,也會讓你看到改善網站的一些方面。


在項目中,早做測試,哪怕一位用戶也好過最后測試50位用戶。


一旦一個網站投入使用,要改變就不是很容易了,有些用戶拒絕做出任何變化,所以在開始的時候,有助于防止你犯錯誤的方法都很劃算。


測試的關鍵不是證明什么或者反駁什么,而是了解你的判斷力。對于用戶的招募也不要太嚴格,如果能夠讓用戶是更接近使用網站的用戶就更好了,但更重要的是,要盡早和經常進行測試,這是一個開發(fā),測試,修復,再度測試的過程,沒有什么比現場用戶的反應更重要了。

 

其實做可用性測試沒有想象的那么復雜,一個簡單的可用性測試完全可以把問題解決。

 

那么應該測試多少用戶呢:

很多情況下,每輪測試用戶數量應該是三個,最多四個。前三個用戶很可能會遇到幾乎所有最明顯的問題,更重要的是多做幾輪測試,只測試三名用戶有助于很快進行下一輪測試。由于你會修正在第一輪測試提出的問題,因此在第二輪測試中,就會發(fā)現新的問題。這樣的話,能夠很快的對測試進行總結,并能很快利用測試結果進行修正。

 

很多人不知道該招募怎樣的測試人員,總是很糾結,其實沒那么難。


實際上,我們都是初學者。就算找一位專家,你也有可能發(fā)現他也在勉強應付。


設計出的網站如果只有你的目標用戶能使用,這通常不是一個好的方法,應該既要滿足專家的要求也要滿足新手的要求。


例外:

如果你的網站幾乎由某一類用戶使用,那就只招募這一類用戶。


如果你的目標用戶群體可以分成幾個明顯的陣營,而且這些陣營有著完全不同的興趣和需要,那么至少要從每個陣營里選擇用戶進行一次測試。


同時避免對網站或網站背后的組織架構進行預先討論。


可以找任何人來引導測試,真正需要的工作只是鼓勵測試用戶去嘗試。同時還需要一個觀察人,對于觀察人選,建議如果能讓管理層參與就好了,他們的參加能極大鼓舞團隊的士氣,這是他們第一次看到自己的網站被人使用,而且很多地方和他們想象的畫面并不一樣,這樣的話,團隊也更容易向管理層拿到對測試的投資,可謂是一舉兩得。



測試什么,什么時候測試?


測試:顧名思義,就是讓測試用戶看到網站,然后看他們能否理解這個網站,包括目標,價值主張,組織方法和運行方式等。

可以對用戶進行關鍵任務測試,讓用戶完成一些任務,然后觀察他們是怎么做的。

 

立刻回顧測試結果


在測試后的討論會議上,主要做以下兩件事:


給問題分類:

回顧大家看到的問題,決定哪些問題需要修正。


解決問題:

找出修正這些問題的方法。


這樣,從其他人的角度看你的作品,常常能為問題提供全新的解決方案,或者讓你用一種新的眼光看待原有的問題。


要記住,這是一個循環(huán)的過程,不能只做一兩次就停止了。

  

測試常見問題:


1、用戶不清楚概念:用戶看著網站,要么不清楚他們說的是什么,要么他們以為自己知道,但是理解有誤。

2、他們找不到自己要找的字眼:這通常意味著你組織的內容分類不符合用戶的習慣或者分類符合他們的習慣,但沒有使用他們期望的名字。

3、內容太多了:有時候,他們要找的內容就在頁面上,但就是看不到,在這種情況下,你需要減少頁面上的整體干擾或者把他們需要看到的內容設置的更加醒目,讓它們從可視層次結構中更加突出。

 

在任何測試中,你都可能會遇到這樣的情況,用戶暫時出現錯誤,然后在不需要任何幫助的情況下回到原來的軌道。


只要出現問題的人馬上發(fā)現自己偏離了原來的主體,盡量不需要幫助就能回到原來的方向,這種情況看起來沒有擾亂他們的活動,就可以忽略這些??偟膩碚f,如果用戶關于在哪里找到他們需要的內容的第二次猜測總是對的,就可以了。


這樣的問題總會存在的,因為有些含混之處,總是沒有簡單的解決方法,不管怎么做,都會有一半用戶在第一次猜測的時候出錯,但每個人都會在第二次猜測之內找到,這樣就好。

 

當在測試時清楚看到人們沒有理解某些內容時,大部分人的第一反應是增加一些內容,例如一些注釋或者指導說明。


這樣的方法不對,正確的解決方案往往是去除某個或一些讓人混淆的內容,而不是增加另一些干擾。


而且不要太看重人們對新功能的需求,人們常常說“如果它能像某某”就好了,這樣的說法常常被看做是在要求新的功能,如果仔細詢問,常常會發(fā)現,他們已經找到一個很好的網站,能做某某功能,就算你做了這個功能,他們也不會切換到你的網站,他們只是在告訴你他們的喜好而已。

 

當大家看到第一個用戶試著勉強應付的時候,問題和解決方法都很明顯的那種驚喜,就像是現成的收獲,你應該馬上修正它們。

 

和任何好的設計一樣,成功的網頁需要巧妙的平衡,要記住,哪怕一個微小的變化都會帶來不小的影響,有時候,真正的挑戰(zhàn)不是修正你發(fā)現的問題,而是修正這些問題的同時不破壞已經正常運行的部分。


只要進行改變,就要仔細思考它將會影響哪些其他內容。特別是,當你把某些部分調整的更為突出時,想想看是不是把其他內容的重要性降低了。


降低網站好感度有幾種方式:

1、隱藏我想要的信息;

2、因為沒有按照你們的方式行事而懲罰我;

3、向我詢問不必要的信息:大多數用戶都很介意個人信息,如果網站要求的信息超出當前任務時,會讓用戶覺得很麻煩。

4、敷衍我,欺騙我:我們都會討厭虛偽的真誠,也討厭假意的關心,想想每次你聽到“您的電話對我們來說很重要”的時候是什么感覺吧!

5、給我設置障礙:不得不等待一個長長的flash介紹。

6、你的網站看上去不專業(yè):網站看起來很凌亂,組織很混亂。


就算你有些地方做的不好,也還有可能再度提高我的好感,只要讓我相信你的所作所為是在為我著想。


提高好感的幾種方式:

1、知道人們在你的網站上想做什么,并讓他們容易明白:把用戶最想做的幾件事放在最明顯的地方;

2、告訴我我想知道的。

3、盡量減少步驟,讓用戶以最快的途徑到達他們想去的地方。

4、知道我可能有哪些疑問,并且給予解答:可以做一個經常更新的常見列表。

5、為我提供協助。

6、容易從錯誤中恢復:當潛在的錯誤不可避免時,要提供一個快速且清晰的方法快速從錯誤中恢復。

7、如果不確定,記得道歉:有時候會因為暫時沒有能力或資源做到用戶想要的,如果你做不到,至少讓他們明白你知道你在給他們造成不便。

一個例子讓你明白原型對象和原型鏈

seo達人

開篇

之前對js中的原型鏈和原型對象有所了解,每當別人問我什么是原型鏈和原型對象時,我總是用很官方(其實自己不懂)的解釋去描述。有一句話說的好:如果你不能把一個很復雜的東西用最簡單的話語描述出來,那就說明你沒有真正的理解。最近正在讀《Javascript高級程序設計》,書中對原型對象和原型鏈的描述讓我受益匪淺,下面僅用一個對比性的例子來說明。



我們經常會這么寫

    function Person () {

        this.name = 'John';

    }

    var person = new Person();

    Person.prototype.say = function() {

        console.log('Hello,' + this.name);

    };

    person.say();//Hello,John

1

2

3

4

5

6

7

8

上述代碼非常簡單,Person原型對象定義了公共的say方法,雖然此舉在構造實例之后出現,但因為原型方法在調用之前已經聲明,因此之后的每個實例將都擁有該方法。從這個簡單的例子里,我們可以得出:



原型對象的用途是為每個實例對象存儲共享的方法和屬性,它僅僅是一個普通對象而已。并且所有的實例是共享同一個原型對象,因此有別于實例方法或屬性,原型對象僅有一份。



所以就會有如下等式成立:



    person.say == new Person().say

1

可能我們也會這么寫

    function Person () {

        this.name = 'John';

    }

    var person = new Person();

    Person.prototype = {

        say: function() {

            console.log('Hello,' + this.name);

        }

    };

    person.say();//person.say is not a function

1

2

3

4

5

6

7

8

9

10

很不幸,person.say方法沒有找到,所以報錯了。其實這樣寫的初衷是好的:因為如果想在原型對象上添加更多的屬性和方法,我們不得不每次都要寫一行Person.prototype,還不如提煉成一個Object來的直接。但是此例子巧就巧在構造實例對象操作是在添加原型方法之前,這樣就會造成一個問題: 

當var person = new Person()時,Person.prototype為:Person {} (當然了,內部還有constructor屬性),即Person.prototype指向一個空的對象{}。而對于實例person而言,其內部有一個原型鏈指針proto,該指針指向了Person.prototype指向的對象,即{}。接下來重置了Person的原型對象,使其指向了另外一個對象,即



 Object {say: function}

1

這時person.proto的指向還是沒有變,它指向的{}對象里面是沒有say方法的,因為此報錯。



從這個現象我們可以得出:



在js中,對象在調用一個方法時會首先在自身里尋找是否有該方法,若沒有,則去原型鏈上去尋找,依次層層遞進,這里的原型鏈就是實例對象的proto屬性。



若想讓上述例子成功運行,最簡單有效的方法就是交換構造對象和重置原型對象的順序,即:



    function Person () {

        this.name = 'John';

    }

    Person.prototype = {

        say: function() {

            console.log('Hello,' + this.name);

        }

    };

    var person = new Person();

    person.say();//person.say is not a function

1

2

3

4

5

6

7

8

9

10

一張圖讓你秒懂原型鏈

 



其實,只需要明白原型對象的結構即可:



    Function.prototype = {

        constructor : Function,

        proto : parent prototype,

        some prototype properties: ...

    };

1

2

3

4

5

總結:

函數的原型對象constructor默認指向函數本身,原型對象除了有原型屬性外,為了實現繼承,還有一個原型鏈指針proto,該指針指向上一層的原型對象,而上一層的原型對象的結構依然類似,這樣利用proto一直指向Object的原型對象上,而Object的原型對象用Object.prototype.proto = null表示原型鏈的最頂端,如此變形成了javascript的原型鏈繼承,同時也解釋了為什么所有的javascript對象都具有Object的基本方法。



Blog同步


w3cschool編程實戰(zhàn)之JavaScript 隊列

seo達人

JavaScript 隊列

題目:

在計算機科學中 隊列(queue)是一個抽象的數據結構,隊列中的數據條目都是有秩序的。新的條目會被加到 隊列 的末尾,舊的條目會從 隊列 的頭部被移出。



寫一個函數 queue ,用一個數組arr和一個數字item作為參數。數字item添加到數組的結尾,然后移出數組的第一個元素,最后隊列函數應該返回被刪除的元素。

queue([], 1) 應該返回 1

queue([2], 1) 應該返回 2

queue([5,6,7,8,9], 1) 應該返回 5

在 queue(testArr, 10) 之后, testArr[4] 的值應該是 10



通關答案:



function queue(arr, item) {

/下面這兩句是關鍵/

    arr.push(item);

    return arr.shift();// Change this line

}



console.log(queue([], 1));

console.log(queue([2], 1));

console.log(queue([5,6,7,8,9], 1));

// Test Setup

var testArr = [1,2,3,4,5];



// Display Code

console.log("Before: " + JSON.stringify(testArr));

console.log(queue(testArr, 10)); // Modify this line to test

console.log("After: " + JSON.stringify(testArr));



藍藍設計m.yvirxh.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業(yè)提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計  包裝設計 、 圖標定制  用戶體驗 、交互設計、 網站建設 、平面設計服務。

頁面跳轉的兩種方式(轉發(fā)和重定向)區(qū)別及應用場景分析

seo達人

轉發(fā)和重定向區(qū)別詳解

        作為一名程序員,特別是java web開發(fā)的程序員,在使用servlet/jsp的時候,我們必須要知道實現頁面跳轉的兩種方式的區(qū)別和聯系:即轉發(fā)和重定向的區(qū)別。



      1、RequestDispatcher.forward方法只能將請求轉發(fā)給同一個WEB應用中的組件;而HttpServletResponse.sendRedirect 方法不僅可以重定向到當前應用程序中的其他資源,還可以重定向到同一個站點上的其他應用程序中的資源,甚至是使用絕對URL重定向到其他站點的資源。如果傳遞給HttpServletResponse.sendRedirect 方法的相對URL以“/”開頭,它是相對于整個WEB站點的根目錄;如果創(chuàng)建RequestDispatcher對象時指定的相對URL以“/”開頭,它是相對于當前WEB應用程序的根目錄。、



      2、調用HttpServletResponse.sendRedirect方法重定向的訪問過程結束后,瀏覽器地址欄中顯示的URL會發(fā)生改變,由初始的URL地址變成重定向的目標URL;而調用RequestDispatcher.forward 方法的請求轉發(fā)過程結束后,瀏覽器地址欄保持初始的URL地址不變。



      3、HttpServletResponse.sendRedirect方法對瀏覽器的請求直接作出響應,響應的結果就是告訴瀏覽器去重新發(fā)出對另外一個URL的 訪問請求,這個過程好比有個綽號叫“瀏覽器”的人寫信找張三借錢,張三回信說沒有錢,讓“瀏覽器”去找李四借,并將李四現在的通信地址告訴給了“瀏覽器”。于是,“瀏覽器”又按張三提供通信地址給李四寫信借錢,李四收到信后就把錢匯給了“瀏覽器”??梢?,“瀏覽器”一共發(fā)出了兩封信和收到了兩次回復, “瀏覽器”也知道他借到的錢出自李四之手。RequestDispatcher.forward方法在服務器端內部將請求轉發(fā)給另外一個資源,瀏覽器只知道發(fā)出了請求并得到了響應結果,并不知道在服務器程序內部發(fā)生了轉發(fā)行為。這個過程好比綽號叫“瀏覽器”的人寫信找張三借錢,張三沒有錢,于是張三找李四借了一些錢,甚至還可以加上自己的一些錢,然后再將這些錢匯給了“瀏覽器”??梢?,“瀏覽器”只發(fā) 出了一封信和收到了一次回復,他只知道從張三那里借到了錢,并不知道有一部分錢出自李四之手。



       4、RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬于同一個訪問請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和response對象,它們屬于兩個獨立的訪問請求和響應過程。對于同一個WEB應用程序的內部資源之間的跳轉,特別是跳轉之前要對請求進行一些前期預處理,并要使用HttpServletRequest.setAttribute方法傳遞預處理結果,那就應該使用RequestDispatcher.forward方法。不同WEB應用程序之間的重定向,特別是要重定向到另外一個WEB站點上的資源的情況,都應該使用HttpServletResponse.sendRedirect方法。



        5、無論是RequestDispatcher.forward方法,還是HttpServletResponse.sendRedirect方法,在調用它們之前,都不能有內容已經被實際輸出到了客戶端。如果緩沖區(qū)中已經有了一些內容,這些內容將被從緩沖區(qū)中。



以上五點的論述來源于:點擊查看原文論述



轉發(fā)和重定向的圖解





兩種跳轉獲得對象的方式

//獲得轉發(fā)對象getRequestDispatcher()

HttpServletRequest(httpServletRequest).getRequestDispatcher

ServletContext.getRequestDispatcher();

 

//獲得重定向對象sendRedirect()

HttpServletResponse(httpServletResponse).sendRedirect();

轉發(fā)和跳轉的小結

      1、轉發(fā)使用的是getRequestDispatcher()方法;重定向使用的是sendRedirect();



      2、轉發(fā):瀏覽器URL的地址欄不變。重定向:瀏覽器URL的地址欄改變;



      3、轉發(fā)是服務器行為,重定向是客戶端行為;



      4、轉發(fā)是瀏覽器只做了一次訪問請求。重定向是瀏覽器做了至少兩次的訪問請求;



      5、轉發(fā)2次跳轉之間傳輸的信息不會丟失,重定向2次跳轉之間傳輸的信息會丟失(request范圍)。



轉發(fā)和重定向的選擇

      1、重定向的速度比轉發(fā)慢,因為瀏覽器還得發(fā)出一個新的請求,如果在使用轉發(fā)和重定向都無所謂的時候建議使用轉發(fā)。



      2、因為轉發(fā)只能訪問當前WEB的應用程序,所以不同WEB應用程序之間的訪問,特別是要訪問到另外一個WEB站點上的資源的情況,這個時候就只能使用重定向了。



轉發(fā)和重定向的應用場景

       在上面我已經提到了,轉發(fā)是要比重定向快,因為重定向需要經過客戶端,而轉發(fā)沒有。有時候,采用重定向會更好,若需要重定向到另外一個外部網站,則無法使用轉發(fā)。另外,重定向還有一個應用場景:避免在用戶重新加載頁面時兩次調用相同的動作。



       例如,當提交產品表單的時候,執(zhí)行保存的方法將會被調用,并執(zhí)行相應的動作;這在一個真實的應用程序中,很有可能將表單中的所有產品信息加入到數據庫中。但是如果在提交表單后,重新加載頁面,執(zhí)行保存的方法就很有可能再次被調用。同樣的產品信息就將可能再次被添加,為了避免這種情況,提交表單后,你可以將用戶重定向到一個不同的頁面,這樣的話,這個網頁任意重新加載都沒有副作用;



       但是,使用重定向不太方便的地方是,使用它無法將值輕松地傳遞給目標頁面。而采用轉發(fā),則可以簡單地將屬性添加到Model,使得目標視圖可以輕松訪問。由于重定向經過客戶端,所以Model中的一切都會在重定向時丟失。但幸運的是,在Spring3.1版本以后,我們可以通過Flash屬性,解決重定向時傳值丟失的問題。



       要使用Flash屬性,必須在Spring MVC的配置文件中添加一個<annotation-driven/>。然后,還必須再方法上添加一個新的參數類型:org.springframework.web.servlet.mvc.support.RedirectAttributes。



       如下所示:



@RequestMapping(value="saveProduct",method=RequestMethod.POST)

public String saveProduct(ProductForm productForm,RedirectAttributes redirectAttributes){

 

     //執(zhí)行產品保存的業(yè)務邏輯等

  

     //傳遞參數

       redirectAttributes.addFlashAttribute("message","The product is saved successfully");

   

     //執(zhí)行重定向

      return "redirect:/……";



藍藍設計m.yvirxh.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業(yè)提供卓越的UI界面設計、BS界面設計 、 cs界面設計  ipad界面設計 、 包裝設計 、 圖標定制  用戶體驗 、交互設計、 網站建設 平面設計服務。

日歷

鏈接

個人資料

藍藍設計的小編 http://m.yvirxh.cn

存檔