首页

干货|尼尔森十大可用性原则案例解析

鹤鹤

尼尔森的十大可用性原则,它们被称为「启发式」,<br>被奉为交互设计师的入门法则。

开篇灵魂拷问:


你认为一个怎样的产品才算是一个好的产品?

这个问题耳熟吗?面试的时候是不是有被问到过?
我们经常使用的那些产品,哪些是好的产品呢?

当我们谈论一个 APP 产品时,
作为用户你最关心的是什么?
一般都是是这个产品好用吗?功能复杂吗?
而不是这个产品用户界面颜色好看吗?
交互的动效酷炫吗?

互联网已经深入到每个人的生活当中,
时刻影响着我们;
一个好的产品会给我们带来便捷,
使我们的生活变得简单而又美好;
也会有一些产品使用时会感到不舒服,
糟糕的产品体验会让我们的生活变得复杂而又烦恼。
所以,决定一个产品好不好用,
能不能长期使用都是用户体验直接决定的。
用户体验关注的是在满足用户需求的同时带给用户美好的感受。

接下来我们来聊一聊「尼尔森十大原则」,
这十大原则是具体而又全面的用户体验可行性检验方法。

    
尼尔森是谁?
雅各布·尼尔森(Jakob Nielsen)是毕业于哥本哈根的丹麦技术大学的人机交互博士,他拥有79项美国专利,专利主要涉及让互联网更容易使用的方法。于1995年1月1日发表了「十大可用性原则」。1995年以来,他通过自己的 Alertbox 邮件列表以及 useit.com 网站,向成千上万的 Web 设计师传授 Web 易用性方面的知识,尽管他的一些观点可能带来争议,至少在 Web 设计师眼中,他是 Web 易用性领域的顶尖领袖。2006年4月,并被纳入美国计算机学会人机交互学院,被赋予人机交互实践的终身成就奖。他还被纽约时报称为“Web 易用性大师”,被 Internet Magazine 称为 “易用之王”。
        
尼尔森的十大可用性原则,它们被称为「启发式」,      
    
    
是广泛的经验法则,而不是特定的可用性指导原则。
虽然是1995年提出来的,
但是至今仍然被奉为交互设计师的入门法则,
我们不能把它上升为一种标准,
而只当做一种经验来学习,
然后跟现实中的设计结合来使用。
因为尼老师是从 web 设计提出的十大可用性原则,
我们要结合的是目前移动互联网的特点,

然后在「尼尔森十大原则」的结构下探讨在用户体验上达到的目标。


尼尔森十大可⽤用性原则为:

01. 状态可见原则 

02. 环境贴切原则 

03. 撤销重做原则

04. 一致性原则 

05. 防错原则

06. 易取原则 

07. 灵活原则 

08. 易扫原则 

09. 容错原则 

10. 人性化帮助原则


下面我们就针对每一条来单独分析一下吧~


 ·.  状态可见原则 
系统应该让用户知道发生了什么,
在适当的时间内做出适当的反馈。
不要蒙蔽用户;
沟通是所有关系的基础,无论⼈还是设备。

示例:在淘宝里,我下拉时他告诉我「松开刷新」,也就是现在还没有开始刷新;我松开后状态变更成「刷新中」,表示现在正在刷新。
这样的设计告诉我们,界面现在是什么状态,现在在干嘛,在整个功能的变化过程中我们都能看到对应的文字描述。


其他示例:下拉刷新时的加载中,加载完成提示,收藏成功、支付成功、实付失败等提示。


·. 环境贴切原则

功能和服务贴近用户使用的场景,

符合当前场景用户的体验。

产品的功能和服务应该贴近真实世界,

让信息更自然,逻辑上也更容易被用户理解。


示例:我们在店里买东西的时候经常会听到这样的声音「支付宝导致:5元」就是贴近环境的设计。
商家需要确认你是否付钱,
但是又经常忙于手头的事情无法及时查看;
而这样功能的设计,商家即使在忙着手头的事情依然能通过声音来确认已经收到你的钱了。
这样的设计对于商家和消费者是友好便捷的。


 ·.  撤销重做原则 

在使用产品时了解和掌控当前页面。

如果用户误操作,可以随时撤销,用户在使用产品时足够自由。


示例1:我们用微信和对方聊天时,当我们写了很多字,发出去时却发现其中有错误,这时我们可以使用微信的撤回功能,体验更好的是,撤回消息旁边有「重新编辑」功能,可以让之前编辑的文本回到对话框重新编辑再发送。如下图:


示例2:iOS系统照片的删除和撤回


·. 一致性原则

同样的文字、状态、按钮,都应该触发相同的事情,遵从通用的平台惯例。也就是,同一用语、功能、操作保持一致。主要包括以下五个方面:


1. 结构一致性

保持一种类似的结构,新的结构变化会让用户思考,规则的排序能减轻用户的思考负担。

示例:微信中每个模块的条目都有统一的「图标+文字信息」的结构样式,能让用户快速了解每一个模块;


2. 色彩一致性

产品所使用的主要色调应该是统一的,而不是换一个页面,颜色就不同。

示例:淘宝的图标颜色与界面的主色均为橙色,也包括其中一些标签和强调的文字颜色都是橙色色。整个界面除了图片的有效信息外,都通过灰、白、橙色色来呈现,界面保持了很好的一致性;


3. 操作一致性

能在产品更新换代时仍然让用户保持对原产品的认知,减小用户的学习成本。

示例:微信在对话框和通讯录都采用了左滑出操作的交互,如下图:


4. 反馈一致性

用户在操作按钮或者条目的时候,点击的反馈效果应该是一致的。

示例:QQ的每个分组点击后都是向下展开组内成员列表;


5. 文字一致性
产品中呈现给用户阅读的文字大小、样式、颜色、布局等都应该是一致的。
示例:例如微信几个关键界面的字体:三个主界面内容结构不尽相同,但是,列表的标题字体和间距都一样,这样让整个APP视觉上看起来很舒服;


 ·.  防错原则
比出现错误信息提示更更好的是,用设计防⽌止这类问题发生。在用户选择动作发⽣生之前, 就要防止用户容易混淆或者错误的选择。

1. 限制操作范围与条件;
示例:未输入验证码前,底部的登录按钮是置灰不可点击的,只有填写完整,底部的登录按钮才会变为可点击状态。这就是为了防止用户犯更多错误;


2. 对有风险的操作进⾏二次确认;
示例:删除个好友时,通过二次弹窗给出防错措施。

·. 易取原则

减少用户记忆负荷,在适合的时机给用户需要获取的信息。
1. 为用户提供历史记录、关注、收藏等功能;
示例:爱奇艺为用户提供了看过记录和我的收藏,帮助用户记忆:



2. 选择而不是输入,尽量降低输入成本;

示例1:打车软件自动获取当前位置;

示例2:iOS系统收到验证码后自动带入到键盘,点击直接输入;


·. 灵活原则

对于新用户来说,需要功能明确、清晰,对于老用户需要快捷使用高频功能。不可为了某一种用户,把不必要的信息占据重要部分。主要体现在3个方面:

1. 自定义功能或模块的展示位置;

示例:支付宝首页的应用是可以根据自身喜好自定义的,包括定义常用应用、排序、删除、新增等等。这样用户可以根据自己的个人兴趣定制自己适合的应用分布方式,这就叫做用户定制常用功能,如下图:


2. 将“常用”自动归纳以提升使用效率;

示例:微信聊天界面表情弹窗中会有一个「最近使用」的模块,它把个人平时使用频率或者次数最多的表情进行归类。当用户使用的时候,能很快的找到自己喜欢或者常用的表情,提高了聊天效率;包括饿了么的「我的订单」里的每一个订单都可以通过再来一单重新一键下单,如下图:


3. 缩短操作路路径,提升使⽤用效率与体验;

示例:微信的对话框,当点击「+」调出下面的操作选项时,会默认弹出刚截图或拍照的照片,方便用户直接调取,还有APP长按后出来的快捷操作列表,如下图:


·. 易扫原则

直译:美学和简约的设计;页面不应包含不相关或很少需要的信息,页面中的每个额外信息都会降低主要内容的相对可见性。

示例:如下图列表中出现的信息都是用户比较关注的信息,比如配送费,配送时间,距离等;携程的选择机票界面讲最重要的时间和机票价格放大突出,让用户能一眼看到,如图:


 9 ·. 容错原则

直译:帮助用户识别、诊断和从错误中恢复;我们尽量避免用户出现错误,但当出现错误时,我们应该尽量去安抚用户的挫败感。

⽤配图+文字代替「404」,明确告诉用户哪⾥错了和解决方案。

示例:界面加载失败时的刷新提示,还有登录时的手机号码校验,如果手机格式错误会出现会提示用户手机格式不正确和正确的格式。


 10 ·. 人性化帮助

帮助性提示最好的方法是:

1.无需提示:非常简单易懂,用户看界面就知道怎么操作,无需提示;

2.一次性提示:只需要一次提示用户就懂如何使用;

示例:常见的新功能引导、引导⻚等,示例:


3.常驻提示: 较重要的提示,用于指导或帮助用户;

示例:支付宝转账时,常驻在顶部的安全确认提示,还有转账时的服务费提示,如图:


4.帮助文档:稍微复杂一点的软件,虽然要让他尽量简单但帮助文档都是必要的;

示例:微信设置界面里的「帮助与反馈」,还有支付宝转账时弹出来的「求助反馈」,点进去后的常见问题界面;


以上就是我对Jakob Nielsen(雅各布·尼尔森)的十大交互设计原则的理解和实例解读,希望对大家有所帮助。如果大家同样对这些方面有些兴趣或者看了后有些什么想法,欢迎一起讨论。

转自:站酷-搞设计的月野兔



Vue源码剖析(三)patch和Diff算法

seo达人

Patch和Diff算法

网上看了好多的博客和源码教程,感觉很多仔细的地方没有说清,而且在一些复杂的部分加了好多的描述,所以就想自己也写下心得, 方便自己, 方便他人,有兴趣的同学可以关注我的github里面有我之前一些博文 github/193Eric



我们知道的,在数据更改后,会触发getter,然后通过dep.notify()来通知watcher触发update进而更新视图,最终是通过Diff算法来对比新老Vnode的差异,并把差异更新到Dom视图上



Diff

我们知道的,Virtual DOM是一颗树,而diff算法主要把两颗树进行对比,找出之间的差异,来渲染页面



diff 算法是通过同层的树节点进行比较而非对树进行逐层搜索遍历的方式,所以时间复杂度只有 O(n),是一种相当的算法



1.调用patch函数比较Vnode和OldVnode,如果不一样直接return Vnode即将Vnode真实化后替换掉DOM中的节点



2.如果OldVnode和Vnode值得进一步比较则调用patchVnode方法进行进一步比较,分为以下几种情况:



Vnode有子节点,但是OldVnode没有,则将Vnode的子节点真实化后添加到真实DOM上



Vnode没有子节点,但是OldVnode上有,则将真实DOM上相应位置的节点删除掉



Vnode和OldVnode都有文本节点但是内容不一样,则将真实DOM上的文本节点替换为Vnode上的文本节点



Vnode和OldVnode上都有子节点,需要调用updateChildren函数进一步比较



updateChildren比较规则



提取出Vnode和OldVnode中的子节点分别为vCh和OldCh,并且提出各自的起始和结尾变量标记为 oldS oldE newS newE



如果是oldS和newE匹配上了,那么真实dom中的第一个节点会移到最后



如果是oldE和newS匹配上了,那么真实dom中的最后一个节点会移到最前,匹配上的两个指针向中间移动



如果都没有,在没有key的情况下直接在DOM的oldS位置的前面添加newS,同时newS+1。在有key的情况下会将newS和Oldch上的所有节点对比,如果有相同的则移动DOM并且将旧节点中这个位置置为null且newS+1。如果还没有则直接在DOM的oldS位置的前面添加newS且newS+1

直到出现任意一方的start>end,则有一方遍历结束,整个比较也结束



updateChildren例子:



假设:



真实dom为 A、B、C

oldDom为 A1、B1、C1

newDom为 A2、D2、C2、B2



先确定oldS = A1 ; oldE = C1; newS = A2; newE = B2



先对比oldS和newS,oldE和newE,发现oldS = newS 所以真实dom的A固定不动。排序为 A、B、C

然后oldS = B1 ; oldE = C1; newS = D2; newE = B2



对比发现 oldS = newE , 所以真实dom,B要插入到后面去



真实dom排序为:A、C、B



然后oldS = C1; oldE = C1; newS = D2; newE = B2



对比发现两两都不对等,所以走第三步。

假设有key存在,所以newS直接和oldDom里面的所有节点对比,发现没有存在,然后插入到oldS前面,且newS+1

真实dom排序为:A、D、C、B

然后重新开始,oldS++ > oldE-- ,结束了。



这就是updateChildren,之后就是一直遍历,运行updateChildren直到没有


一文秒懂 ajax, fetch, axios

seo达人

1, JavaScript的Ajax

Ajax的全称是Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求,而不需要重载(刷新)整个页面。

Ajax使用XMLHttpRequest对象取得新数据,然后再通过 DOM 将新数据插入到页面中。另外,虽然名字中包含 XML 的成分,但 Ajax 通信与数据格式无关; 这种技术就是无须刷新页面即可从服务器取得数据,但不一定是 XML 数据。

对于IE7+和其他浏览器,可以直接使用XMLHttpRequest对象,对于IE6及以前的浏览器,使用ActiveXObject对象。



使用方法如下:



var xhr;

if (window.XMLHttpRequest) {

    xhr = new XMLHttpRequest();

} else {

    xhr = new ActiveXObject('Microsoft.XMLHTTP');

}

1

2

3

4

5

6

启动请求:



xhr.open(method, url, boolean);     

xhr.send();

1

2

注:

1,xhr.open参数含义:

method:请求方式,post、get等

url: 请求链接,只能向同源的url发送请求

boolean:是否异步请求,true:异步, false: 同步,默认为true

2,调用 open()方法并不会真正发送请求, 而只是启动一个请求以备发送。

3,send()方法接收一个参数,即要作为请求主体发送的数据(post方法会使用,get方法直接传null)。如果不需要通过请求主体发送数据,则必须传入 null,因为这个参数对有些浏览器来说是必需的。调用send()之后,请求就会被分派到服务器。



XMLHttpRequest对象的异步请求示例如下:



function success(text) {

    console.log(text);

}



function fail(code) {

   console.log(code);

}



var xhr = new XMLHttpRequest();     // 新建XMLHttpRequest对象

xhr.onreadystatechange = function () { 

    // 状态发生变化时,函数被回调

    if (xhr.readyState === 4) { // 成功完成

        // 判断响应结果:

        if (xhr.status === 200) {

            // 成功,通过responseText拿到响应的文本:

            return success(xhr.responseText);

        } else {

            // 失败,根据响应码判断失败原因:

            return fail(xhr.status);

        }

    } else {

        // HTTP请求还在继续...

    }

}



// 发送请求:

xhr.open('get', '/api/categories');

xhr.send(null);

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

xhr的属性含义如下:

responseText: 作为响应主体被返回的文本。

responseXML: 如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存响应数据的 XML DOM 文档。

status: 响应的 HTTP 状态。

statusText: HTTP 状态的说明。

readyState :表示请求/响应过程的当前活动阶段。可取值如下。

0: 未初始化。尚未调用 open()方法。

1: 启动。已经调用 open()方法,但尚未调用 send()方法。

2: 发送。已经调用 send()方法,但尚未接收到响应。

3: 接收。已经接收到部分响应数据。

4: 完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

只要 readyState 属性的值由一个值变成另一个值,都会触发一次 readystatechange 事件。可以利用这个事件来检测每次状态变化后readyState 的值。通常,我们只对 readyState 值为 4 的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用 open()之前指定 onreadystatechange事件处理程序才能确保跨浏览器兼容性。



另外,在接收到响应之前还可以调用 abort()方法来取消异步请求:



xhr.abort();

1

调用这个方法后,XHR 对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。在终止请求之后,还应该对 XHR 对象进行解引用操作。由于内存原因,不建议重用 XHR 对象。



2, jQuery的Ajax

$.ajax({

        url:"",

        type:"GET",

        contentType: '',

        async:true,

        data:{},

        dataType:"",

        success: function(){

        }

});

1

2

3

4

5

6

7

8

9

10

url 必填项,规定把请求发送到哪个 URL。

type 以什么样的方式获取数据,是get或post

contentType:发送POST请求的格式,默认值为’application/x-www-form-urlencoded;

charset=UTF-8’,也可以指定为text/plain、application/json

async 是否异步执行AJAX请求,默认为true,千万不要指定为false

data 发送的数据,可以是字符串、数组或object。如果是GET请求,data将被转换成query附加到URL上,如果是POST请求,根据contentType把data序列化成合适的格式;

dataType

接收的数据格式,可以指定为’html’、‘xml’、‘json’、'text’等,缺省情况下根据响应的Content-Type猜测。

success 可选。执行成功时返回的数据。

缺点:

是基于XHR原生开发的,目前已有的fetch可替代。本身是针对mvc的编程模式,不太适合目前mvvm的编程模式。jQuery本身比较大,如果单纯的使用ajax可以自己封装一个,不然会影响性能体验。



3,Axios

Vue2.0之后,axios开始受到更多的欢迎。其实axios也是对原生XHR的一种封装,不过是Promise实现版本。它是一个用于浏览器和 nodejs 的 HTTP 客户端,符合的ES规范。



axios具有以下特征:



从浏览器中创建 XMLHttpRequest

支持 Promise API

客户端支持防止CSRF

提供了一些并发请求的接口

从 node.js 创建 http 请求

拦截请求和响应

转换请求和响应数据

取消请求

自动转换JSON数据

PS:防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。



设置全局的 axios 默认值



axios.defaults.baseURL = 'https://api.example.com';

axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

1

2

3

注:axios 的 headers的 content-type 默认是 “application/json ”



默认情况下,axios将JavaScript对象序列化为JSON,如果是get请求,对请求参数不用做任何处理,但是如果是post请求,并且Content-Type 为application/x-www-form-urlencoded,需要使用URLSearchParams API格式化请求参数, 否则Content-Type依然是application/json



var params = new URLSearchParams();

params.append('param1', 'value1');

params.append('param2', 'value2');

1

2

3

get请求,以下3中写法完全等价



axios.get('/user?id=12345&name=xiaoming')

.then(function (response) {

    console.log(response);

})

.catch(function (error) {

    console.log(error);

});

1

2

3

4

5

6

7

axios.get('/user', {

    params: {

      id: '12345',

      name: 'xiaoming'

    }

})

.then(function (response) {

    console.log(response);

})

.catch(function (error) {

    console.log(error);

});

1

2

3

4

5

6

7

8

9

10

11

12

axios({

    url: '/user',

    method: 'get',

    params: {

      id: '12345',

      name: 'xiaoming'

    }

})

.then(function (response) {

    console.log(response);

})

.catch(function (error) {

    console.log(error);

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

post请求,以下2种写法完全等价



axios({

    url: '/user',

    method: 'post',

    headers: {

        'Content-Type': 'application/json'

    },

    data: {

      id: '12345',

      name: 'xiaoming'

    }

})

.then(function (response) {

    console.log(response);

})

.catch(function (error) {

    console.log(error);

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

var url = '/user';

var data = {

      id: '12345',

      name: 'xiaoming'

    };

axios.post(url, data, {

       headers: {

        'Content-Type': 'application/json'

    }

})

.then(function (response) {

    console.log(response);

})

.catch(function (error) {

    console.log(error);

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

执行多个并发请求



function getUserAccount() {

  return axios.get('/user/12345');

}

 

function getUserPermissions() {

  return axios.get('/user/12345/permissions');

}

 

axios.all([getUserAccount(), getUserPermissions()])

  .then(axios.spread(function (acct, perms) {

    // 两个请求现在都执行完成

}));

1

2

3

4

5

6

7

8

9

10

11

12

创建实例



可以使用自定义配置新建一个 axios 实例



axios.create([config])

var instance = axios.create({

  baseURL: 'https://some-domain.com/api/',

  timeout: 1000,

  headers: {'X-Custom-Header': 'foobar'}

});

1

2

3

4

5

6

配置会以一个优先顺序进行合并,顺序由低到高为

1,在 node_modules/axios/lib/defaults.js 找到的库的默认值

2,实例的 defaults 属性

3,请求的 config 参数



// 使用由库提供的配置的默认值来创建实例

// 此时超时配置的默认值是 0

var instance = axios.create();

 

// 覆写库的超时默认值

// 现在,所有请求都会等待 2.5 秒

instance.defaults.timeout = 2500;

 

// 为已知需要花费很长时间的请求覆写超时设置

instance.get('/longRequest', {

  timeout: 5000

});

1

2

3

4

5

6

7

8

9

10

11

12

拦截器



在请求发出之前或响应被 then 或 catch 处理前拦截它们做预处理。



// 添加请求拦截器

axios.interceptors.request.use(function (config) {

    // 在发送请求之前做些什么

  }, function (error) {

    // 对请求错误做些什么

  });

 

// 添加响应拦截器

axios.interceptors.response.use(function (response) {

    // 对响应数据做点什么

  }, function (error) {

    // 对响应错误做点什么

  });

1

2

3

4

5

6

7

8

9

10

11

12

13

可以在稍后移除拦截器:



var myInterceptor = axios.interceptors.request.use(function () {/.../});

axios.interceptors.request.eject(myInterceptor);

1

2

可以为自定义 axios 实例添加拦截器



var instance = axios.create();

instance.interceptors.request.use(function () {/.../});

1

2

4, fetch

window 自带了 window.fetch 方法, 在版的 Firefox 和 Chrome 中已经提供支持,其他浏览器还有兼容性问题,要做兼容性处理。fetch 是一个 基于promise设计的low-level API,不是ajax的进一步封装,而是原生js,它注定不会像你习惯的 $.ajax 或是 axios 等库帮你封装各种各样的功能或实现.



interface GlobalFetch {

    fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;

}

1

2

3

fetch()是一个全局的函数,返回一个promise对象。它有两个参数,第一个参数是请求的地址,第二个参数是可选,RequestInit是个对象格式如下:



interface RequestInit {

    body?: any;

    cache?: RequestCache;

    credentials?: RequestCredentials;

    headers?: HeadersInit;

    integrity?: string;

    keepalive?: boolean;

    method?: string;

    mode?: RequestMode;

    redirect?: RequestRedirect;

    referrer?: string;

    referrerPolicy?: ReferrerPolicy;

    window?: any;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

优点:

符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里

更好更方便的写法

更加底层,提供的API丰富

脱离了XHR,是ES规范里新的实现方式

fetch中可以设置mode为"no-cors"(不跨域)



缺点:

fetch不支持同步请求

fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理

fetch默认不会带cookie,需要添加配置项

fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费

fetch没有办法原生监测请求的进度,而XHR可以



fetch的使用示例:



window.fetch(url)

    .then(response => {

        if (response.ok) {

            //通过 response 原型上的 json 方法将 response.body 转换为 JS 对象,再返回出去

            return response.json();

        }

    }

).then(result => {

    console.log(result);

}).catch(error => {

    console.log(error);

})

1

2

3

4

5

6

7

8

9

10

11

12

需要注意以下几点:

1,用 response.ok判断fetch请求是否成功

2,服务端只返回了response对象,而真正的请求结果,即 response.body,则是一个 ReadableStream。fetch 将 response.body 设计成 ReadableStream 在请求大体积文件时变得非常有用。然而,在我们的日常使用中,还是短小的 JSON 片段更加常见。而为了兼容不常见的设计,我们不得不多一次 response.json() 的调用。不仅是调用变得麻烦,如果你的服务端采用了严格的 REST 风格,对于某些特殊情况并没有返回 JSON 字符串,而是用了 HTTP 状态码(如:204 No Content),那么在调用 response.json() 时则会抛出异常。

3,Response 限制了响应内容的重复读取和转换,response .json / response.text 方法只能使用一个并且只能使用一次,同时使用两个,或使用两次都会报如下错误:



Uncaught (in promise) TypeError: Failed to execute 'json' on 'Response': body stream is locked

1

为什么不能使用两次?

因为数据流只能读取一次,一旦读取,数据流变空,再次读取会报错。

————————————————

版权声明:本文为CSDN博主「Sherry慈」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_41480546/article/details/102805864

重磅发布!天猫双十一品牌设计背后的故事

涛涛

一年一度,天猫双十一全球狂欢节,如约而至!

从2015年开始,我们每年都会在双十一期间,将双十一品牌设计的完整思路分享给大家,这已经成为双十一设计团队的传统。不为别的,各位同仁辛苦一年,想跟大家就着新鲜出炉的设计唠唠嗑。

每逢双十一logo出街,都会有热心的朋友帮我们解读,也有人问我们为啥不搞个官方发布?各位朋友,您现在看到的就是官方发布的内容,它不只有logo,而是从头到尾一个完整的故事。

△ 2019天猫双十一主logo

△ 2019天猫双十一主logo多语言版本

今年是双十一的第十一年,当我们接到这个任务的时候,就有机灵的同学提议:「我们用6个1吧,111111,61儿童节!」、「让我们回归购物的纯真快乐!」。

「哈哈哈哈哈哈…」魔性的笑声在整个会议室回荡,看来往年挠破头也解不开的难题,就这么解开了?故事当然不会这么简单,我们还没有往这个方向尝试就被否了。

  • 其一,双十一是一个深入人心的认知,这四个一已经成为了超级符号,是我们宝贵的品牌资产,而六个一不但不能帮我们强化认知价值,反而会增加认知成本。
  • 其二,六个一是一个纯视觉的创意,他很难支撑起我们要传达的消费者价值,也很难建立起情感连接。

我们应该从哪儿入手?

回归到设计的本质来思考,我们认为,设计的本质是将一个想法或者观点巧妙的表达给目标对象,表达的过程中,形式只是手段,重点在于我们要表达什么。

我们集合了阿里各事业部的设计师代表,让大家回归到一个普通消费者的状态,一起聊一聊各自的双十一故事,把这些故事提炼出来,就是消费者对于双十一普遍真实的认知。在全年最便宜的一天,无论凑热闹也好,跟风也好,贪便宜也好,好像不买点什么总感觉错过了什么。在这一天,「购物」毫无疑问成为头等重要的事情。

△ 阿里巴巴经济体设计师共创

那么我们要对消费者表达「购物」吗,讲我们多么便宜,货品多么丰富,多么物美价廉?这些是消费者早就形成的认知,是我们不用表达大家都知道的事,它看起来并不是一个想法和观点。

还是购物,但肯定不是教大家怎么购物,作为消费者,购物能给我们带来什么?

有人说,购物能让我们吃饱穿暖,让我们出行方便,让我们安居无忧。

如果这些你都有,你为什么还要购物?

因为每个人都向往更好的生活!

为了更好的生活,我们需要通过物品的改善带来心理的满足感。当然也有人会会说,满足感也可以通过其他的方式获取,比如关爱他人、亲近自然、学习、修行、冥想等等,我们非常认同,更好的生活当然不仅仅只有购物。但我们当下探讨的范畴仅仅只是「购物」以及「购物」能带来的满足感,对这种满足感的期待,是每一个消费行为的动因。比如你想要买一件新衣服的时候,其实你已经在期待穿上这件新衣服的样子,你在挑选一件礼物的时候,已经在期待他人收到这件礼物时的反应……

双十一,全年最便宜的一天,无疑让你的期待,变得「更值得」期待,所以「更值得」让大家买得更多。

但,这些洞察还只是帮我们理清了消费行为背后的共性规律,实际上,细分到每个消费者,因为身份角色生活方式的不同,动因各自不同,还不能简单的用向往更好的生活来概括,因为它太抽象,听上去对,但每个消费者更关心的是我的需求是不是被满足,而对于双十一来讲,我们就是要打造属于每一人的双十一,而不仅仅只是购物,这样它才具有节日的文化属性。

所以,我们开始探寻真实的消费者故事,寻找那些通过物品让生活变得更好的故事,这些真实的故事,给了我们很大的感触。我们发现,购物行为下,其实还隐藏了每一个消费者内心更深层的需求,它是一个个藏在心底的愿望,正是这些不同人的愿望,成就了每一个平凡人鲜活的人生。我们想要帮助他们实现自己的愿望。在双十一当天,帮助每个消费者「愿望11实现」!这才是双十一更应该满足的消费者需求,它不仅仅是购物,而是通过物品价值上升到情感价值,这样的品牌,才真正能够让人感受到温度。

在倾听这些故事的时候,我们的阿里女神被感动了,她主动要求帮我们写一首歌,她想把她的感动通过音乐的方式记录下来,配合我们精选出来的11个故事,讲给大家听。

△ 双十一品牌设计概念篇mv

「logo出来了?」低沉而沙哑的声音,把我们从自我陶醉中唤醒,我们找到了想要表达什么,但和怎么表达之间还隔着上百个logo方案。

于是,我们开始了一轮又一轮的打磨,打磨的的重点放在了如何表达「愿望11实现」这一主题,这个过程中,有两个大方向上的分歧:

一个大方向是表现「愿望」,因为它比较有画面感,也比较容易表达。

另一个大方向是表现「实现」,因为它是对结果的描述,更符合消费者对结果的预期。

在纠结挣扎过后,我们选择了把两个方向融合,剧情貌似又回到了熟悉的设计故事,「把这两个方案融合一下!」我相信做设计的朋友,一定反复听过这句话,没听过的朋友,那说明你做设计还不久,我保证在你今后的职业生涯里,这句话一定会反复出现。(一个会心的微笑)

融合说起来容易,这么抽象的文字怎么转换成图形表达,同时还要和猫头+11.11融合,为什么要和猫头+11.11融合呢,因为这是我们重要的品牌形象资产,从2015年开始,猫头+11.11的组合就固定下来了,这意味着logo的80%的主体已经固定,我们的难点就在于在这20%的区域里,如何既要表达主题,还能做出和往年不一样的感觉。我敢向你保证,双十一的logo是所有logo里最难的,没有之一,至少是我十几年职业生涯里最硬的茬。

「愿望、实现、猫头、11.11」这几个词反复在脑海里萦绕,经验告诉我们,当面对如此复杂的局面,我们应该从里面跳出来,换个视角看问题,换什么视角?当然还是再次回到消费者视角,消费者愿望实现时是一种什么样的状态?是愿望实现时的满足?好像还差点意思,愿望平时也能实现,和在双十一实现愿望有什么不同?

我们认为,它应该是超越你期待的表达,从愿望实现时的满足,升级到愿望实现时的惊喜!这才是狂欢节该有的味道。当然,惊喜也有很多种它还不够有体感,如何找准惊喜体感?

答案是感同身受。于是我们开始了场景模拟,模拟消费者逛双十一的场景。

当我们来到双十一的时候:「咦!今年好像真的不一样!」

继续探索的时候:「呀!找了好久的idou同款原来在这里!」

准备下单的时候:「喔!真的很便宜!」

收到快递的时候:「哇!!!!」

听上去有点夸张,但这确实是我们想要营造给消费者的惊喜,当人感到超越期待的惊喜时,会不自觉的放大瞳孔、张开嘴巴脱口而出。这是人类共通的体感,是不用解释就有的共鸣。这让我们瞬间被点亮了,「惊喜到脱口而出!」我们一下子找到了核心创意。

通过反复尝试,我们发现气泡形的表达,不仅能成为承载所有消费者愿望的想法框,同时也能成为表达愿望实现时惊喜到脱口而出的对话框,把这个气泡形和猫头+11.11结合,这就是我们今年双十一主logo的原由,这个logo和以往双十一的logo最大的不同在于,它更像是一个容器,容纳不同人不同的个性化表达。它一改之前一直端着的状态,以一种更加亲民,更加个人化的方式呈现给大家。

△ 2019天猫双十一品牌logo演绎视频

当然,作为容器,我们还要把核心创意延展到线上线下各个场景。

△ 双十一定制礼盒

△ 走向全球的双十一

过去几年,我们向大家介绍过天猫双11的主风格的来龙去脉,一定会在创新的基础上,保持一贯的传承。所以今年波普艺术的主基调还是会延续下去,问题又回到了我们如何在波普艺术这个大的基调下面,通过老元素的新组合,创造出全新的视觉感受。相比符号,视觉风格更容易表现「惊喜到脱口而出!」这个idea,它可以通过形色质构全方位的表达。

当一个人「惊喜到脱口而出!」的时候,快乐的气场围绕在他周围,这些无形的从中心向四周放散的表现,看上去很像是圆形声波,同时它还能根据不同人的状态做动态变化,这就形成了一种设计语言,一种能用固定的形式做出千变万化的效果的语言。

当我们把它和波普艺术的主基调结合的时候,就形成了今年双十一独特的视觉语言,再通过形色质构的拆解,应用到各个场景。

△ 装置应用

△ 天猫双十一发布会现场应用

△ 天猫双十一开幕盛典现场应用

文章来源:优设

JS实现动态星空背景

seo达人



这里我截取的是一个图片,实际上是会动的。废话不多说,上代码。

HTML:



<canvas id="canvas"></canvas>

1

CSS:



/css reset /

body,p,div,ol,ul,li,dl,dt,dd,h1,h2,h3,h4,h5,h6,form,input,iframe,nav {

    margin: 0;

    padding: 0;

}

html,body {

    width: 100%;

    height: 100%;

}

body {

    font: 14px Microsoft YaHei;

    -webkit-text-size-adjust:100%;

    -moz-user-select: none;

    -webkit-user-select: none;

    user-select: none;

    position: relative;

    background: #000;

}


canvas {

    width: 100%;

    height: 100%;

    display: block;

    opacity: .8;

}





// 音量大小,0.01-1





//宇宙

var canvas = document.getElementById('canvas'),

ctx = canvas.getContext('2d'),

w = canvas.width = window.innerWidth,

h = canvas.height = window.innerHeight,



hue = 217,

stars = [],

count = 0,

maxStars = 1100;                //星星数量,默认1300

var canvas2 = document.createElement('canvas'),

ctx2 = canvas2.getContext('2d');

canvas2.width = 100;

canvas2.height = 100;

var half = canvas2.width / 2,

gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half);

gradient2.addColorStop(0.025, '#CCC');

gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');

gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');

gradient2.addColorStop(1, 'transparent');



ctx2.fillStyle = gradient2;

ctx2.beginPath();

ctx2.arc(half, half, half, 0, Math.PI 2);

ctx2.fill();



// End cache

function random(min, max) {

    if (arguments.length < 2) {

        max = min;

        min = 0;

    }



    if (min > max) {

        var hold = max;

        max = min;

        min = hold;

    }



    return Math.floor(Math.random()
(max - min + 1)) + min;

}



function maxOrbit(x, y) {

    var max = Math.max(x, y),

    diameter = Math.round(Math.sqrt(max max + max max));

    return diameter / 2;

    //星星移动范围,值越大范围越小,

}



var Star = function() {



    this.orbitRadius = random(maxOrbit(w, h));

    this.radius = random(60, this.orbitRadius) / 10;       //星星大小,值越大星星越小,默认8

    

    this.orbitX = w / 2;

    this.orbitY = h / 2;

    this.timePassed = random(0, maxStars);

    this.speed = random(this.orbitRadius) / 80000;        //星星移动速度,值越大越慢,默认5W

    

    this.alpha = random(2, 10) / 10;



    count++;

    stars[count] = this;

}



Star.prototype.draw = function() {

    var x = Math.sin(this.timePassed) this.orbitRadius + this.orbitX,

    y = Math.cos(this.timePassed)
this.orbitRadius + this.orbitY,

    twinkle = random(10);



    if (twinkle === 1 && this.alpha > 0) {

        this.alpha -= 0.05;

    } else if (twinkle === 2 && this.alpha < 1) {

        this.alpha += 0.05;

    }



    ctx.globalAlpha = this.alpha;

    ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);

    this.timePassed += this.speed;

}



for (var i = 0; i < maxStars; i++) {

    new Star();

}



function animation() {

    ctx.globalCompositeOperation = 'source-over';

    ctx.globalAlpha = 0.5;                                 //尾巴

    ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)';

    ctx.fillRect(0, 0, w, h)



    ctx.globalCompositeOperation = 'lighter';

    for (var i = 1,

    l = stars.length; i < l; i++) {

        stars[i].draw();

    };



    window.requestAnimationFrame(animation);

}



animation();

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

损失厌恶心理是如何影响我们的决策

涛涛

损失厌恶心理在设计中的应用以及是怎么影响我们的决策

前言:

前几天在一篇文章中看到“损失厌恶”这个心理学现象,就上网查阅了一些相关资料,以及它在设计中是如何运用,又是如何影响我们的决策,总结一点自己的观点。


一、损失厌恶


对于损失厌恶,先来做几个实验,来帮助我们更好的理解。

如果我给你一个苹果,你应该会感到高兴吧!现在换一下,我给你两个苹果,接着我向你拿回了一个。

请问,你更喜欢哪一个场景?我想多数人的答案是第一个,而不喜欢第二个场景。

这个实验两个场景的结果都是一样的,都得到了一个苹果,但是在第二个场景中,因为得而复失,损失了一个苹果,这严重影响并拉低了获得一个苹果的幸福感。


丹尼尔·卡尼曼(Daniel Kahneman)曾经设计了一个掷质硬币的实验,硬币是均质的。如果是正面,你将得到150美元;如果是背面,你将输掉100美元。这个赌局对于参与者来说,长期下注的话,肯定是稳赚不赔的,毕竟输赢概率相同,赢的收益大于输的损失。

但是实验结果却是,大多数人仍然拒绝了这个赌局,因为对于多数人来说,损失100美元的痛苦远远大于得到150美元的快乐。最少收益多少,快乐才能弥补普通人是失去100美元的痛苦呢?答案是,200美元。


由上述实验我们可以看出:


损失厌恶是指人们面对同样数量的收益和损失时,认为损失更加令他们难以忍受。同量的损失带来的负效用为同量收益的正效用的2.5倍。损失厌恶反映了人们的风险偏好并不是一致的,当涉及的是收益时,人们表现为风险厌恶;当涉及的是损失时,人们则表现为风险寻求。


二、坚持中庸最好


我们在进行网购的时候,比如看上一件很喜欢的衣服,追求高性价比的用户会通过图片在淘宝进行搜索,进行价格的对比,从而选择一款销量高、评价好、价格又合理的款式。

“损失厌恶心理”在其中发挥着它的作用,人们害怕价格太低,买到的商品没有自己预期的好,质量得不到保障,害怕价格太高,买到的商品不值这个价格。感觉自己会买亏,所以我们总是选择规避这样的风险,去选择一个中间价位的作为目标购买, “坚持中庸最好”。   



三、电商中的应用


每逢换季、过节时一些电商平台经常会搞一些促销活动,比如

  1. 2件8折,3件7折,预计到手XX元;

  2. 现价99,倒计时x小时恢复199;

  3. 线下店面到期最后一天全场5折的海报(每次路过的时候都是最后一天)

商家都是为了营造现在不买就没的“稀缺感”对你刺激消费,套路还是老套路,但是一直都很有用。如果我们真喜欢这件物品,即使凑单也要享受7折优惠去购买,因为你会感觉便宜很多,省下了不少钱;


还有一年一次的店庆,淘宝的双11,京东的618,也以用户的“损失厌恶”心理为基座。

用户从第一个角度想,能在这样的狂欢节中买到如此实惠的产品,一定要抓住机会,熬夜也要买买买!

用户从第二个角度想,一年一次,要是错过这个机会,如此实惠的产品可只有明年才有了,越累越多的人有这种心理,所以淘宝双十一的总额年年都在刷新记录。


再就是拼团功能的应用,单买价格可能对你来说不贵,但拼团会让你感觉更划算,能省则省,中国有14亿人,有那么3 4亿消费者是不追求高质量、高标准的,对于他们来说便宜就行,也正是因为这样一拨人,才促使了拼多多的在短短的3 4年就可以做到上市的原因之一。



在二手平台,有个估价的功能,当我们输入我们产品的各种信息后,会出现一个大概的市场价,下面会提示我们预计下周跌幅150元、一周后在降低200元等信息,这些细节设计的很到位,都是利用了人们的损失厌倦心理去促成交易。



四、股票市场中的应用


“损失厌恶”心理往往深刻影响这人们的投资决策。例如,你手中有两只股票,一只涨了100块,另一只跌了100块。现在你因急事需要用钱,必须卖掉一只,那么你会卖掉哪一只?调查显示,大多数人会选择卖掉上涨的股票。因为股票上涨是收益,赚了白不赚,一定要先落袋为安,却没有考虑它继续上涨的可能性。而股票下跌是损失,面临损失大多数人是不可接受的,总希望它能涨回来避免损失,如果卖掉那损失就永远不可挽回了。事实上正确的操作应该是卖掉跌的股票,及时止损,不然损失越来越大的概率要更高。


作者在支付宝里买了两支基金,在探索阶段,所以少买了一些在试水,第一支波动比较大,会有亏损,第二支,比较平稳基本就是定期的会有收益,即使没有,也几乎没有亏损的情况,而对我这种金融小白来说会卖掉亏损比较大的,用这些钱去买稳定一些的产品。



五、不要被蝇头小利蒙蔽


养孩子最贵的莫过于尿不湿和奶粉了当然除了学费,对于一个追求高性价比的人来说,孩子的尿不湿我会在闲鱼淘一些宝妈们转卖的全新产品,从下面这个对话来看,我们两个都会呈现出明显的“损失厌恶心理”,卖家不愿意放弃自己眼里的利益,认为自己可以减少损失,而我之前因为花了同样的钱买了同样数量的同样的品牌,所以也不想做出让步,最终也没完成交易。



六、间断造成的损失


一些app中的签到、金币购买皮肤等这些常见的功能就是利用了用户的损失厌恶心理来增加用户粘性,当用户连续签到多少天才可以赢得红包或礼品,中间只要一间断不仅领不到奖励还要重新开始签到,所以一些用户为了减少自己的损失,就会连续签到,还有QQ退出时的提示语也是利用了用户的这种心理,从而能很好的增加留存。



掌上生活app中的积分抽奖活动,1分、9分,一点点的花光都没抽中你想要的,内心的不服输,又抱着侥幸的心理再来一次,可能你把积分花光了也不一定能中奖;

像这样的情况,我们很容易被眼前的利益所蒙蔽,我们不愿意放弃对未来会有更大利益的收获,所以不断投入“沉没成本”,令损失加倍。



七、在产品中的植入


最常见的就是“购物车”功能,我们女生都爱买买买,也常把购物车当作收藏来使用,放进购物车,就感觉这件商品自己的,过两天在看,已经下架就会感觉自己像失去了一件宝贝似的

还有就是VIP体验功能,我们通过百度云盘上传或者下载文件的时候,会有一个免费体验300秒的极速下载的功能,先让你体验了最为VIP的待遇,体验过后,开始给你限速;


苏宁易购APP中非会员用户可以免费享受一个月SUPER VIP,并购买商品时返现2%到个人账户中,让用户感觉我买东西的同时还可以剩下2%,像是自己赚到的一样,体验期过后,你会感觉自己买东西亏了很多;


这些产品都是先让你免费试用付费的VIP,待你用习惯了,VIP也停了,大部分人都会乖乖付费,这也是损失厌恶的一种应用。



八、不敢轻易尝试


在生活中我们吃饭、逛街也是一样,尤其是吃饭,我们通常会选择口味、价格、服务、环境等都比较熟悉的地方吃饭,对一些不熟悉的饭馆,会比较谨慎,这也是损失厌恶心理在“作祟”担心陌生的餐馆饭菜不好吃还贵;


生活中还有很多常见的损失厌恶心理作祟的例子:比如吃自助餐,虽然过食伤胃的道理大家都懂,人们依然觉得已经花了这么多钱,就该敞开肚子吃才算有“赚到”;比如花30块买了张电影票,但看了20分钟后觉得无聊至极,但想着已经花了30块,不看完整场会很“亏”,选择继续呆在影院,即使电影带来的效益为负……有些时候,哪怕是很小的损失。


总结:


我们每个人都有损失厌恶心理,可以说是天性,也是本能,我们要尽可能去找到一些产生损失厌恶的边界,让自己坦然面对损失,规避“损失厌恶”。

点击遮罩层的背景关闭遮罩层

seo达人

开发工具与关键技术:Adobe Dreamweaver CC

作者:黄灿

撰写时间:2019.1.16



在模仿华为官方网页的练习当中我发现华为官网中有一个遮罩层是随便点击遮罩层的背景也能关闭掉遮罩层,但唯独点击内容区域不会关闭掉遮罩层。于是我开始模仿这个写案例,连内容也一模一样(因为这个练习就是要写出和华为关一样的效果或则比它更好的效果),一开始我是这样子写的(图1)



图1



class=Select_Region_bj 我给了一个灰色半透明的背景样式,后来在Javascript中写onclick事件无论这么写,点击内容区也是会关闭掉遮罩层。我百思不得其解到底怎么样写才能点击内容区不会关闭遮罩层,后来下课期间我看见我同学他写的带能点击内容区不会关闭遮罩层。我问他你是这么写的,他告诉我:“把他们分离就可以的了。”我思考了一会,脑补:分离?怎么分离?补着补着补着就补出了背景和内容区分离。分离写(图2)

图2



把背景层和内容区分开来写,不要在背景层中包裹内容,这样子点击内容区就不会关闭掉遮罩层了!

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

深入理解vue中的slot与slot-scope

seo达人

写在前面

vue中关于插槽的文档说明很短,语言又写的很凝练,再加上其和methods,data,computed等常用选项使用频率、使用先后上的差别,这就有可能造成初次接触插槽的开发者容易产生“算了吧,回头再学,反正已经可以写基础组件了”,于是就关闭了vue说明文档。

实际上,插槽的概念很简单,下面通过分三部分来讲。这个部分也是按照vue说明文档的顺序来写的。

进入三部分之前,先让还没接触过插槽的同学对什么是插槽有一个简单的概念:插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示、以及怎样显示由父组件来决定。 实际上,一个slot最核心的两个问题这里就点出来了,是显示不显示怎样显示

由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板插槽模板两大类。
非插槽模板指的是html模板,指的是‘div、span、ul、table’这些,非插槽模板的显示与隐藏以及怎样显示由插件自身控制;插槽模板是slot,它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置确由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块

单个插槽 | 默认插槽 | 匿名插槽

首先是单个插槽,单个插槽是vue的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。

单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。

下面通过一个例子来展示。

父组件:


  1. <template>
  2. <div class="father">
  3. <h3>这里是父组件</h3>
  4. <child>
  5. <div class="tmpl">
  6. <span>菜单1</span>
  7. <span>菜单2</span>
  8. <span>菜单3</span>
  9. <span>菜单4</span>
  10. <span>菜单5</span>
  11. <span>菜单6</span>
  12. </div>
  13. </child>
  14. </div>
  15. </template>

子组件:


  1. <template>
  2. <div class="child">
  3. <h3>这里是子组件</h3>
  4. <slot></slot>
  5. </div>
  6. </template>

在这个例子里,因为父组件在<child></child>里面写了html模板,那么子组件的匿名插槽这块模板就是下面这样。也就是说,子组件的匿名插槽被使用了,是被下面这块模板使用了。


  1. <div class="tmpl">
  2. <span>菜单1</span>
  3. <span>菜单2</span>
  4. <span>菜单3</span>
  5. <span>菜单4</span>
  6. <span>菜单5</span>
  7. <span>菜单6</span>
  8. </div>

最终的渲染结果如图所示:



  1. 注:所有demo都加了样式,以方便观察。其中,父组件以灰色背景填充,子组件都以浅蓝色填充。

具名插槽

匿名插槽没有name属性,所以是匿名插槽,那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次。出现在不同的位置。下面的例子,就是一个有两个具名插槽单个插槽的组件,这三个插槽被父组件用同一套css样式显示了出来,不同的是内容上略有区别。

父组件:


  1. <template>
  2. <div class="father">
  3. <h3>这里是父组件</h3>
  4. <child>
  5. <div class="tmpl" slot="up">
  6. <span>菜单1</span>
  7. <span>菜单2</span>
  8. <span>菜单3</span>
  9. <span>菜单4</span>
  10. <span>菜单5</span>
  11. <span>菜单6</span>
  12. </div>
  13. <div class="tmpl" slot="down">
  14. <span>菜单-1</span>
  15. <span>菜单-2</span>
  16. <span>菜单-3</span>
  17. <span>菜单-4</span>
  18. <span>菜单-5</span>
  19. <span>菜单-6</span>
  20. </div>
  21. <div class="tmpl">
  22. <span>菜单->1</span>
  23. <span>菜单->2</span>
  24. <span>菜单->3</span>
  25. <span>菜单->4</span>
  26. <span>菜单->5</span>
  27. <span>菜单->6</span>
  28. </div>
  29. </child>
  30. </div>
  31. </template>

子组件:


  1. <template>
  2. <div class="child">
  3. // 具名插槽
  4. <slot name="up"></slot>
  5. <h3>这里是子组件</h3>
  6. // 具名插槽
  7. <slot name="down"></slot>
  8. // 匿名插槽
  9. <slot></slot>
  10. </div>
  11. </template>

显示结果如图:


可以看到,父组件通过html模板上的slot属性关联具名插槽。没有slot属性的html模板默认关联匿名插槽。

作用域插槽 | 带数据的插槽

最后,就是我们的作用域插槽。这个稍微难理解一点。官方叫它作用域插槽,实际上,对比前面两种插槽,我们可以叫它带数据的插槽。什么意思呢,就是前面两种,都是在组件的template里面写


  1. 匿名插槽
  2. <slot></slot>
  3. 具名插槽
  4. <slot name="up"></slot>

但是作用域插槽要求,在slot上面绑定数据。也就是你得写成大概下面这个样子。


  1. <slot name="up" :data="data"></slot>
  2. export default {
  3. data: function(){
  4. return {
  5. data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
  6. }
  7. },
  8. }

我们前面说了,插槽最后显示不显示是看父组件有没有在child下面写模板,像下面那样。


  1. <child>
  2. html模板
  3. </child>

写了,插槽就总得在浏览器上显示点东西,东西就是html该有的模样,没写,插槽就是空壳子,啥都没有。
OK,我们说有html模板的情况,就是父组件会往子组件插模板的情况,那到底插一套什么样的样式呢,这由父组件的html+css共同决定,但是这套样式里面的内容呢?

正因为作用域插槽绑定了一套数据,父组件可以拿来用。于是,情况就变成了这样:样式父组件说了算,但内容可以显示子组件插槽绑定的。

我们再来对比,作用域插槽和单个插槽和具名插槽的区别,因为单个插槽和具名插槽不绑定数据,所以父组件是提供的模板要既包括样式由包括内容的,上面的例子中,你看到的文字,“菜单1”,“菜单2”都是父组件自己提供的内容;而作用域插槽,父组件只需要提供一套样式(在确实用作用域插槽绑定的数据的前提下)。

下面的例子,你就能看到,父组件提供了三种样式(分别是flex、ul、直接显示),都没有提供数据,数据使用的都是子组件插槽自己绑定的那个人名数组。

父组件:


  1. <template>
  2. <div class="father">
  3. <h3>这里是父组件</h3>
  4. <!--第一次使用:用flex展示数据-->
  5. <child>
  6. <template slot-scope="user">
  7. <div class="tmpl">
  8. <span v-for="item in user.data">{{item}}</span>
  9. </div>
  10. </template>
  11. </child>
  12. <!--第二次使用:用列表展示数据-->
  13. <child>
  14. <template slot-scope="user">
  15. <ul>
  16. <li v-for="item in user.data">{{item}}</li>
  17. </ul>
  18. </template>
  19. </child>
  20. <!--第三次使用:直接显示数据-->
  21. <child>
  22. <template slot-scope="user">
  23. {{user.data}}
  24. </template>
  25. </child>
  26. <!--第四次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
  27. <child>
  28. 我就是模板
  29. </child>
  30. </div>
  31. </template>

子组件:


  1. <template>
  2. <div class="child">
  3. <h3>这里是子组件</h3>
  4. // 作用域插槽
  5. <slot :data="data"></slot>
  6. </div>
  7. </template>
  8. export default {
  9. data: function(){
  10. return {
  11. data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
  12. }
  13. }
  14. }

结果如图所示:

github

以上三个demo就放在GitHub了,有需要的可以去取。使用非常方便,是基于vue-cli搭建工程。

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

开发过程中积累的CSS样式(持续更新)

seo达人

前言:平时写页面的时候有些样式使用完发现没过多久就忘记了,这篇文章主要是用来记录开发过程中容易忘记的CSS样式,与其总是去网上查,还不如一个一个记录下来,虽然说之前的都没有记录,但是知识的累积不论什么时候开始做都不会晚的。



首先 记录几个好用的插件网站:



layDate日期与时间组件: https://www.layui.com/laydate/

Vant移动端插件库: https://youzan.github.io/vant/#/zh-CN/intro

Element组件库: https://element.eleme.cn/#/zh-CN/component/installation

Vue.js框架: https://cn.vuejs.org/v2/guide/

Bootstrap框架: https://v2.bootcss.com/index.html

菜鸟教程官网: https://www.runoob.com/

w3school官网: https://www.w3school.com.cn/

下面是遇到的一些想累积的css样式:(内容会随时间累积的越来越多)



1、一个 div 中的内容实现上下滑动效果(而不是超出body的高以后上下滑动):overflow:auto;

简单的描述:body 中的一个 div 内,如果设置了固定的 height,而内容的总 height 超出了 div 的高,则超出的部分就会被覆盖,而想实现超出的部分变成滑动的效果而不被覆盖,则用 overflow:auto; 实现。



2、修改 前端框架封装好的css样式: border-radius: 20px!important;(注意使用英文的 ! 叹号)

简单的描述:在开发过程中经常使用一些前端框架(bootstrap,vue.js,laydate,Vant等等),在使用link导入css文件以后,发现有些css是在标签内使用内嵌的方式实现的,优先级最高,那么我们怎么修改呢?

比如:css文件中的边框弧度样式为10px:border-radius: 10px;

我们想改成20px,则在后面加上 !important 即可:border-radius: 20px!important;



这篇文章主要是以后回头复习或者忘记了的时候给我自己看的,但是如果恰好也帮助到了你,那是更加的有意义,在以后的开发过程中,该文章的内容一定会累积的越来越多

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

产品设计核心三要素

涛涛

先问一个问题:怎么样衡量一个设计好与不好?工作中实践越多次,越会发现华丽的设计稿并不是体现设计师专业能力的唯一标准。普通设计师和高级设计师区别在于,设计方案是否具备完整设计思路;设计对于业务有没有真正的价值体现;以及设计方案的推动落地的完整性到底有多少。设计越往后走,越考验产品思维,设计思维,以及设计推动能力。这是产品设计师需要关注的核心三要素。


设计师在工作中接到设计需求会不自觉的第一时间想着如何去进行视觉表达,视觉表达确实非常重要,也是公司对于设计师的核心价值的定位之一,但视觉表达只是其中设计专业本职工作中的一个环节。设计师还要应该能够站在产品、设计、技术等不同维度去思考设计方案的可行性。产品打磨-视觉呈现-落地执行,在这三个核心点里面设计师分别有不同的定位和价值所在。 


  一. 产品“双标”满足   

产品打磨包含产品规划,内容组成,界面布局,交互梳理等等…所有环节的工作是为了符合产品最终的目标。产品所有的能力会核心围绕两个点:1商业变现 2用户需求满足。这两个目标在产品执行的环节有时候会有一些冲突,在产品打磨阶段设计师通过怎样的方式,做到既满足产品商业目标又满足用户体验需求?可以按照以下几个步骤进行分析寻求切入点: 


Image title



这里用腾讯动漫付费模块举例说明: 项目背景是腾讯动漫产品要做付费体系升级设计,接到需求先有由产品源头一步步深入,逐步展开设计方案的规划。 


 01 产品目标确认  

通过对项目背景的解读和产品方案的深入了解,以及总结当前存在的一些问题,可以明确得到项目中产品核心目是什么。付费升级核心原因是付费转化低,用户付费意愿不够强烈。此次升级的核心目标是促进内容消费,提升付费率。 


Image title



 02 分析用户路径  

确认目标之后从哪个模块儿开始进行首要需要考虑的。对于现有现有功能的升级,建议核心从产品本身着手,可以根据用户行为分析,获取用户常规使用路径,找到用户使用场景下的核心目的,从而去挖掘用户在付费路径下的诉求点,根据诉求点找到付费升级的触点。这里我们罗列了用户阅读产品的路径。 

Image title



 03 观察用户核心需求是否被满足 

 用户在每个场景下都会有“痛点”和“痒点”。比如在阅读前,核心目是想快点看到漫画内容;阅读过程中,想要及时宣泄对漫画的故事情节的感受;阅读后,希望找到更多相关内容或者能够和内容有更多的互动。目前产品在这三个关键的路径节点都存在一些问题,阅读前对于付费缺乏正向引导,阅读过程中互相行为较少,阅读后没有更多延展内容可供消费等。 


Image title



 04 洞察设计切入点  

根据用户在阅读 “前 中 后” 关键路径的节点的不同情绪反馈,我们可以做出找到相应情感满足切入点,并且制定解决方案 


Image title



 05 制定设计方案  

将之前找到的设计情感切入点用交互和视觉的形式呈现出来,尽可能完整的表达清晰。下面展示是关于付费升级优化的完整视频DEMO。整个方案采用趣味情感化形式为核心设计思路,逐步去引导用户付费。让用户在趣味互动中完成产品的商业转化目标。 


https://v.youku.com/v_show/id_XNDM0NDg1MzY2MA==.html


 二. 设计呈现的“差异化”   

视觉呈现是设计师们都比较擅长的工作,但不同专业高度要求下方案最终呈现出的效果是完全不一样的。好的设计方案,需要在设计上做出明显的“差异化”,这里的差异化是指要区别于常规输出一般的水平。差异化的可以从多个点入手:


Image title



优质的设计美感

美感是作为设计师首先需要培养的技能之一,也是在后续职业生涯的一直需要用到的技能。设计师被神职化的很大一个原因就是因为设计师的美感比一般人要好,有懂得欣赏美、鉴别美、以及创造美的能力。单一从视觉层面,设计作品是合格品还是精品,最终取决于画面的精美程度。项目不分大小,再小的一个项目都可以做出精致品质,这也是体现设计师专业度的核心衡量之一。


Image title



完整设计思路:

设计方案的完整性也能够很好的设计师专业度的差异化,几张图的设计稿和一个有完整设计思路的设计方案在品质上自然是明显差别的。设计师不光需要将设计呈现出来,更需要有严谨的设计思路并且表达出来让受众到你的设计想法。设计前期分析、中期执行、后期落地以及迭代优化,能够让设计师有意识的锻炼和提升自己的设计思维,对于设计师能力提升有必然的帮助。 


Image title



独特创意:

设计差异化呈现上,创意是一个非常好的切入点。行业大趋势的前提下,现在同类产品越来越趋于同质化,受众使用产品的时候都会有一些常规认知,关于功能的、交互操作的、内容组成的等等,淘宝和京东、大众和美团、甚至QQ音乐和网易音乐在产品使用体验上都有高度重合的地方,这些已经在用户心智中形成习以为常的认知感受。如果能够在用户的常规认知里,用创意手法呈现出超出他们预期的内容使其惊喜,产品设计就会有明显差异化体现。 


Image title



善用情感化:

具备美感的设计能让作品看起来有高级感,但更为高级且有效的是能够引起用户情感共鸣的设计。设计是主观的,对于设计每个人都有自己的想法,也正是因为主观的设计感受,能让设计在情感化打造方面可以有很多的尝试方向。能够引起受众主观情感上的共鸣和认同的设计,会形成产品的核心记忆点之一。设计师对于情感化设计往往会有一些误区,认为图形可爱,色彩羡慕,动效流畅且能够形成一套视觉体系,就能够算情感设计。真正的情感设计是需要从用户角度出发,挖掘用户的认知领域和喜欢,从而去进行符合用户情感诉求的呈现。 


Image title


三. 方案推动的效能管理 

 

设计方案输出只是整个产品生产流程中的一个核心环节,产品上线后体验如何最终取决于落地实现的程度。在方案落地支持过程中,效率协调和实现能力是保证设计方案贯彻一致执行的关键因素:


 协作  

产品设计师工作协调分为内部协作和外部协作。内部协作即设计师之间的沟通协同,主要内容是如何保持设计语言一致性,除了制定设计规范,还可以建立公共控件库,线上调用。控件库能够使设计师协作无学习成本,设计师输出设计稿效率也能够大大提升,同时保一致性。


外部协作主要是和下游的技术同事直接的工作对接,设计方案的交接方式以及开发获取信息的效率很关键。在开发接收设计方案的时候,尽能力降低获取成本以及理解成本。比如设计稿的标注,在标注上设计师一般会花很长时间,开发也需要逐步查看,偶尔还会有标注遗漏的地方。我们团队会直接采用插件,设计稿及时同步,并且开发可以自己随时查看每个元素的标注信息,便捷。


这里推荐两款协调软件:一款是InVision可以在sketch里进行控件协同调用,所有想用的元素直接源文件调用,不需要再问同事要源文件!另一款是Zeplin技术同学可以直接查看元素属性以及间距等,设计师解放双手不再需要标注!


Image title



官网链接: 

https://login.invisionapp.com/auth/sign-in   

https://zeplin.io/


实现能力   

专业技术之间的壁垒,也会成为设计方案实现的阻力。同样的界面,设计人员用设计软件实现,技术人员用逻辑代码实现,实现的方式和成本存在很大的差异性,所以往往设计师认为很简单的需求在开发层面的确非常难实现。当然,不是所有需求都是无解的,设计师在技术实现层面还是可以做一些事情:


01 方案前置沟通

设计一个新的功能的时候,如果有非常规的设计方案,可以提前和技术人员沟通实现的难易程度,让技术人员有前期预判和预演的时间。并且,可以将设计做成简易DEMO方便技术人员快速理解,避免双方存在信息不对等的情况。


02 搭建开发控件库

开发控件库和设计规范一样,是最基础但应用最为频繁的模块儿。开发控件库可以将最基础的元素形成固有规范,所有开发实现都用同一套规范,以确保实现的高度一致性,同时也能够提升实现效率和设计还原。设计可以辅助开发一起制定开发控件库,确保控件库和设计规格的一致性。


03 寻求技术语言共通性

尽量将设计方案转化为技术能够理解和复用的形式进行对接。除了静态设计稿的标注,设计和技术实现最大的难点在于动态交互的实现上,对于动态设计,将设计方案转换为代码文件交付给技术实现,这样能确保功能的正常实现同时减少后期设计还原性的偏差。


以上初步总结的关于产品设计师在设计过程中从前期产品规划到中期设计执行再到后期开发落地应该注意的一些核心点:

第一条,设计方案既要满足产品目标又同时要兼顾用户体验;

第二条,优秀的设计师,会保持设计方案的“差异化”;

第三条,设计师职责除了确保设计方案完整性,更重要的是推动设计方案的完整落地。


在产品设计过程中,设计师需要关注还有很多关键点,这里也欢迎大家一起补充交流,正是这些关键点,将设计师的思维逐步打开,使其成为一个具有全链路思维的设计人才。 

文章来源:UI中国

日历

链接

个人资料

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

存档