<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          如何設計更懂用戶的搜索頁

          資深UI設計者

          搜索模塊的邏輯原理
          搜索模塊的功能及流程分析

          “搜索”是目前互聯網產品中最常見也是最有必要的功能模塊,搜索一方面幫助用戶快速觸達自己想要商品/服務/咨詢等,另一方面作為平臺的重要數據入口可以獲取比較有價值的用戶信息。

          目前大部分產品的搜索模塊后臺邏輯和前端設計大同小異,但是不同的品類的產品又存在一些差異,從產品邏輯上分析基本原理如下圖,

          用戶輸入一個關鍵詞,搜索系統根據用戶的輸入的信息,篩選出系統認為用戶感興趣的內容,同時按照系統認定的重要性進行排序展示。簡單而言,搜索可以分為三步。


          Step1:對用戶輸入信息的過濾

          用戶輸入的關鍵詞首先要經過邏輯層進行非法詞過濾,錯詞糾錯,特定跳轉幾步操作

          非法詞過濾顯而易見就是用戶輸入的敏感詞匯會根據后端的非法詞庫進行判斷屏蔽,網上一般有現成的詞庫可以直接導入系統,不滿足的后臺可以根據產品屬性及業務需求再進行維護擴充。錯詞糾錯輸入查詢關鍵詞,用戶可能會輸入成拼音、或者錯別字,邏輯中有一套糾錯詞處理,當系統對比有錯誤時,會進行糾錯處理,最終輸出糾錯后的結果進行輸出。特定跳轉是后端將特定詞匯設置為特殊跳轉,后端需要維護的映射庫。比如雙十一的時候,輸入雙十一可能會直接跳轉到活動會場,而不是具體的某個商品。 


          Step2:根據用戶輸入信息對內容進行分析解讀

          經過三種異常詞庫的過濾后,關鍵詞會進入常規搜索詞庫。搜索詞庫是有限的,但是用戶的輸入卻是沒有限制的,怎么將無限制的搜索轉化為有限的詞庫,并且匹配到對應的結果呢?這里需要一個關鍵的步驟即分詞,分詞是將一個比較長的關鍵字拆分成多個合理的比較短的關鍵字,經過分詞非標準的關鍵詞就被轉化為標準的詞庫,而這些詞就會對應一些搜索目標內容,但這些目標內容并不全展示給用戶,展示給用戶的也不一定完全跟用戶搜索的相關,這里就有兩個跟搜索相關的兩個關鍵指標即準確率和召回率,準確率是指所有展示的內容中與用戶搜索相關的內容的占比,召回率是指所有與用戶搜索相關的內容中被展示出來內容的占比。準確率和召回率是一對存在矛盾的指標,搜索后臺會有調和這兩個數據相關的目標函數,后臺搜索優化的目標就是提高準確率和召回率,讓后臺與用戶搜索相關的內容都能盡可能展示出來。


          Step3:對解讀后的結果進行排序

          搜索系統標準詞庫都有與之現關聯的具體內容,每個具體內容是否包含關鍵詞決定是否展示這些內容,同時根據關鍵詞的權重給展示的內容一個分數,最終根據每個內容的分數進行排序,不同平臺的關鍵詞權重不一樣,這屬于平臺運營的機密,權重的高低直接影響目標內容的排序,也直接影響平臺的銷售額和用戶體驗。


          在前端設計看來一個簡單的搜索框,但是后端卻需要多層邏輯的判斷和輸出,最終實現業務與體驗的最優化。以上只是作為設計人員的簡單總結,方便我們做設計的時候更好跟研發人員溝通。 


          從前端功能流程上分析搜索模塊可以拆分為啟動搜索-輸入內容-獲取結果

          啟動搜索

          目前大部分的搜索入口分為頂部搜索框/底部導航/局部圖標,產品的屬性決定搜索功能的重要級,從而影響搜索入口的樣式,另外需要明確搜索在當前頁面中的的優先級從而明確搜索的樣式,底部是app的一個最重要位置,將搜索功能放在底部導航一方面突出搜索功能的重要級別,但相對于放在首頁頂部又不至于影響首頁的流量分發。頁面局部設置搜索圖標,相對搜索功能的重要級會低一些。頂部搜索一般是吸頂懸停,用戶對搜索的依賴性很高,此類搜索入口的功能也最完整,對設計的要求也最高。 


          完整的搜索框從功能點上分包括,掃碼/語音/圖片/文本等幾種搜索能力,設計時需明確搜索框自帶的功能點有哪些,功能點的優先級和關聯性,總結發現一般電商類服務類產品會比社交信息類產品的搜索更為明顯且搜索的功能點更多一些。


          輸入內容

          在輸入內容這個階段,用戶可能進行的操作是是輸入(語音/文本/圖片等)功能,選擇聯想關鍵詞,清除/修改文本功能信息展示上一般有搜索歷史,搜索維度,推薦搜索,默認提示詞等,歸納起來基本為關聯搜索,引導搜索,細分搜索這三種,目的都是一方面為了滿足用戶高效搜索的需求,另一方面實現平臺營銷策略。設計要兼顧這兩點,在滿足業務的同時給用戶更好的搜索體驗。

          以上搜索返回流程中兩大主流平臺有一些差異的原因

          第一種:搜索結果頁—搜索啟動頁-搜索入口,可能的原因:

                      符合移動端的流程可逆的操作習慣

                      營銷需要,返回至搜索推薦頁,多一層頁面的曝光機會

                      便于用戶觸發再次搜索的行為

          第二種:搜索結果頁—搜索入口,可能的原因:

                      用戶用取消操作,表達的是取消搜索模塊,故返回入口,同時也能再次調起

                      縮短返回路徑,更加高效,注重高效的操作體驗 


          獲取結果

          平臺屬性不同搜索結果頁的目標內容會有區別,除了目標內容的輸出外,搜索結果頁會對應的展示篩選條件和推薦,此時需要做到的是篩選維度清晰,業務核心明確,平臺特點突出

          在這個階段用戶的目的是在目標信息/商品/服務中進行對比選擇,獲得自己最想要(從平臺角度則是推薦給用戶)的。在設計搜索結果頁的目標內容時,需要注意信息層級的展示,比如電商平臺最突出價格,而咨詢分享類產品可能要突出關注度熱度等。

          大部分平臺都有自己的rank邏輯,rank邏輯是根據商品的相關因素綜合起來形成的一種排序邏輯,比如電商產品中的轉化率/銷量/點擊率等,而且會根據產品的不同階段去優化升級,目的是可以輸出更符合用戶心理的排序,從而更精準高效的滿足用戶,提升產品體驗。


          搜索異常狀態

          搜索異常的狀態一般有三種,1.搜索結果為空;2.智能糾錯;3.網絡異常等,

          搜索結果為空時一般需要空態圖和文案說明和引導,緩解用戶需求沒有達成的心情。智能糾錯,是在用戶輸入內容上的一種提示或糾正,如果用戶輸入的內容有問題或不夠標準,在搜索結果中會能給最貼切的搜索結果。網絡異常,需要考慮的是提示是在哪個階段告知用戶,用戶在沒有網絡的情況下仍然可以調起搜索啟動頁,此時提示用戶網絡異常會比在搜索結果頁告知用戶的體驗要好。


          文章來源:站酷  作者:周沐Zhoumu 

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


          app界面賞析 ——— 北京藍藍設計 移動端UI設計資源分享(二十)

          前端達人

          移動互聯網的迅速崛起,讓移動網頁,移動客戶端越來越重要,客戶端的頁面設計也是一門很大的學問??萍佳杆侔l展的今手機屏幕的尺寸越來越放大化,但卻始終 很有限,因此,在APP的界面設計中,精簡是一貫的準則。這里所說的精簡并不是內容上盡可能的少量,而是要注重重點的表達。在視覺上也要遵循用戶的視覺邏 輯,用戶看著順眼了,才會真正的喜歡。


          接下來為大家分享精美的app UI設計案例:


          jhk-1617329495749.jpgjhk-1617329712960.jpgjhk-1617329746696.jpgjhk-1618475057961.pngjhk-1618475082684.pngjhk-1618475178817.jpg



          --手機appUI設計--

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



            更多精彩文章:

                 手機appUI界面設計賞析(一)

                 手機appUI界面設計賞析(二)

                 手機appUI界面設計賞析(三)

                 手機appUI界面設計賞析(四)

                 手機appUI界面設計賞析(五)

                 手機appUI界面設計賞析(六)

                 手機appUI界面設計賞析(七)

                 手機appUI界面設計賞析(八)

                 手機appUI界面設計賞析(九)

                  手機appUI界面設計賞析(十)

                 手機appUI界面設計賞析(十一)

                 手機appUI界面設計賞析(十二)

                  手機appUI界面設計賞析(十三)

                 手機appUI界面設計賞析(十四)

                 手機appUI界面設計賞析(十五)

                 手機appUI界面設計賞析(十六)

                 手機appUI界面設計賞析(十七)

                手機appUI界面設計賞析(十八)

                手機appUI界面設計賞析(十九)





          vue傳值方式總結 (十二種方法)

          前端達人

          一.父傳子傳遞

          (1)在父組件的子組件標簽上綁定一個屬性,掛載要傳輸的變量
          (2)在子組件中通過props來接受數據,props可以是數組也可以是對象,接受的數據可以直接使用 props: [“屬性 名”] props:{屬性名:數據類型}
          代碼示例:

          //父組件
          <template>
            <div>
              <i>父組件</i>
              <!--頁面使用-->
              <son :data='name'></son> 
            </div>
          </template>
          
          <script>
          import son from "./son.vue";//導入父組件
          export default {
            components: { son },//注冊組件
            name: "父組件",
            data() {
              return {
                name: "Frazier", //父組件定義變量
              };
            },
          };
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          //子組件
          <template>
            <div>{{data}}</div>
          </template>
          
          <script>
          export default {
          components: { },
            name: '子組件',
            props:["data"],
          };
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

          二.子傳父傳遞

          (1)在父組件的子組件標簽上自定義一個事件,然后調用需要的方法
          (2)在子組件的方法中通過 this.$emit(“事件”)來觸發在父組件中定義的事件,數據是以參數的形式進行傳遞的
          代碼示例:

          //父組件
          <template>
            <div>
              <i>父組件</i>
              <!--頁面使用-->
              <son @lcclick="lcclick"></son>//自定義一個事件
            </div>
          </template>
          
          <script>
          import son from "./son.vue"; //導入父組件
          export default {
            components: { son }, //注冊組件
            name: "父組件",
            data() {
              return {};
            },
            methods: {
              lcclick(){
                alert('子傳父')
              }
            },
          };
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          //子組件
          <template>
            <div>
              <button @click="lcalter">點我</button>
            </div>
          </template>
          
          <script>
          export default {
          components: { },
            name: '子組件',
            methods: {
              lcalter(){
                this.$emit('lcclick')//通過emit來觸發事件
              }
            },
          };
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18

          三.兄弟組件通信(bus總線)

          (1)在src中新建一個Bus.js的文件,然后導出一個空的vue實例
          (2)在傳輸數據的一方引入Bus.js 然后通過Bus.e m i t ( “ 事 件 名 ” , " 參 數 " ) 來 來 派 發 事 件 , 數 據 是 以 emit(“事件名”,"參數")來來派發事件,數據是以emit(,"")emit()的參 數形式來傳遞
          (3)在接受的數據的一方 引入 Bus.js 然后通過 Bus.$on(“事件名”,(data)=>{data是接受的數據})
          圖片示例:
          在這里插入圖片描述
          在這里插入圖片描述
          在這里插入圖片描述

          四.ref/refs(父子組件通信)

          (1)ref 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實例,
          (2)可以通過實例直接調用組件的方法或訪問數據。也算是子組件向父組件傳值的一種
          代碼示例:

          //父組件
          <template>
            <div>
              <button @click="sayHello">sayHello</button>
              <child ref="childForRef"></child>
            </div>
          </template>
          <script>
          import child from './child.vue'
            export default {
              components: { child },
              data () {
                return {
                  childForRef: null,
                }
              },
              mounted() {
                this.childForRef = this.$refs.childForRef;
                console.log(this.childForRef.name);
              },
              methods: {
                sayHello() {
                  this.childForRef.sayHello()
                }
              }
            }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          //子組件
          <template>
            <div>child 的內容</div>
          </template>
          <script>
          export default {
            data () {
              return {
                name: '我是 child',
              }
            },
            methods: {
              sayHello () {
                console.log('hello');
                alert('hello');
              }
            }
          }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19

          五.Vuex通信

          組件通過 dispatch 到 actions,actions 是異步操作,再 actions中通過 commit 到 mutations,mutations 再通過邏輯操作改變 state,從而同步到組件,更新其數據狀態
          代碼示例:

          //父組件
          template>
            <div id="app">
              <ChildA/>
              <ChildB/>
            </div>
          </template>
          <script>
            import ChildA from './ChildA' // 導入A組件
            import ChildB from './ChildB' // 導入B組件
            export default {
              components: {ChildA, ChildB} // 注冊組件
            }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          //子組件A
          <template>
           <div id="childA">
             <h1>我是A組件</h1>
             <button @click="transform">點我讓B組件接收到數據</button>
             <p>因為點了B,所以信息發生了變化:{{BMessage}}</p>
           </div>
          </template>
          <script>
           export default {
             data() {
               return {
                 AMessage: 'Hello,B組件,我是A組件'
               }
             },
             computed: {
               BMessage() {
                 // 這里存儲從store里獲取的B組件的數據
                 return this.$store.state.BMsg
               }
             },
             methods: {
               transform() {
                 // 觸發receiveAMsg,將A組件的數據存放到store里去
                 this.$store.commit('receiveAMsg', {
                   AMsg: this.AMessage
                 })
               }
             }
           }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          //子組件B
          <template>
           <div id="childB">
             <h1>我是B組件</h1>
             <button @click="transform">點我讓A組件接收到數據</button>
             <p>點了A,我的信息發生了變化:{{AMessage}}</p>
           </div>
          </template>
          
          <script>
           export default {
             data() {
               return {
                 BMessage: 'Hello,A組件,我是B組件'
               }
             },
             computed: {
               AMessage() {
                 // 這里存儲從store里獲取的A組件的數據
                 return this.$store.state.AMsg
               }
             },
             methods: {
               transform() {
                 // 觸發receiveBMsg,將B組件的數據存放到store里去
                 this.$store.commit('receiveBMsg', {
                   BMsg: this.BMessage
                 })
               }
             }
           }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          //vuex
          import Vue from 'vue'
           import Vuex from 'vuex'
           Vue.use(Vuex)
           const state = {
             AMsg: '',
             BMsg: ''
           }
          
           const mutations = {
             receiveAMsg(state, payload) {
               // 將A組件的數據存放于state
               state.AMsg = payload.AMsg
             },
             receiveBMsg(state, payload) {
               // 將B組件的數據存放于state
               state.BMsg = payload.BMsg
             }
           }
          
           export default new Vuex.Store({
             state,
             mutations
           }) 
          
          • 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

          六.$parent

          通過parent可以獲父組件實例 ,然 后通過這個實例就可以訪問父組件的屬 性和方法 ,它還有一個兄弟parent可以獲父組件實例,然后通過這個實例就可以訪問父組件的屬性和方法,它還有一個兄弟parent可以獲父組件實例,然后通過這個實例就可以訪問父組件的屬性和方法,它還有一個兄弟root,可以獲取根組件實例。
          代碼示例:

          // 獲父組件的數據
          this.$parent.foo
          
          // 寫入父組件的數據
          this.$parent.foo = 2
          
          // 訪問父組件的計算屬性
          this.$parent.bar
          
          // 調用父組件的方法
          this.$parent.baz()
          
          //在子組件傳給父組件例子中,可以使用this.$parent.getNum(100)傳值給父組件。 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13

          七.sessionStorage傳值

          sessionStorage 是瀏覽器的全局對象,存在它里面的數據會在頁面關閉時清除 。運用這個特性,我們可以在所有頁面共享一份數據。
          代碼示例:

          // 保存數據到 sessionStorage
          sessionStorage.setItem('key', 'value');
          
          // 從 sessionStorage 獲取數據
          let data = sessionStorage.getItem('key');
          
          // 從 sessionStorage 刪除保存的數據
          sessionStorage.removeItem('key');
          
          // 從 sessionStorage 刪除所有保存的數據
          sessionStorage.clear(); 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11

          注意:里面存的是鍵值對,只能是字符串類型,如果要存對象的話,需要使用 let objStr = JSON.stringify(obj) 轉成字符串然后再存儲(使用的時候 let obj = JSON.parse(objStr) 解析為對象)。
          推薦一個庫 good-storage ,它封裝了sessionStorage ,可以直接用它的API存對象

          //localStorage
           storage.set(key,val) 
           storage.get(key, def)
          //sessionStorage
           storage.session.set(key, val)
           storage.session.get(key, val) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6

          八.路由傳值

          使用問號傳值
          A頁面跳轉B頁面時使用 this.r o u t e r . p u s h ( ’ / B ? n a m e = d a n s e e k ’ ) B 頁 面 可 以 使 用 t h i s . router.push(’/B?name=danseek’) B頁面可以使用 this.router.push(/B?name=danseek)B使this.route.query.name 來獲取A頁面傳過來的值
          上面要注意router和route的區別
          使用冒號傳值
          配置如下路由:

          {
              path: '/b/:name',
              name: 'b',
              component: () => import( '../views/B.vue')
           }, 
          
          • 1
          • 2
          • 3
          • 4
          • 5

          在B頁面可以通過 this.$route.params.name 來獲取路由傳入的name的值

          使用父子組件傳值
          由于router-view本身也是一個組件,所以我們也可以使用父子組件傳值方式傳值,然后在對應的子頁面里加上props,因為type更新后沒有刷新路由,所以不能直接在子頁面的mounted鉤子里直接獲取最新type的值,而要使用watch

          <router-view :type="type"></router-view>
          
          // 子頁面
          props: ['type']
          watch: {
                 type(){
                     // console.log("在這個方法可以時刻獲取最新的數據:type=",this.type)
                 },
          }, 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9

          九.祖傳孫 $attrs

          正常情況下需要借助父親的props作為中間過渡,但是這樣在父親組件就會多了一些跟父組件業務無關的屬性,耦合度高,借助$attrs可以簡化些,而且祖跟孫都無需做修改
          祖組件:

          <template>
              <section>
                  <parent name="grandParent" sex="男" age="88" hobby="code" @sayKnow="sayKnow"></parent>
              </section>
          </template>
          
          <script>
              import Parent from './Parent'
              export default {
                  name: "GrandParent",
                  components: {
                    Parent
                  },
                  data() {
                      return {}
                  },
                  methods: {
                    sayKnow(val){
                      console.log(val)
                    }
                  },
                  mounted() {
                  }
              }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25

          父組件

          template>
            <section>
              <p>父組件收到</p>
              <p>祖父的名字:{{name}}</p>
              <children v-bind="$attrs" v-on="$listeners"></children>
            </section>
          </template>
          
          <script>
            import Children from './Children'
          
            export default {
              name: "Parent",
              components: {
                Children
              },
              // 父組件接收了name,所以name值是不會傳到子組件的
              props:['name'],
              data() {
                return {}
              },
              methods: {},
              mounted() {
              }
            }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26

          子組件

          <template>
            <section>
              <p>子組件收到</p>
              <p>祖父的名字:{{name}}</p>
              <p>祖父的性別:{{sex}}</p>
              <p>祖父的年齡:{{age}}</p>
              <p>祖父的愛好:{{hobby}}</p>
          
              <button @click="sayKnow">我知道啦</button>
            </section>
          </template>
          
          <script>
            export default {
              name: "Children",
              components: {},
              // 由于父組件已經接收了name屬性,所以name不會傳到子組件了
              props:['sex','age','hobby','name'],
              data() {
                return {}
              },
              methods: {
                sayKnow(){
                  this.$emit('sayKnow','我知道啦')
                }
              },
              mounted() {
              }
            }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31

          十.孫傳祖使用$listeners

          文字內容同第九個

          祖組件

          <template>
            <div id="app">
              <children-one @eventOne="eventOne"></children-one>
              {{ msg }}
            </div>
          </template>
          <script>
          import ChildrenOne from '../src/components/children.vue'
          export default {
            name: 'App',
            components: {
              ChildrenOne,
            },
            data() {
              return {
                msg: ''
              }
            },
            methods: {
              eventOne(value) {
                this.msg = value
              }
            }
          }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25

          父組件

          <template>
            <div>
              <children-two v-on="$listeners"></children-two>
            </div>
          </template>
          
          <script>
          import ChildrenTwo from './childrenTwo.vue'
          
          export default {
            name: 'childrenOne',
            components: {
              ChildrenTwo
            }
          }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16

          子組件

          <template>
            <div>
              <button @click="setMsg">點擊傳給祖父</button>
            </div>
          </template>
          
          <script>
          export default {
            name: 'children',
            methods: {
              setMsg() {
                this.$emit('eventOne', '123')
              }
            }
          }
          </script> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16

          十一.promise傳參

          promise 中 resolve 如何傳遞多個參數

          //類似與這樣使用,但實際上后面兩個參數無法獲取
          promise = new Promise((resolve,reject)=>{
              let a = 1
              let b = 2
              let c = 3
              resolve(a,b,c) 
          })
          promise.then((a,b,c)=>{
              console.log(a,b,c)
          }) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10

          resolve() 只能接受并處理一個參數,多余的參數會被忽略掉。
          如果想多個用數組,或者對象方式。。
          數組

          promise = new Promise((resolve,reject)=>{
              resolve([1,2,3]) 
          })
          promise.then((arr)=>{
              console.log(arr[0],arr[1],arr[2])
          }) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          對象

          promise = new Promise((resolve,reject)=>{
              resolve({a:1,b:2,c:3}) 
          })
          promise.then(obj=>{
              console.log(obj.a,obj.b,obj.c)
          }) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          十二.全局變量

          定義一個全局變量,在有值的組件直接賦值,在需要的組件內直接使用就可以了。


          轉自:csdn 作者:Frazier_梁超


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

          設計師必須學會的圖標技巧

          周周


          本文從圖標的起源、定義到基礎的設計方法總結無一不包,還有大量的案例幫你理解布爾運算,是新人設計師學習圖標設計的必備干貨!

          一、圖標的定義

          一說到圖標,我想您一定會覺得非常熟悉。圖標,也稱為 icon 或 picto,是指有明確含義的圖形視覺語言。那么當我們一提起圖標設計,您的腦中會想起哪個圖標來呢?有可能您想起的是微信APP ,由兩個白色氣泡組成的啟動圖標,或者是我們每天使用的 APP 中的那些返回、關閉等系統圖標,也可能是商場導視里的衛生間圖標等。沒錯,圖標的形式有很多種,它可以應用在很多場景中,并且表現方式非常豐富:有線的、有面的、也有擬物的等等。圖標的歷史可以追溯到象形文字(Pictogram),我們的祖先在發明文字之前就使用圖標記錄一天的生活了。聽著是不是不可思議呢?從亙古時代的象形文字開始,我們的祖先就偏愛使用這種抽象的圖形來表達意思了。在平面設計領域的商標其實也是一種圖標,平面設計里的視覺導視(例如衛生間的圖標)也有圖標的應用,所以圖標在我們的生活中應用非常廣泛。

          萬字干貨!設計師必須學會的圖標技巧

          △ 生活中隨處可見的圖標

          在計算機時代,從80年代的施樂公司界面中的單色圖標開始,圖標就開始出現在屏幕之中了,圖標較編程語言更容易被大眾理解。到了后來從 iMac 到 iPhone 引領的擬物圖標更是開啟了一個絢麗的圖標設計時代。擬物時代盛行也帶來了一些麻煩:擬物圖標的質感、光影會吸引走用戶的注意力,我們稱之為「視覺噪音」。于是 UI設計師開始探索更新的表現形式來設計界面中的圖標。扁平圖標發展史上有過很多次嘗試,比如微軟引領的 Metro風格中的圖標設計和 Google 引領的扁平設計風格中的長投影風格圖標,但由于它們表現形式太過于抽象、缺乏情感的傳遞,并沒有獲得用戶的垂青。而我們現在界面設計中的圖標設計是一種「輕擬物」或「微扁平」的風格:在面積比較小的區域我們使用扁平圖標或線形圖標;在面積比較大的區域我們會使用加入漸變甚至輕質感的圖標。(關于圖標風格的變化,可以參考這個網站:https://historyoficons.com)。

          萬字干貨!設計師必須學會的圖標技巧

          △ 不同的圖標設計風格

          如今我們界面中的圖標可謂非常豐富了,如果根據 Material Design 對圖標的分類,UI設計中的圖標可以分為帶有品牌屬性和特性的產品圖標、有功能指示作用的系統圖標兩種圖標,下面我們將針對于這兩種圖標進行研究。

          二、產品圖標

          萬字干貨!設計師必須學會的圖標技巧

          產品圖標是我們在設計界面的時候體現品牌調性和特性的圖標。通過產品圖標,用戶就可以大概感知這個產品主要是做什么的。比如微信的產品圖標是兩個對話氣泡,暗示了這是一款社交APP;再比如 ofo 的產品圖標是字母ofo 的組合,同時也是一輛自行車,這暗示了這款產品是共享單車的APP;再比如 KEEP 的字母「K」的圖標,像極了一個在抬腿做運動的人,暗示了這是一個運動APP。

          同時有些產品也依靠自身已經在用戶心中產生的品牌來直接設計產品圖標,比如淘寶APP 的產品圖標就是一個「淘」字;支付寶的產品圖標就是一個「支」字。優秀的產品圖標都會在我們心中打上一個烙印,當我們看到這些圖形、配色時,腦中會立即想起來它們的功能和特點。產品圖標除了在手機屏幕中作為啟動圖標,也會出現在閃屏、情感化設計、「關于我們」界面等場景中,所以也要有一定的靈活性,在設計上要以簡單、大膽、友好的方式傳達產品的核心理念和意圖。產品圖標很類似在企業識別系統(VI)里的 logo,需要讓用戶一眼看到它就能夠與腦中的產品相關聯。所以設計一個優秀的產品圖標對于任何產品來說都是非常重要的。

          1. 風格

          產品圖標有不同的風格,這些風格有可能很擬物,也有可能很扁平;有可能很抽象,也可能很具象。通過不同的設計風格可以更加標新立異,從而被用戶記住。讓用戶記住我們的圖標真是一件非常重要的事兒,要知道,每個手機都像是一把瑞士軍刀,它有無數個功能,而我們的產品只是萬種功能中的一個。用戶不可能記住手機里所有的 APP 都是什么,所以能在第一時間取得好感和記憶非常重要,產品圖標設計得好看并且容易被人記住就成了非常重要的任務。產品圖標的主要風格有以下幾種。

          文字風格

          文字是最直白的信息,而且不容易被曲解。所以很多國內的產品都會使用文字來作為自己的產品圖標。比如:支付寶、淘寶、今日頭條、OFO、愛奇藝、知乎、網易新聞、毛豆新車等。這么做也有它的問題,比如文字給人美的感受不如圖形,因為文字需要閱讀而不是觀察。并且移動端設備都會在啟動圖標之下加上一行輔助文字,如果圖標上的文字和下面的輔助文字完全重合,會顯得像介紹了自己兩遍一樣。如果您決意要使用文字作為產品圖標,且是中文的話,那么一定要記得文字最好為1-2個,并且不應該是產品的全稱。如果是英文的話,最好是首字母而不是產品全稱。當然不管是中文還是英文都需要選擇合適氣質的字體并做一定的變化。

          單讀:單讀是一個偏文藝的閱讀產品,所以產品圖標使用了黑白配色和兩個非常有文藝氣息的宋體繁體字,這樣的設計符合產品調性,傳遞給用戶一種產品的文藝氣息。

          今日頭條:今日頭條是一款優秀的新聞APP。它的圖標非常直白,一張報紙上有紅色的頭條標題,頭條使用了非常粗的黑體字,非常顯眼。

          淘寶:淘寶采用了一個俏皮的「淘」字作為 icon 的主要元素,并且背景顏色是令人興奮和刺激的橘黃色,凸顯了電商屬性。并且這個字使用了很久,用戶對此有一定的品牌認知。

          愛奇藝:愛奇藝的 icon 采用了英文字母iQIYI 和上下邊框相組合的形式。整體看來像是一個電視機,強調了品牌屬性和功能,并且使用了在視頻領域非常有識別性的綠色,讓人一看便知這是愛奇藝了。

          萬字干貨!設計師必須學會的圖標技巧

          △ 單讀、今日頭條、淘寶、愛奇藝的產品圖標

          如果您的品牌使用英文作為產品圖標,我們在設計的時候要格外注意英文字母之間的正負空間關系以及不同西文字體的不同氣質。

          ONE:雖然是中文產品,但是 ONE 的icon 顯得非常的高端和小眾。ONE 三個字母的正負空間關系做了微調,并且選擇了無襯線字體來體現時尚感。下面的小字是一個 slogan,并且和 ONE 的寬度一致。

          Pinterest:Pinterest 的產品圖標是一個手寫體的P,并且用紅色圓形作為陪襯。這樣一個字母作為 ICON 的好處就是方便用戶記憶。

          HULU:HULU 是一個國外視頻產品,它的產品圖標顏色很鮮艷,字母本身有韻律感,所以沒有做過多的設計。

          Facebook:作為一個社交產品,Facebook 的產品圖標同樣采用了一個字母代表較長的單詞。

          萬字干貨!設計師必須學會的圖標技巧

          △ ONE、Pinterest、HULU、Facebook的產品圖標

          正負形與隱喻風格

          圖標的設計可以使用正負形和隱喻,來讓圖標更加有耐人尋味的看點。

          抖音:抖音的產品圖標是一個音符,但是不知道大家是否發現,下面圓形的負空間也是一個音符,所以顯得非常巧妙。為了增加動感還加了紅和藍綠色的類似3D的動感效果。

          Keep:Keep 產品圖標是一個K,但是同時也是一個人抬著腿正在鍛煉。

          Skillshare:Skillshare 是一個技能交換平臺,第一眼看是兩個手像太極一樣交換著技能,同時也是該產品的首字母:S。

          萬字干貨!設計師必須學會的圖標技巧

          △ 抖音、Keep、Skillshare、OFO的產品圖標

          折紙風格

          折紙的效果會讓人感覺很立體,所以很多產品也選擇了折紙效果(比較扁平的手法)來設計產品圖標。

          Calendar:這個產品的產品圖標是一個正在翻頁的日歷,非常簡潔明了。

          Snapseed:除了扁平的設計之外,使用了長投影的設計風格。這個長投影也是扁平化的設計。

          Netflix:Netflix 的產品圖標是該產品的首字母N,這個 N 用了一些陰影來表示立體感。

          繪聲繪影:同樣是用了長投影和折紙效果,顯得非常清新。

          萬字干貨!設計師必須學會的圖標技巧

          △ Calendar、Snapseed、Netflix、繪聲繪影的產品圖標

          填充圖標風格

          產品圖標使用填充圖標風格是非常合適的。填充圖標風格具有簡潔和識別性強的特點。這種 ICON 的可擴展性更高,比如在一些特殊節日時可以用手繪、拼貼等形式來做輔助圖形。所以很多公司都鐘愛填充圖標風格。

          Lucking:這是一個線上咖啡外賣的產品。它的 APP圖標使用了一個鹿回頭的造型。這個鹿造型簡潔,非常有識別性。

          Tinder:這是一個國外社交APP,通過一個火的填充圖標讓人第一時間記住這個產品。

          youtube:這是國外著名視頻APP,它的產品圖標同樣使用了填充圖標風格,是一個有電視機隱喻的圓角矩形,并且中心是一個播放鍵,簡明扼要地說明了這個產品的功能。

          Twitter:國外著名社交APP,它的 icon 同樣使用了填充圖標風格,非常簡潔好記。

          萬字干貨!設計師必須學會的圖標技巧

          △ Lucking、Tinder、Youtube、Twitter的產品圖標

          線性風格

          由于目前設計流行趨勢,很多產品圖標都會采用扁平的設計風格。扁平除了填充的圖標之外,還有一種非常流行的形式——線性風格。線性風格一定要注意不要太細,因為手機和電腦設計環境顯示尺寸不同,如果我們做得太細,那么在手機上看會非常尖銳,顯得不太好點擊。

          Airbnb:Airbnb 的背景是一個微漸變,線性風格是一個曲線組成的 A,同時也是一個小蜜蜂。

          LOFTCam:為了凸顯文藝產品調性,使用了偏細的線條,同時使用了兩種主題色。

          NextDay:同樣非常文藝的產品,使用了比較抽象的手法。這個 ICON 是一個牛奶,突出了這個產品必須今天看,否則就如牛奶一樣會過期。

          VUE:這是一個攝影產品,同樣應用了黑色的微漸變,前面是非常前衛的45度長短不同的線。

          萬字干貨!設計師必須學會的圖標技巧

          △ Airbnb、LOFTCam、NextDay、VUE的產品圖標

          LOWPOLY風格

          我曾介紹過 LOWPOLY 這種設計風格,這種風格如果應用在產品圖標上同樣非常搶眼,因為用戶的手機上可能安裝了很多 APP,那么第一眼掃過去一定會注意到最亮眼的圖標。而 LOWPOLY 因為本身造型的獨特性非常吸引眼球。當然 LOWPOLY 也有它的問題,比如容易讓圖標失去細節等,所以很多產品圖標都是使用 LOWPOLY 作為圖形的背景。

          潮自拍:潮自拍使用了暖色鄰近色漸變的 LOWPOLY 作為背景,前景使用了一個很潮的S。

          潘通色:潘通色本身的最大特征就是色卡,所以使用了 LOWPOLY 的形式。

          美妝相機:通常 LOWPOLY 的形式是方塊,而美妝相機使用了三角作為基礎元素,很特別。

          人人:人人的產品圖標使用了不同的矩形斜度45°,增加了設計的速度感。

          萬字干貨!設計師必須學會的圖標技巧

          △ 潮自拍、潘通色、美妝相機、人人的產品圖標

          微漸變風格

          微漸變也是非常常見的表現手法。在擬物被扁平替代以后,我們會發現無法表達空間上的 Z軸。所以用輕微的漸變表現圖片的深度非常流行。我認為微漸變可能是眾多圖標設計風格中最有競爭力的一種。

          每日優鮮:每日優鮮在背景上用了很多炫彩的圓球,由于促銷時段在原有圖標上增加了一個雙十一的小標識,在手機中非常搶眼。

          陌陌:陌陌圖標如果設計成扁平你還會注意到它嗎?使用線性圖標會使得圖標厚度感不夠,而微漸變可以非常好地解決這個問題。

          全民K歌:使用了紫紅色的漸變來塑造一只鸚鵡,如果遇到其他使用場景可以使用扁平版本,這樣會讓產品圖標的使用更加靈活。

          Mindnode:這款腦圖軟件的產品圖標使用了三組鄰近色的漸變,同時使用了非常微妙的陰影。

          萬字干貨!設計師必須學會的圖標技巧

          △ 每日優鮮、陌陌、全民K歌、Mindnode的產品圖標

          卡通風格

          卡通風格的產品圖標會讓用戶更有好感,所以我們可以為產品設計一個可愛的卡通角色。好多決策者會認為卡通是一種低齡的審美,其實是錯誤的??ㄍ梢哉f是一種通吃的風格,比如騰訊就是以一個企鵝作為品牌形象開始拓展自己的版圖。而卡通本身有不同的風格,比如擬物類的卡通、扁平類的卡通等,也會給人不同的感受。所以如果我們的產品要使用卡通作為產品圖標,最好以目標用戶群的喜好作為標尺。

          開心消消樂:開心消消樂是一個休閑游戲,游戲類APP 的產品圖標通常是使用擬物風格,這樣可以最大地吸引玩家的注意力和興趣。

          映客:映客是直播APP,通常用戶年齡不是很大,所以使用了一個很可愛的貓頭鷹作為產品圖標。

          Waze:Waze 的產品圖標不僅可愛而且突出了 Waze 的地圖查找功能。

          BOO!:BOO! 是一個兒童社交產品,用戶比較低齡,所以更適合使用可愛的卡通作為圖標。

          萬字干貨!設計師必須學會的圖標技巧

          △ 開心消消樂、映客、Waze、BOO!的產品圖標

          2. 圖標的網格和參考線

          如果我們想設計一個小圖標,那么我們可以把畫布放大到400%來設計。同時可以使用網格和參考線來作為我們設計的輔助。網格在很多軟件里都有,比如在 Illustrator 中點擊視圖 > 網格,即可開啟網格了。參考線模板則需要下載第三方設計的模板,比如 Material Design 的參考線模板就有正方形、圓形、圓形和長方形結合等不同形式。如果對齊模板中的形狀,即可得到面積相等的長方形、正方形、圓形。這對我們構建視覺上面積相等的圖標很有益處。

          萬字干貨!設計師必須學會的圖標技巧

          △ 網格和參考線

          萬字干貨!設計師必須學會的圖標技巧

          △ 不同形狀的網格布局

          萬字干貨!設計師必須學會的圖標技巧

          △ 在網格的輔助下可以設計出大小均衡的圖標

          3. 尺寸

          蘋果啟動圖標尺寸

          蘋果需要很多尺寸的圖標用在不同的場景上,比如說在網頁端打開iTunes會使用512px的大圖標,而在手機、iPad桌面上的圖標大小也不同。除了尺寸不同,這些圖標的圓角也有不同的數值。為了簡化這部分的難度,蘋果為開發者提供了模板,有了模板就不用記那么多東西啦。蘋果官方HIG 下載的這套資源中,有 Template-AppIcons-iOS 這個文件,這個文件提供了 PS、Sketch、XD等不同格式。我比較推薦使用 PS 的格式。

          打開這個文件,用我們自己設計的啟動圖標替換掉任意智能對象里的內容。那么打開智能對象就是一個1024x1024px的矩形畫布,把我們的產品圖標放在這里,保存這個智能對象再關閉它就可以了。這時,你會發現所有尺寸的圖標都變成了我們的圖標。然后我們把背景隱藏,切出這些圖標即可。如果是 AI 完成的產品圖標可以直接 Ctrl+C 然后在 PS智能對象中 Ctrl+V復制過來就行。

          萬字干貨!設計師必須學會的圖標技巧

          △ Template-AppIcons-iOS

          安卓啟動圖標尺寸

          安卓啟動圖標同樣需要很多尺寸,主流是需要:1024x1024px、512x512px、144x144px、96x96px、72x72px、48x48px這六種。我們提供給程序員的是直角的矩形,然后程序員通過代碼進行切割變成圓角圖標。在這里我也做了一個智能對象的模板送給您,只要替換其中的智能對象圖像,換成您的1024x1024px圖標保存即可。

          萬字干貨!設計師必須學會的圖標技巧

          △ 安卓圖標模板

          4. 設計流程

          設計產品圖標前,首先我們需要找一些和產品氣質相符的圖片制作情緒板。通過情緒板我們可以感受到產品的調性,然后我們從中提取一些形狀和色彩作為我們產品圖標的主要造型。這里我舉我的產品每日名畫的例子,每日名畫是一個美術方面的APP,所以我找了一些和美術相關的圖片。

          萬字干貨!設計師必須學會的圖標技巧

          △ 關于美術的情緒板

          下面我開始在 AI 設計產品圖標了。我建立了一個1024x1024px的畫布,然后根據盧浮宮前的金字塔建筑設計了一枚抽象的產品圖標,它內在的符號是:帶領大家走進藝術的殿堂。同時我也增加了一些自己對美術的含義,如藝術來源于生活高于生活等。這些都寫在了設計說明中。

          萬字干貨!設計師必須學會的圖標技巧

          △ 在Illustrator中設計產品圖標

          然后我給這枚圖標加入了蒙德里安的配色,增加產品的藝術感,并最終完成產品圖標的設計。這個圖標也可以作為該產品的企業形象(VIS),將來產品周邊都可以使用這個圖形。

          萬字干貨!設計師必須學會的圖標技巧

          △ 最終定稿的圖標

          由于產品會首先上線到蘋果設備上,所以我下面把 AI 繪制的產品圖標全選復制,然后打開圖標模板中的智能對象(雙擊圖標模板中智能對象圖層的縮略圖),粘貼過來。粘貼的時候系統會提示選擇粘貼過來的方式,這里我們選擇:智能對象。然后保存并關閉智能對象,這時回到模板PSD 中,就看到了這個效果。

          萬字干貨!設計師必須學會的圖標技巧

          △ 替換了模板中智能對象的效果

          接下來隱藏背景圖層,然后按下鍵盤上的 ctrl+Shift+Alt+S,調出存儲為Web所用模式,選擇保存到桌面上,格式選擇僅圖片。關閉 PS,打開桌面上的文件夾,就看到圖標被我們工整地切好了。

          萬字干貨!設計師必須學會的圖標技巧

          △ 產品圖標的切圖文件

          三、系統圖標

          萬字干貨!設計師必須學會的圖標技巧

          第二種圖標被稱為系統圖標。系統圖標指的是擔負著一定功能和含義的圖形,一般來說需要像文字一般地被人迅速理解,所以表達方式上不適合特別復雜。比如微信底部四個系統圖標:「微信」、「通訊錄」、「發現」、「我」就使用了比較簡潔的線性風格。

          當然系統圖標也不一定要做的非常無趣,比如我們常用的58同城APP 中就有大量的系統圖標,在保證識別性的前提下使用了多彩的顏色和不同的造型,顯得非?;顫?。所以系統圖標同樣可以做得有趣和多樣,前提是保證圖標的可識別性。

          1. 風格

          萬字干貨!設計師必須學會的圖標技巧

          填充圖標(Filled icon)

          填充圖標是以面為主要表現形式的圖標。在微信APP 底部的 tab欄中,未選中的圖標是線性圖標,而選中態則是填充圖標,并且會變成較為鮮亮的顏色暗示用戶該功能被選中了。填充態圖標占用的面積要比線性圖標多,所以更加顯眼。實際上,在最新的蘋果設計規范中,蘋果也建議開發者在 APP底部 Tab欄中全部使用填充圖標,點擊態通過改變填充圖標的顏色進行區別。這是因為填充圖標看上去像可點擊的。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為填充圖標

          線性圖標(Outlined icon)

          線性圖標的表現形式是線條,在系統圖標里通常是由統一粗細的線條組成。這里可能很多新朋友不明白為什么要使用統一的粗細,這是因為通常系統圖標并非單一出現,而是成組使用。比如微信底部的四個 tab圖標、網易云音樂頂部導航欄的圖標等。在一個場景下的幾個同等重要的圖標,如果線條粗細不一致,很容易造成它們存在權重上差異的感覺。所以我們在繪制線性圖標時,線條通常都會使用統一的粗細。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為線性圖標

          圓角圖標(Rounded icon)

          無論是線性還是填充的圖標,在圖標的邊角處使用圓角都是圓角圖標風格。圓角圖標的好處就是讓人覺得很溫柔,可以非常舒適地點擊它。所以很多產品的圖標都會使用圓角圖標。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為圓角圖標

          尖角圖標(Sharp icon)

          無論是線性還是填充的圖標,在圖標的邊角處使用尖角都是尖角圖標風格。尖角圖標的好處是讓人感覺到有棱角,視覺上會多凝視幾秒。并且給人以正式的感覺,所以像銀行、辦公等APP 中都較多地使用尖角圖標風格。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為尖角圖標

          斷線圖標(Breaking Lines)

          如果我們的線性圖標顯得太死板,我們可以使用斷線這種方式來讓它變得俏皮。斷線圖標就是線性圖標的一種風格變化,它的特點就是在線條中出現斷口。但是這個斷口并不是看起來那么簡單,它得遵循幾個規則:第一,斷線開口只有一個,否則圖標會無法識別;第二,斷線開口位置不應該在中心線上;第三,斷線開口盡量在轉折處;第四,斷線不應該太過于瑣碎。

          萬字干貨!設計師必須學會的圖標技巧

          △ 土豆APP的標簽欄使用了斷線的風格

          雙調圖標(Two-Tone icon)

          如果我們把圖標簡單地分為線性圖標和填充圖標,是不是太無聊了?比如我們要設計一個 iOS平臺的 APP,它的底部Tab欄就一定是未選中態是線性的,選中就是填充的嗎(或者全部是填充態,僅僅改變顏色)?這也太無聊了吧!所以又出現了雙調圖標的設計風格。即:雙調圖標的外形還是線性圖標,但是用透明度很高的同類色填充到線性圖標內部空間里。這樣的圖標顯得俏皮可愛,并且感覺非常透氣。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為雙調圖標

          動態圖標(Motion)

          動態圖標是非常有趣的,如果靜態圖標不足以讓用戶感受到新鮮,那我們不妨給圖標增加動效。比如 QQ應用中底部 Tab欄的圖標點擊其中一個的時候,其他圖標會「偷看」選中態圖標的方向。除了底部標簽欄之外,很多 APP 點擊能觸發導航的「漢堡包圖標」,點擊時也會有一個從導航圖標變成返回圖標的動畫。這都是非常能夠調動用戶好奇心的。

          萬字干貨!設計師必須學會的圖標技巧

          △ Material Design中的動態圖標

           

          四、圖標的設計方法

          萬字干貨!設計師必須學會的圖標技巧

          1. 矢量圖形(Vetctor)

          我們在使用 Photoshop 工具的時候會感嘆,畫筆比鋼筆好用,橡皮比布爾運算好用。那么我們在畫圖標的時候能不能使用畫筆這樣的工具來繪制圖標呢?在 Photoshop 里使用畫筆工具和橡皮工具、涂抹工具、選區工具的填充、油漆桶工具制作的圖形,以及從網絡上復制過來的jpg圖片文件,這些都是像素圖形。它們是計算機記錄每一個點的顏色來呈現圖像的。這也是為什么我們把一張照片放得特別大它就虛了的原因。而我們通過 Photoshop 中的鋼筆工具、布爾運算、貝塞爾曲線、形狀圖層制作的圖形,以及 Illustrator 復制過來的圖形、Sktech繪制的圖形等,都是矢量圖形。它們是計算機記錄一個錨點到另一個錨點的方向、位置、色彩來呈現圖像的。所以像素圖形變化多端、顏色變換豐富、細節更多;矢量圖形則文件較小,并且具有隨意放大縮小都不虛的能力。因為每個錨點之間的方向、位置都是相對的,放大和縮小不受影響,而像素圖形記錄每個點的色彩,比如一張2000px x 2000px的圖片,縮小到1000px x 1000px就會損失一千個像素信息。我們繪制圖標比較適合用矢量圖形來設計,因為我們可能需要隨時調整圖標的大小,并且在不同分辨率的適配中也更加方便。

          2. 布爾運算(Boolean)

          布爾運算聽著很可怕,其實非常簡單,布爾運算是數字邏輯推演法,主要有數字邏輯的聯合、相交、相減。在我們使用的平面軟件中引用了這種邏輯運算方法來使基本圖形通過聯合、相交、相減等數學計算變成新的造型。比如兩個圓形相減可以得到一個月亮的造型,這就是布爾運算了。那么為什么叫布爾運算呢?布爾指的是喬治·布爾(George Boole),一位19世紀最重要的數學家,為了紀念布爾在符號邏輯運算中的杰出貢獻,所以我們將這種運算稱為布爾運算。布爾運算在 Photoshop、Illustrator、Sketch、Adobe XD、After Effects等我們熟悉的軟件中都有,并且操作基本一致。

          布爾運算的核心就是兩個形狀的關系:即Union(并集)、Intersection(交集)和Subtraction(差集,包括A-B和B-A兩種)。這些關系有點像我們初中學過的數學,應該比較好理解。但是很多軟件中對于布爾運算的關系翻譯不同,所以可能大家會有些不適應。比如在 Photoshop 中布爾運算被翻譯成:合并形狀、減去頂層形狀、與形狀區域相交、排除重疊形狀。而在 Adobe XD 中則翻譯成:添加、減去、交叉、排除重疊。雖然名字不同,但是功能是相同的,所以大家在學習新的軟件時不妨先找一下布爾運算。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為布爾運算不同運算模式

          3. 貝塞爾曲線(Bézier curve)

          貝塞爾曲線是用于二維圖形繪制的數學曲線。1962年法國工程師皮埃爾·貝塞爾發表了貝塞爾曲線,它的誕生主要是為了汽車的主體設計繪制圖形的。貝塞爾曲線是繪制矢量圖形時的重要工具,我們使用鋼筆工具畫出的所有圖形一般來說都是貝塞爾曲線組成的。貝塞爾曲線由錨點和線段組成,點擊錨點就會出現兩個手柄,一邊是控制前面的線條走向,另一邊是控制后端的線條走向。同時我們也可以通過增加錨點工具和刪除錨點工具進行調整。要想學好平面電腦繪圖軟件,貝塞爾曲線是必須修煉的一課(練習貝塞爾曲線的在線游戲:https://bezier.method.ac/)。一般來說,二維平面軟件都有貝塞爾曲線的痕跡,鋼筆工具、增加錨點、刪除錨點、轉換點工具,這些都是平面軟件的標配。并且,貝塞爾曲線和布爾運算可謂是一對好朋友,在繪制矢量圖形時可以使用它們輕松地繪制出準確的造型。

          萬字干貨!設計師必須學會的圖標技巧

          △ 圖為貝塞爾曲線繪制方法

          那么我們使用什么軟件來繪制圖標呢?這里我建議使用 Illustrator。首先,UI設計師使用不同的軟件來設計頁面,目前主流是 Photoshop和 Sketch,也有很多設計師選擇 Adobe XD。而這些軟件都是兼容 Illustrator 的,所以使用它來繪制圖標非常有靈活性??赡苣鷮?Illustrator 并不熟悉,不過沒關系,我們在這里只需要了解它與圖標繪制功能相關的功能即可,比如鋼筆、布爾運算、屬性面板、描邊、填充、混合工具等,并不需要學習非常深入。所以大家不必緊張。

          笑臉圖標

          笑臉圖標的設計步驟:畫出一個正圓;接著畫一個小圓,然后 ctrl+F復制平行移動到旁邊,然后右鍵編組。接著,同時選中大圓和編組的小圓進行水平居中對齊。我們繪制一個圓形,然后通過布爾運算減去一個矩形得到半圓形組成嘴,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 笑臉圖標

          對號圖標

          對號圖標的設計步驟:使用矩形工具畫出一個長方形,然后復制,將復制后的長方形向右上移動相同的距離,使用布爾運算剪切,旋轉45°后變成一個對號。繪制一個正方形,使用路徑選擇工具選中,拖動圓角的圓點拉出圓角得到圓角矩形。對號和圓角矩形進行布爾運算,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 對號圖標

          WIFI圖標

          WIFI圖標的設計步驟:繪制多個圓形并且通過布爾運算相加減得出三個圓圈嵌套的靶子造型。通過旋轉過的45°矩形和之前圖形布爾運算得到 Wifi圖標,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ WIFI圖標

          地理位置圖標

          地理位置圖標的設計步驟:選擇矩形工具單擊畫面輸入數值,建立一個100px的圓形。然后選擇這個圓形復制它,然后等比例縮小它,和之前的大圓進行布爾運算相減,得到環形。繪制50px的矩形,用對齊工具放在環形的左下方。旋轉45°得到地理圖標,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 地理位置圖標

          云彩圖標

          云彩圖標的設計步驟:繪制兩個大小不同的圓形,使用對齊工具進行底部對齊。繪制一個矩形,同樣底部對齊。合并形狀,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 云彩圖標

          眼睛圖標

          眼睛圖標的設計步驟:繪制出一個正圓。復制這個正圓形,然后按著 Shift+方向鍵下鍵,并通過布爾運算得到眼睛外輪廓。繪制兩個圓形,通過對齊工具和布爾運算工具得到最終眼睛造型,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 眼睛圖標

          鈴鐺圖標

          鈴鐺圖標的設計步驟:首先用圓形和矩形合并組成主體;使用矩形和圓形進行布爾運算繪制鈴鐺底部和鈴鐺頂部的零件,然后進行合并形狀;鈴鐺底部的半圓使用圓形和矩形布爾運算,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 鈴鐺圖標

          簡易齒輪圖標

          簡易齒輪圖標的設計步驟:通過兩個圓形進行布爾運算得到環形。繪制一個矩形,上下復制在圓形上,然后把它們倆編組和環形使用對齊工具進行水平垂直對齊。復制矩形編組并旋轉90°,得到一個十字形。復制這個十字形并最終全部合并形狀,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 簡易圖標

          齒輪圖標

          齒輪圖標的設計步驟:用 AI 的爆炸圖形和圓形進行布爾運算畫出齒輪;用兩個圓形進行布爾運算做出里面的零件,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 齒輪圖標

          螺絲刀圖標

          螺絲刀圖標的畫法:用圓形和矩形做出螺絲刀主體;用矩形旋轉并復制再布爾運算做出凹槽;使用矩形做出前面的造型,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 螺絲刀圖標

          蘋果圖標

          蘋果圖標的畫法:繪制一個六邊形。將水平中間兩個點向上移動。在中心線上下建立兩個錨點,并且向下移動。將下面兩個點向內分別移動。使用圓角工具將每兩個相同的點一組一組拉成圓角。繪制一個矩形并且旋轉45°,然后將左右兩個點向內拉得到菱形。用圓角工具使菱形變成葉子造型并且旋轉45°。使用一個圓形和蘋果造型相切,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 蘋果圖標設計過程

          放大鏡線性圖標

          放大鏡線性圖標的畫法:繪制正圓。繪制一條直線。用屬性面板里的對齊工具把它們倆對齊。用描邊面板里的屬性將描邊改成圓頭,然后旋轉45°即可。

          萬字干貨!設計師必須學會的圖標技巧

          △ 放大鏡線性圖標

          時鐘線性圖標

          時鐘線性圖標的畫法:繪制正圓。繪制一個矩形,對齊圓形中心。用增加錨點工具在矩形左和下邊上增加兩個錨點。用直接選擇工具框選沒用的線條,刪除即可。

          萬字干貨!設計師必須學會的圖標技巧

          △ 時鐘線性圖標

          點贊線性圖標

          點贊線性圖標的畫法:繪制兩個矩形,并用直接選擇工具選擇重合的四個錨點,在屬性面板里使用對齊工具讓它們完全對齊。將大的矩形底部錨點向左移動。繪制一個矩形并和大的矩形左對齊。用直接選擇工具選中直角,拖動圓角小圓點讓它們變成圓角,完成。

          萬字干貨!設計師必須學會的圖標技巧

          △ 點贊線性圖標

          4. 線性圖標的處理

          如果您掌握了以上填充態圖標的設計方法,相信其他圖標的設計只要以此及彼的思考,就可以完成。比如線性圖標,在繪制線性圖標時,我們首先會建立一個半透明的矩形來固定圖標應該繪制的范圍,比如「40px」。然后我們把填充關閉,只使用描邊來繪制線性圖標即可。繪制完以后我們無需保存文件,僅通過 Ctrl+C的復制快捷鍵,然后打開 Sketch 或者 Adobe XD 就可以使用 Ctrl+V 將圖標粘貼過去了。但是,如果您使用 Photoshop 做界面設計,可能會多兩道手續,首先就是線性圖標需要擴展才可以復制到 Photoshop 中。將圖標復制一份(擴展之后的圖標不方便修改,所以要留著可修改版本),然后點擊對象菜單 > 擴展,點確定,就可以把原本是沒有閉合的路徑改為完整的形狀。

          萬字干貨!設計師必須學會的圖標技巧

          △ 在Illustrator中的擴展

          然后復制,打開 Photoshop 粘貼會打開提示框,我們可以選擇把圖標粘貼成為像素、智能對象、路徑、形狀。如果粘貼成像素的話,那無疑對修改是非常不利的。如果粘貼成智能對象,雙擊智能對象會回到 Illustrator 中修改,但是也有一定缺點,那就是智能對象不能直接在 Photoshop 中進行調整。如果粘貼成路徑也不是很方便,所以最好是我們將 Illustrator 中繪制的小圖標粘貼成形狀。選擇后,圖標就粘貼成了形狀圖層,我們可以在 Photoshop 中對它進行布爾運算、錨點調整等操作了。

          萬字干貨!設計師必須學會的圖標技巧

          △ 粘貼到Photoshop中的選項

          然而,我們會發現圖標粘貼到 Photoshop 中,橫豎的路徑會出現虛邊的情況(圓角和斜線是允許一定的虛邊出現的,但是直線不可以)。這種虛邊有可能會影響用戶的體驗,我們必須把它消滅掉。第一種方法:在 Photoshop 中我們可以用直接選擇工具后界面上方的對齊路徑功能,給它打鉤來嘗試修復這個問題。第二種方法:我們可以使用直接選擇工具選中虛掉的某兩個錨點,然后按 Ctrl+T(自由變換),再按鍵盤的上下或左右「搖一搖」,路徑就會清晰了。第三種方法:也可以使用幾像素的矩形進行布爾運算強行對齊。三種方法一定能夠讓圖標的橫豎路徑沒有虛邊,達到完美的效果。當然 Sketch 和 Adobe XD 都是矢量工具所以復制后沒有這個問題。

          萬字干貨!設計師必須學會的圖標技巧

          在 Photoshop 中使用「搖一搖」的方法對齊路徑

          萬字干貨!設計師必須學會的圖標技巧

          在 Adobe XD 中,圖標無需進行擴展,并可以實時調整描邊粗細等屬性。

          5. 應用

          標簽欄圖標

          在蘋果和安卓APP 的底部,一般都會有一個放置重要功能的常駐欄,在 iOS中被稱為標簽欄(也叫做Tab欄)。一般,Tab欄的圖標是2-5個。每個圖標的區域平分整個 Tab欄寬度,底部會有一個22px(11pt)的文字注釋。當然如果圖標釋義較為清晰,也可以為了保持設計感去掉文字注釋。如果我們是以 iPhone6/7/8尺寸設計界面,那么我們的標簽欄圖標尺寸應該是60px(30pt)左右,可以基于這個范圍來設計我們的圖標。

          萬字干貨!設計師必須學會的圖標技巧

          △ 互聯網產品中優秀的標簽欄圖標設計

          每個 Tab欄的圖標都應該設計一個選中狀態,可以做樣式的變換也可以做顏色的改變,總之要讓人知道當前所在的頁面是哪個。如果您的 Tab欄由五個 icon 組成,那么可以在中間放置比較重要的功能,并做出突顯的樣式,比如使用一個圓球當作背景。還要額外注意,圖標的選中態樣式要和中間突出狀態的圖標保持區別,以免發生誤會。

          導航欄圖標

          在蘋果APP 的頂部區域,我們稱之為 Navigation Bar,就是導航欄。導航欄左右一般都會有圖標,如果是二級頁面,左側一般是返回圖標。安卓也有類似的設計。那么我們在設計這種圖標的時候一定要保證所有導航欄上的圖標大小和風格都是一致的。如果以 iPhone6/7/8尺寸設計界面,那么導航欄圖標的尺寸大概是44px(22pt)左右。

          萬字干貨!設計師必須學會的圖標技巧

          △ 互聯網產品中優秀的導航欄圖標

          金剛區圖標

          在我們逛淘寶和美團的時候您會發現,在它們頁面首頁都會有一個區域放置很多分類,一般是6-8個大小一樣的圖標,有可能是圓形,也可能是不規則形狀。這個區域其實在蘋果和安卓規范里并沒有,屬于設計師自創的規范。這個區域經常有八個圖標組成,被稱為「八大金剛圖標」,后來很多產品在這個區域并不使用8個圖標,我們就稱它們為金剛區了。金剛區圖標的設計風格應該盡量是微扁平、輕擬物的感覺,這樣會有更好的點擊感。尺寸方面,金剛區并沒有規范,所以大家可以以設計稿最終效果為準。

          萬字干貨!設計師必須學會的圖標技巧

          △ 互聯網產品中優秀的金剛區圖標設計

          設計方法:《用四個步驟,幫你學會金剛區圖標的設計方法》

          總結

          圖標設計是 UI設計中非常重要的一環,因為除了文字和圖片的排版之外,在扁平時代我們能夠傳遞給用戶情緒和設計感的通道就是頁面中的各種圖形和圖標了,如果做不好圖標,用戶就將在使用界面時失去樂趣。所以,我建議每位 UI設計師都需要在平時做大量的圖標練習。在不同的圖標風格中,學會使用各式各樣的武器。




          文章來源:優設網    作者:郗鑒


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



          “五一”機票酒店價格報復性上漲,我決定在家躺平……

          seo達人

           

          令人期待的“五一”假期將至,一場報復性出游蓄勢待發。與此同時,機票酒店價格也迎來了報復性上漲。

          6a600c338744ebf855dd05c39b8cb1226159a71f.jpeg

          資料圖:玉淵潭人頭攢動。中新網記者 李金磊 攝

          “五一”假期或迎2億人次出游

          今年“五一”放假5天,當前疫情防控形勢穩定,春節“就地過年”積壓的探親、出游需求有望進一步釋放,再加上“五一”本來就是傳統出行旺季,業內預計“五一”假期或迎來報復性出游,旅游人次有望突破2019年同期,達2億人次新高。

          火車票秒光、熱門航班經濟艙一票難求、熱門景區門票售罄、酒店民宿預訂火爆……種種跡象表明,“五一”出行需求強烈,一個史上最熱的“五一”假期在路上了。

          “五一”火車票緊俏。多條熱門線路火車票瞬間秒光,“12306崩了”一度登上熱搜,不少人感嘆“五一”搶票太難,堪比春運。

          熱門航班經濟艙售罄。去哪兒數據顯示,“五一”假期機票預訂量超過2019年同期三成水平。熱門航班經濟艙一票難求。以“五一”當天北京飛往三亞的航線為例,多數航班經濟艙已經售罄。

          熱門城市酒店民宿火爆。攜程數據顯示,“五一”期間酒店預訂量比2019年同期增長43%。途家大數據顯示,很多網紅民宿在“五一”期間已提前滿房;長沙、西安、廈門、武漢、桂林、青島多地民宿宣布庫存“告急”。

          熱門景區門票售罄。記者4月23日登陸故宮網站發現,“五一”假期前三天(5月1日至5月3日)的故宮門票已經售罄。

          4610b912c8fcc3ce2a42c59dd030b080d53f201f.jpeg

          “五一”假期前三天故宮門票已售罄。

          熱門城市機票酒店大幅漲價

          報復性出游蠢蠢欲動,在出游熱情高漲的同時,機票和酒店的價格也迎來報復性上漲。

          中國民航局運輸司副司長商可佳4月16日在新聞發布會上表示,從“五一”假期機票預訂情況看,可謂“量價齊升”,明顯高于今年清明假期,也有望高于2019年“五一”假期。

          攜程數據顯示,目前“五一”機票訂單量已經趕超2019年同期水平,增長23%?!拔逡弧睓C票經濟艙平均票價為1021元,超過2019年同期均價。上海、北京、三亞、廣州、成都、重慶、西安、廈門、杭州、深圳位列前十大出行目的地。

          從酒店來看,去哪兒數據顯示,截至目前,2021年“五一”假期國內酒店預訂量已經超過2019年同期四成以上,每晚均價為458元,比2019年時貴了85元;而與2020年五一假期相比,預訂量增長8.1倍。

          部分熱門目的地酒店價格漲幅較高。據報道,比如三亞的酒店平均價格較2019年同期上漲了80.5%,平均每間夜的價格高達1696元。

          “五一”假期機票和酒店價格上漲,也引發了網友的吐槽。

          “好久不出門,看了一眼‘五一’的機票和住宿怎么都這么貴,普普通通的酒店一晚都一千了?沒錢都不敢出去玩?!?/span>

          “‘五一’前一周開始計劃出游,我體會到了機票和酒店驚人的價格?!?/span>

          “后悔沒有早訂票!看完機票和酒店價格,我決定在家里躺5天了。”

          78310a55b319ebc487a0678ac053a9f41f171641.jpeg

          圖為三亞大東海旅游景區的沙灘吸引了許多游客前來游玩,享受陽光沙灘?!●樤骑w 攝

          跨省長線游熱度高

          “五一”5天長假進一步刺激了跨省長途旅游的熱情。請3天假休9天的方案為計劃長線旅游人群提供了可能。

          攜程數據顯示,“五一”假期超7成人群選擇跨省旅游,黃金周“遷徙式旅游”盛況或將重現。

          去哪兒大數據研究院院長蘭翔表示,雖然2020年“五一”假期也是五天,但當時出游仍以周邊游、短途游為主。今年國內疫情防控形勢總體保持良好,人們出游信心不斷恢復、出游需求也日益增加,清明假期就是一次短暫的試水。今年“五一”,更多的游客會選擇跨省長線游。

          西北和西南再度火熱,新疆酒店預訂增幅明顯。去哪兒數據顯示,與2019年同期相比,酒店預訂量增長超過7倍。今年“五一”假期酒店預訂增幅最高的十個目的地中,四個目的地來自新疆。

          “五一”假期,你去哪里玩?

          (來源:中國新聞社)

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

          刷新記錄!印度疫情單日新增46萬人,局勢或將全面失控!

          seo達人

           

          印度衛生部官方網站公布的最新數據顯示,截至 4月22日24時,印度單日新冠肺炎確診病例達461,477例。印度新冠肺炎累計確診數16,263,695累計死亡病例186,928例。

          據路透社報道,印度古吉拉特邦火葬場內的煤氣爐和柴火爐已經連續工作了很長一段時間,在新冠疫情期間還從來沒有停下過,設備上的金屬零件甚至都已經開始熔化。不僅如此,印度多個城市的火葬場都出現了遺體積壓的情況,連火化場地和使用的木柴都出現短缺。

          一直夢想趕超中國的印度,面臨這樣的崩潰局面,到底會如何反應?

          01為什么疫情爆發如此厲害?

          4月14日是印度教的慶典“大壺節”,是世界上參加人數最多的節日之一。2021年4月14日,共有1.5億印度人參加大壺節活動,約有65萬印度教徒在恒河內共浴。

          大壺節是印度最重要的節日,可以相當于我國的春節。不同的是,疫情影響下的春節,在黨和政府領導下,全國上下人民齊心協力共同抗擊疫情。

          而鄰國印度的大壺節仍轟轟烈烈舉行,官員甚至喊出口號:圣潔的恒河會沖走新冠病毒!這對于我國人民來說,簡直是不可想象!

          02印度面臨多重困境

          印度由于歷史問題累積,導致了公共衛生體系建設不完善、醫療條件落后、廣大人民受教育水平低。而這些問題在疫情中無疑是協同放大,將印度的疫情防控推向更糟糕的境地。

          在疫情之中我國的神器是:有效隔離、細心護理和中藥防治。而印度大概就是:恒河水、牛糞和牛尿。

          據報道,印度安得拉邦的村子里,數千人無視社交距離進行“潑糞大戰”以慶祝節日,當地村民們會互擲牛糞以祈求健康。

          印度人民受教育程度普遍較低也嚴重影響了疫情的控制?!都~約時報》指出,許多印度居民擔心疫苗存在副作用,甚至質疑疫苗是政府的陰謀。按目前的接種速度,印度需要大約十年的時間才可讓全國70%的人口接種疫苗。

          03印度局勢或將劇變

          在疫情影響下,印度經濟也遭遇重大打擊:國內通貨膨脹嚴重,難以利用宏觀調控繼續刺激經濟;其次,嚴重的疫情狀況也使得印度國內的外資紛紛撤出,這同時也導致了印度每天都有數萬人失業。

          更不用說印度對周邊國家不斷地挑釁和軍事沖突,危機時刻一觸即發。

          疫情的控制不力對印度來說,無疑是一場人道主義災難。也許,印度得先思考如何解決眼前的民生問題,才能準備“超越中國”。

          文章來源:騰訊網

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

           

          一口(很長的)氣了解 babel

          前端達人

          最近幾年,如果你是一名前端開發者,如果你沒有使用甚至聽說過 babel,可能會被當做穿越者吧?

          說到 babel,一連串名詞會蹦出來:

          • babel-cli
          • babel-core
          • babel-runtime
          • babel-node
          • babel-polyfill
          • ...

          這些都是 babel 嗎?他們分別是做什么的?有區別嗎?

          babel 到底做了什么?怎么做的?

          簡單來說把 JavaScript 中 es2015/2016/2017/2046 的新語法轉化為 es5,讓低端運行環境(如瀏覽器和 node )能夠認識并執行。本文以 babel 6.x 為基準進行討論。最近 babel 出了 7.x,放在最后聊。

          嚴格來說,babel 也可以轉化為更低的規范。但以目前情況來說,es5 規范已經足以覆蓋絕大部分瀏覽器,因此常規來說轉到 es5 是一個安全且流行的做法。

          如果你對 es5/es2015 等等也不了解的話,那你可能真的需要先補補課了。

          使用方法

          總共存在三種方式:

          1. 使用單體文件 (standalone script)
          2. 命令行 (cli)
          3. 構建工具的插件 (webpack 的 babel-loader, rollup 的 rollup-plugin-babel)。

          其中后面兩種比較常見。第二種多見于 package.json 中的 scripts 段落中的某條命令;第三種就直接集成到構建工具中。

          這三種方式只有入口不同而已,調用的 babel 內核,處理方式都是一樣的,所以我們先不糾結入口的問題。

          運行方式和插件

          babel 總共分為三個階段:解析,轉換,生成。

          babel 本身不具有任何轉化功能,它把轉化的功能都分解到一個個 plugin 里面。因此當我們不配置任何插件時,經過 babel 的代碼和輸入是相同的。

          插件總共分為兩種:

          • 當我們添加 語法插件 之后,在解析這一步就使得 babel 能夠解析更多的語法。(順帶一提,babel 內部使用的解析類庫叫做 babylon,并非 babel 自行開發)

          舉個簡單的例子,當我們定義或者調用方法時,最后一個參數之后是不允許增加逗號的,如 callFoo(param1, param2,) 就是非法的。如果源碼是這種寫法,經過 babel 之后就會提示語法錯誤。

          但最近的 JS 提案中已經允許了這種新的寫法(讓代碼 diff 更加清晰)。為了避免 babel 報錯,就需要增加語法插件 babel-plugin-syntax-trailing-function-commas

          • 當我們添加 轉譯插件 之后,在轉換這一步把源碼轉換并輸出。這也是我們使用 babel 最本質的需求。

          比起語法插件,轉譯插件其實更好理解,比如箭頭函數 (a) => a 就會轉化為 function (a) {return a}。完成這個工作的插件叫做 babel-plugin-transform-es2015-arrow-functions

          同一類語法可能同時存在語法插件版本和轉譯插件版本。如果我們使用了轉譯插件,就不用再使用語法插件了。

          配置文件

          既然插件是 babel 的根本,那如何使用呢?總共分為 2 個步驟:

          1. 將插件的名字增加到配置文件中 (根目錄下創建 .babelrc 或者 package.json 的 babel 里面,格式相同)
          2. 使用 npm install babel-plugin-xxx 進行安裝

          具體書寫格式就不詳述了。

          preset

          比如 es2015 是一套規范,包含大概十幾二十個轉譯插件。如果每次要開發者一個個添加并安裝,配置文件很長不說,npm install 的時間也會很長,更不談我們可能還要同時使用其他規范呢。

          為了解決這個問題,babel 還提供了一組插件的集合。因為常用,所以不必重復定義 & 安裝。(單點和套餐的差別,套餐省下了巨多的時間和配置的精力)

          preset 分為以下幾種:

          • 官方內容,目前包括 env, react, flow, minify 等。這里最重要的是 env,后面會詳細介紹。
          • stage-x,這里面包含的都是當年最新規范的草案,每年更新。
            這里面還細分為
            • Stage 0 - 稻草人: 只是一個想法,經過 TC39 成員提出即可。
            • Stage 1 - 提案: 初步嘗試。
            • Stage 2 - 初稿: 完成初步規范。
            • Stage 3 - 候選: 完成規范和瀏覽器初步實現。
            • Stage 4 - 完成: 將被添加到下一年度發布。

          例如 syntax-dynamic-import 就是 stage-2 的內容,transform-object-rest-spread 就是 stage-3 的內容。
          此外,低一級的 stage 會包含所有高級 stage 的內容,例如 stage-1 會包含 stage-2, stage-3 的所有內容。
          stage-4 在下一年更新會直接放到 env 中,所以沒有單獨的 stage-4 可供使用。

          • es201x, latest
            這些是已經納入到標準規范的語法。例如 es2015 包含 arrow-functions,es2017 包含 syntax-trailing-function-commas。但因為 env 的出現,使得 es2016 和 es2017 都已經廢棄。所以我們經??梢钥吹?es2015 被單獨列出來,但極少看到其他兩個。
            latest 是 env 的雛形,它是一個每年更新的 preset,目的是包含所有 es201x。但也是因為更加靈活的 env 的出現,已經廢棄。

          執行順序

          很簡單的幾條原則:

          • Plugin 會運行在 Preset 之前。
          • Plugin 會從前到后順序執行。
          • Preset 的順序則 剛好相反(從后向前)。

          preset 的逆向順序主要是為了保證向后兼容,因為大多數用戶的編寫順序是 ['es2015', 'stage-0']。這樣必須先執行 stage-0 才能確保 babel 不報錯。因此我們編排 preset 的時候,也要注意順序,其實只要按照規范的時間順序列出即可。

          插件和 preset 的配置項

          簡略情況下,插件和 preset 只要列出字符串格式的名字即可。但如果某個 preset 或者插件需要一些配置項(或者說參數),就需要把自己先變成數組。第一個元素依然是字符串,表示自己的名字;第二個元素是一個對象,即配置對象。

          最需要配置的當屬 env,如下:

          "presets": [ // 帶了配置項,自己變成數組  [ // 第一個元素依然是名字  "env", // 第二個元素是對象,列出配置項  { "module": false } ], // 不帶配置項,直接列出名字  "stage-2" ] 

          env (重點)

          因為 env 最為常用也最重要,所以我們有必要重點關注。

          env 的核心目的是通過配置得知目標環境的特點,然后只做必要的轉換。例如目標瀏覽器支持 es2015,那么 es2015 這個 preset 其實是不需要的,于是代碼就可以小一點(一般轉化后的代碼總是更長),構建時間也可以縮短一些。

          如果不寫任何配置項,env 等價于 latest,也等價于 es2015 + es2016 + es2017 三個相加(不包含 stage-x 中的插件)。env 包含的插件列表維護在這里

          下面列出幾種比較常用的配置方法:

          { "presets": [ ["env", { "targets": { "browsers": ["last 2 versions", "safari >= 7"] } }] ] }

          如上配置將考慮所有瀏覽器的最新2個版本(safari大于等于7.0的版本)的特性,將必要的代碼進行轉換。而這些版本已有的功能就不進行轉化了。這里的語法可以參考 browserslist

          { "presets": [ ["env", { "targets": { "node": "6.10" } }] ] }

          如上配置將目標設置為 nodejs,并且支持 6.10 及以上的版本。也可以使用 node: 'current' 來支持最新穩定版本。例如箭頭函數在 nodejs 6 及以上將不被轉化,但如果是 nodejs 0.12 就會被轉化了。

          另外一個有用的配置項是 modules。它的取值可以是 amdumdsystemjscommonjs 和 false。這可以讓 babel 以特定的模塊化格式來輸出代碼。如果選擇 false 就不進行模塊化處理。

          其他配套工具

          以上討論了 babel 的核心處理機制和配置方法等,不論任何入口調用 babel 都走這一套。但文章開頭提的那一堆 babel-* 還是讓人一頭霧水。實際上這些 babel-* 大多是不同的入口(方式)來使用 babel,下面來簡單介紹一下。

          babel-cli

          顧名思義,cli 就是命令行工具。安裝了 babel-cli 就能夠在命令行中使用 babel 命令來編譯文件。

          在開發 npm package 時經常會使用如下模式:

          • 把 babel-cli 安裝為 devDependencies
          • 在 package.json 中添加 scripts (比如 prepublish),使用 babel 命令編譯文件
          • npm publish

          這樣既可以使用較新規范的 JS 語法編寫源碼,同時又能支持舊版環境。因為項目可能不太大,用不到構建工具 (webpack 或者 rollup),于是在發布之前用 babel-cli 進行處理。

          babel-node

          babel-node 是 babel-cli 的一部分,它不需要單獨安裝。

          它的作用是在 node 環境中,直接運行 es2015 的代碼,而不需要額外進行轉碼。例如我們有一個 js 文件以 es2015 的語法進行編寫(如使用了箭頭函數)。我們可以直接使用 babel-node es2015.js 進行執行,而不用再進行轉碼了。

          可以說:babel-node = babel-polyfill + babel-register。那這兩位又是誰呢?

          babel-register

          babel-register 模塊改寫 require 命令,為它加上一個鉤子。此后,每當使用 require 加載 .js、.jsx.es 和 .es6 后綴名的文件,就會先用 babel 進行轉碼。

          使用時,必須首先加載 require('babel-register')。

          需要注意的是,babel-register 只會對 require 命令加載的文件轉碼,而 不會對當前文件轉碼。

          另外,由于它是實時轉碼,所以 只適合在開發環境使用。

          babel-polyfill

          babel 默認只轉換 js 語法,而不轉換新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局對象,以及一些定義在全局對象上的方法(比如 Object.assign)都不會轉碼。

          舉例來說,es2015 在 Array 對象上新增了 Array.from 方法。babel 就不會轉碼這個方法。如果想讓這個方法運行,必須使用 babel-polyfill。(內部集成了 core-js 和 regenerator)

          使用時,在所有代碼運行之前增加 require('babel-polyfill')?;蛘吒R幍牟僮魇窃?nbsp;webpack.config.js 中將 babel-polyfill 作為第一個 entry。因此必須把 babel-polyfill 作為 dependencies 而不是 devDependencies

          babel-polyfill 主要有兩個缺點:

          1. 使用 babel-polyfill 會導致打出來的包非常大,因為 babel-polyfill 是一個整體,把所有方法都加到原型鏈上。比如我們只使用了 Array.from,但它把 Object.defineProperty 也給加上了,這就是一種浪費了。這個問題可以通過單獨使用 core-js 的某個類庫來解決,core-js 都是分開的。
          2. babel-polyfill 會污染全局變量,給很多類的原型鏈上都作了修改,如果我們開發的也是一個類庫供其他開發者使用,這種情況就會變得非常不可控。

          因此在實際使用中,如果我們無法忍受這兩個缺點(尤其是第二個),通常我們會傾向于使用 babel-plugin-transform-runtime。

          但如果代碼中包含高版本 js 中類型的實例方法 (例如 [1,2,3].includes(1)),這還是要使用 polyfill。

          babel-runtime 和 babel-plugin-transform-runtime (重點)

          我們時常在項目中看到 .babelrc 中使用 babel-plugin-transform-runtime,而 package.json 中的 dependencies (注意不是 devDependencies) 又包含了 babel-runtime,那這兩個是不是成套使用的呢?他們又起什么作用呢?

          先說 babel-plugin-transform-runtime

          babel 會轉換 js 語法,之前已經提過了。以 async/await 舉例,如果不使用這個 plugin (即默認情況),轉換后的代碼大概是:

          // babel 添加一個方法,把 async 轉化為 generator function _asyncToGenerator(fn) { return function () {....}} // 很長很長一段  // 具體使用處 var _ref = _asyncToGenerator(function* (arg1, arg2) { yield (0, something)(arg1, arg2); }); 

          不用過于糾結具體的語法,只需看到,這個 _asyncToGenerator 在當前文件被定義,然后被使用了,以替換源代碼的 await。但每個被轉化的文件都會插入一段 _asyncToGenerator 這就導致重復和浪費了。

          在使用了 babel-plugin-transform-runtime 了之后,轉化后的代碼會變成

          // 從直接定義改為引用,這樣就不會重復定義了。 var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); // 具體使用處是一樣的 var _ref = _asyncToGenerator3(function* (arg1, arg2) { yield (0, something)(arg1, arg2); }); 

          從定義方法改成引用,那重復定義就變成了重復引用,就不存在代碼重復的問題了。

          但在這里,我們也發現 babel-runtime 出場了,它就是這些方法的集合處,也因此,在使用 babel-plugin-transform-runtime 的時候必須把 babel-runtime 當做依賴。

          再說 babel-runtime,它內部集成了

          1. core-js: 轉換一些內置類 (PromiseSymbols等等) 和靜態方法 (Array.from 等)。絕大部分轉換是這里做的。自動引入。
          2. regenerator: 作為 core-js 的拾遺補漏,主要是 generator/yield 和 async/await 兩組的支持。當代碼中有使用 generators/async 時自動引入。
          3. helpers, 如上面的 asyncToGenerator 就是其中之一,其他還有如 jsxclassCallCheck 等等,可以查看 babel-helpers。在代碼中有內置的 helpers 使用時(如上面的第一段代碼)移除定義,并插入引用(于是就變成了第二段代碼)。

          babel-plugin-transform-runtime 不支持 實例方法 (例如 [1,2,3].includes(1))

          此外補充一點,把 helpers 抽離并統一起來,避免重復代碼的工作還有一個 plugin 也能做,叫做 babel-plugin-external-helpers。但因為我們使用的 transform-runtime 已經包含了這個功能,因此不必重復使用。而且 babel 的作者們也已經開始討論這兩個插件過于類似,正在討論在 babel 7 中把 external-helpers 刪除,討論在 issue#5699 中。

          babel-loader

          前面提過 babel 的三種使用方法,并且已經介紹過了 babel-cli。但一些大型的項目都會有構建工具 (如 webpack 或 rollup) 來進行代碼構建和壓縮 (uglify)。理論上來說,我們也可以對壓縮后的代碼進行 babel 處理,但那會非常慢。因此如果在 uglify 之前就加入 babel 處理,豈不完美?

          所以就有了 babel 插入到構建工具內部這樣的需求。以(我還算熟悉的) webpack 為例,webpack 有 loader 的概念,因此就出現了 babel-loader。

          和 babel-cli 一樣,babel-loader 也會讀取 .babelrc 或者 package.json 中的 babel 段作為自己的配置,之后的內核處理也是相同。唯一比 babel-cli 復雜的是,它需要和 webpack 交互,因此需要在 webpack 這邊進行配置。比較常見的如下:

          module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel-loader' } ] } 

          如果想在這里傳入 babel 的配置項,也可以把改成:

          // loader: 'babel-loader' 改成如下: use: { loader: 'babel-loader', options: { // 配置項在這里  } } 

          這里的配置項優先級是最高的。但我認為放到單獨的配置文件中更加清晰合理,可讀性強一些。

          小結一下

          Babel 7.x

          最近 babel 發布了 7.0。因為上面部分都是針對 6.x 編寫的,所以我們關注一下 7.0 帶來的變化(核心機制方面沒有變化,插件,preset,解析轉譯生成這些都沒有變化)

          我只挑選一些和開發者關系比較大的列在這里,省略的多數是針對某一個 plugin 的改動。完整的列表可以參考官網

          preset 的變更:淘汰 es201x,刪除 stage-x,強推 env (重點)

          淘汰 es201x 的目的是把選擇環境的工作交給 env 自動進行,而不需要開發者投入精力。凡是使用 es201x 的開發者,都應當使用 env 進行替換。但這里的淘汰 (原文 deprecated) 并不是刪除,只是不推薦使用了,不好說 babel 8 就真的刪了。

          與之相比,stage-x 就沒那么好運了,它們直接被刪了。這是因為 babel 團隊認為為這些 “不穩定的草案” 花費精力去更新 preset 相當浪費。stage-x 雖然刪除了,但它包含的插件并沒有刪除(只是被更名了,可以看下面一節),我們依然可以顯式地聲明這些插件來獲得等價的效果。完整列表

          為了減少開發者替換配置文件的機械工作,babel 開發了一款 babel-upgrade 的工具,它會檢測 babel 配置中的 stage-x 并且替換成對應的 plugins。除此之外它還有其他功能,我們一會兒再詳細看。(總之目的就是讓你更加平滑地遷移到 babel 7)

          npm package 名稱的變化 (重點)

          這是 babel 7 的一個重大變化,把所有 babel-* 重命名為 @babel/*,例如:

          1. babel-cli 變成了 @babel/cli。
          2. babel-preset-env 變成了 @babel/preset-env。進一步,還可以省略 preset 而簡寫為 @babel/env。
          3. babel-plugin-transform-arrow-functions 變成了 @babel/plugin-transform-arrow-functions。和 preset 一樣,plugin 也可以省略,于是簡寫為 @babel/transform-arrow-functions

          這個變化不單單應用于 package.json 的依賴中,包括 .babelrc 的配置 (pluginspresets) 也要這么寫,為了保持一致。例如

          {
            "presets": [ -   "env" +   "@babel/preset-env"  ]
          } 

          順帶提一句,上面提過的 babel 解析語法的內核 babylon 現在重命名為 @babel/parser,看起來是被收編了。

          上文提過的 stage-x 被刪除了,它包含的插件雖然保留,但也被重命名了。babel 團隊希望更明顯地區分已經位于規范中的插件 (如 es2015 的 babel-plugin-transform-arrow-functions) 和僅僅位于草案中的插件 (如 stage-0 的 @babel/plugin-proposal-function-bind)。方式就是在名字中增加 proposal,所有包含在 stage-x 的轉譯插件都使用了這個前綴,語法插件不在其列。

          最后,如果插件名稱中包含了規范名稱 (-es2015--es3- 之類的),一律刪除。例如 babel-plugin-transform-es2015-classes 變成了 @babel/plugin-transform-classes。(這個插件我自己沒有單獨用過,慚愧)

          不再支持低版本 node

          babel 7.0 開始不再支持 nodejs 0.10, 0.12, 4, 5 這四個版本,相當于要求 nodejs >= 6 (當前 nodejs LTS 是 8,要求也不算太過分吧)。

          這里的不再支持,指的是在這些低版本 node 環境中不能使用 babel 轉譯代碼,但 babel 轉譯后的代碼依然能在這些環境上運行,這點不要混淆。

          only 和 ignore 匹配規則的變化

          在 babel 6 時,ignore 選項如果包含 *.foo.js,實際上的含義 (轉化為 glob) 是 ./**/*.foo.js,也就是當前目錄 包括子目錄 的所有 foo.js 結尾的文件。這可能和開發者常規的認識有悖。

          于是在 babel 7,相同的表達式 *.foo.js 只作用于當前目錄,不作用于子目錄。如果依然想作用于子目錄的,就要按照 glob 的完整規范書寫為 ./**/*.foo.js 才可以。only 也是相同。

          這個規則變化只作用于通配符,不作用于路徑。所以 node_modules 依然包含所有它的子目錄,而不單單只有一層。(否則全世界開發者都要爆炸)

          @babel/node 從 @babel/cli 中獨立了

          和 babel 6 不同,如果要使用 @babel/node,就必須單獨安裝,并添加到依賴中。

          babel-upgrade

          在提到刪除 stage-x 時候提過這個工具,它的目的是幫助用戶自動化地從 babel 6 升級到 7。

          這款升級工具的功能包括:(這里并不列出完整列表,只列出比較重要和常用的內容)

          1. package.json
          2. 把依賴(和開發依賴)中所有的 babel-* 替換為 @babel/*
          3. 把這些 @babel/* 依賴的版本更新為最新版 (例如 ^7.0.0)
          4. 如果 scripts 中有使用 babel-node,自動添加 @babel/node 為開發依賴
          5. 如果有 babel 配置項,檢查其中的 plugins 和 presets,把短名 (env) 替換為完整的名字 (@babel/preset-env)
          6. .babelrc
          7. 檢查其中的 plugins 和 presets,把短名 (env) 替換為完整的名字 (@babel/preset-env)
          8. 檢查是否包含 preset-stage-x,如有替換為對應的插件并添加到 plugins

          使用方式如下:

          # 不安裝到本地而是直接運行命令,npm 的新功能 npx babel-upgrade --write # 或者常規方式 npm i babel-upgrade -g
          babel-upgrade --write

          babel-upgrade 工具本身也還在開發中,還列出了許多 TODO 沒有完成,因此之后的功能可能會更加豐富,例如上面提過的 ignore 的通配符轉化等等。


          轉自:知乎。作者:前端解憂雜貨鋪


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

          TypeScript VS JavaScript 深度對比

          前端達人



          TypeScript 和 JavaScript 是目前項目開發中較為流行的兩種腳本語言,我們已經熟知 TypeScript 是 JavaScript 的一個超集,但是 TypeScript 與 JavaScript 之間又有什么樣的區別呢?在選擇開發語言時,又該如何抉擇呢?

          本文將會深入對比這兩種語言,討論兩種語言之間的關聯和差異,并概述兩種語言各自的優勢。

          JavaScript 和 TypeScript 的概要介紹

          JavaScript

          JavaScript 是一種輕量級的解釋性腳本語言,可嵌入到 HTML 頁面中,在瀏覽器端執行,能夠實現瀏覽器端豐富的交互功能,為用戶帶來流暢多樣的用戶體驗。

          JavaScript 是基于對象和事件驅動的,無需特定的語言環境,只需在支持的瀏覽器上就能運行。

          JavaScript 語言具有以下特點:

        1. JavaScript 是一種腳本編寫語言,無需編譯,只要嵌入 HTML 代碼中,就能由瀏覽器逐行加載解釋執行。

        2. JavaScript 是一種基于對象的語言,可以創建對象同時使用現有對象。但是 Javascript 并不支持其它面向對象語言所具有的繼承和重載功能。

        3. JavaScript 的語法簡單,使用的變量為弱類型。

        4. JavaScript 語言較為安全,僅在瀏覽器端執行,不會訪問本地硬盤數據。

        5. JavaScript 語言具有動態性。JavaScript 是事件驅動的,只根據用戶的操作做出相應的反應處理。

        6. JavaScript 只依賴于瀏覽器,與操作系統的因素無關。因此 JavaScript 是一種跨平臺的語言。

        7. JavaScript 兼容性較好,能夠與其他技術(如 XML,REST API 等)一起使用。


        8. TypeScript

          TypeScript 是 Microsoft 開發和維護的一種面向對象的編程語言。它是 JavaScript 的超集,包含了 JavaScript 的所有元素,可以載入 JavaScript 代碼運行,并擴展了 JavaScript 的語法。

          TypeScript 具有以下特點:

        9. TypeScript 是 Microsoft 推出的開源語言,使用 Apache 授權協議

        10. TypeScript 增加了靜態類型、類、模塊、接口和類型注解

        11. TypeScript 可用于開發大型的應用

        12. TypeScript 易學易于理解


        13. JavaScript 和 TypeScript 的主要差異

          TypeScript 可以使用 JavaScript 中的所有代碼和編碼概念,TypeScript 是為了使 JavaScript 的開發變得更加容易而創建的。例如,TypeScript 使用類型和接口等概念來描述正在使用的數據,這使開發人員能夠快速檢測錯誤并調試應用程序

        14. TypeScript 從核心語言方面和類概念的模塑方面對 JavaScript 對象模型進行擴展。

        15. JavaScript 代碼可以在無需任何修改的情況下與 TypeScript 一同工作,同時可以使用編譯器將 TypeScript 代碼轉換為 JavaScript。

        16. TypeScript 通過類型注解提供編譯時的靜態類型檢查。

        17. TypeScript 中的數據要求帶有明確的類型,JavaScript不要求。

        18. TypeScript 為函數提供了缺省參數值。

        19. TypeScript 引入了 JavaScript 中沒有的“類”概念。

        20. TypeScript 中引入了模塊的概念,可以把聲明、數據、函數和類封裝在模塊中。


        21. TypeScript 的優勢

          下面列舉 TypeScript 相比于 JavaScript 的顯著優勢:

          1. 靜態輸入

          靜態類型化是一種功能,可以在開發人員編寫腳本時檢測錯誤。查找并修復錯誤是當今開發團隊的迫切需求。有了這項功能,就會允許開發人員編寫更健壯的代碼并對其進行維護,以便使得代碼質量更好、更清晰。

          2. 大型的開發項目

          有時為了改進開發項目,需要對代碼庫進行小的增量更改。這些小小的變化可能會產生嚴重的、意想不到的后果,因此有必要撤銷這些變化。使用TypeScript工具來進行重構更變的容易、快捷。

          3. 更好的協作

          當發開大型項目時,會有許多開發人員,此時亂碼和錯誤的機也會增加。類型安全是一種在編碼期間檢測錯誤的功能,而不是在編譯項目時檢測錯誤。這為開發團隊創建了一個更高效的編碼和調試過程。

          4. 更強的生產力

          干凈的 ECMAScript 6 代碼,自動完成和動態輸入等因素有助于提高開發人員的工作效率。這些功能也有助于編譯器創建優化的代碼。

          JavaScript 的優勢

          相比于 TypeScript,JavaScript 也有一些明顯優勢。

          1. 人氣

          JavaScript 的開發者社區仍然是巨大而活躍的,在社區中可以很方便地找到大量成熟的開發項目和可用資源。

          2. 學習曲線

          由于 JavaScript 語言發展的較早,也較為成熟,所以仍有一大批開發人員堅持使用他們熟悉的腳本語言 JavaScript,而不是學習 TypeScript。

          3. 本地瀏覽器支持

          TypeScript 代碼需要被編譯(輸出 JavaScript 代碼),這是 TypeScript 代碼執行時的一個額外的步驟。

          4. 不需要注釋

          為了充分利用 TypeScript 特性,開發人員需要不斷注釋他們的代碼,這可能會使項目效率降低。

          5. 靈活性

          有些開發人員更喜歡 JavaScript 的靈活性。

          如何抉擇

          TypeScript 正在成為開發大型編碼項目的有力工具。因為其面向對象編程語言的結構保持了代碼的清潔、一致和簡單的調試。因此在應對大型開發項目時,使用 TypeScript 更加合適。如果有一個相對較小的編碼項目,似乎沒有必要使用 TypeScript,只需使用靈活的 JavaScript 即可。


          作者:grain先森
          來源:簡書
          著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。






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

          什么才是設計體系?結構、原則與認知誤區

          資深UI設計者

          一、設計體系的三層一環結構

          下面是我提出一個VGLT-MO三層一環結構,幫助大家理解設計體系。

          • 愿景與原則(Vision & Principle),它們作為設計決策的參考,指導前行。
          • 指南(Guidelines),包含樣式指南(Style Guideline)、模式指南(Patterns Guideline)、內容指南(Content Guideline)等更多通過文字和圖像進行傳達的內容。
          • 庫與工具(Libraries & Tools),包含組件庫(Components Libraries)、工具包(Toolkits)、協同工具(Collaborative Tools)等可以直接進行使用的內容。

          包圍著這三層內容的一環是管理結構(Management Structure)與組織流程(Organization Process),它促進整個設計體系成為一個活的生態系統。

          我曾參與過國內某知名企業的設計體系建設過程,遇到了很多困難,但也收獲了更多的認知,了解到不能怎么做和應該如何做,進一步促成了本篇文章;因此我試著搭建出設計體系的通用結構,并且文章后面闡述其中的價值和如何去構建設計體系。

          二、設計體系的原則

          系統規則影響系統行為,穩定的設計體系結構促進產生穩定的設計體系,關于設計體系的原則我將其歸結為以下4點原則:

          1)形式上,通用卻靈活

          設計體系是獨立存在于現有業務外的,用可預測的規則進行構建和管理,指導方向一致性,而非每個人獨自開腦洞。

          但是規則并不是限制,當指導不足以傳達更佳的用戶體驗時就通過體系機制的設計,即時迭代設計體系。

          設計師可以更快地完成原型和迭代工作,因而更加靈活地去思考滿足需求的解決方案。

          2)關系上,整合但互通

          整合設計與開發,鏈接設計與實現的代碼,有效地將體驗的設計與落地的開發相結合;但又通過獨立化的模塊設計以及模塊間關系的設計,搭配良好的機制和協同工具幫助使用者更流暢地使用。

          3)組織上,開放共享且跨域同步

          通過組織流程的設計讓基于模塊化設計思維的組件、設計模式、內容策略等等能被盡可能多的人重復利用,提高知識復用率;并讓關于用戶的知識在組織中的設計師、工程師、產品經理、市場營銷人員等人中保持同步和流通。

          4)成果上,協同而一致

          通過良好的開發體驗,用設計開發的規范化指導,讓大范圍的開發與設計都能良好地匹配用戶心智模型和多設備多平臺需求,帶來優質且統一的產品價值傳達和用戶體驗實現。

          除了創建更高的可用性(Usability)之外,也能建立更高的可訪問性(Accessibility),讓體驗在如障礙群體、各類配置低下的設備、有法律與文化的國際差異等在產品多次迭代中也能更易達成一致(這些往往是較少被考慮到的內容)。

          三、不同設計體系的差異

          不同組織和產品的設計體系都會不一樣。

          設計體系有不同規模(Kholmatova,2017),簡單來說可以分為平臺級設計體系(如Apple的人機交互指南HIG, Microsoft的流暢設計體系FDS)和公司級設計體系(如Atlassian的Atlassian設計體系ADS;Salesforce的閃電設計體系LDS,Adobe的Spectrum),如螞蟻金服的Ant Design等)。

          設計體系的開放程度不一,而且有些設計體系并不對外開放(如Airbnb的設計語言系統DLS),而微軟的流暢設計體系則是全程開放。

          我們可以從實踐規則(嚴格/松散)、構造方式(模塊化/整合化)和管理機制(集中式/分布式)(Kholmatova,2017)。

          任何組織都能在其中找到合適的定位,有些設計體系極為嚴格,而有些反而得益于其松散性與靈活性;如Airbnb的設計體系整體上更為嚴格,擁有詳實的設計規范文檔、設計與開發有精準的同步流程、擁有嚴格的新模式入庫流程,詳實全面的設計文檔等;通過內網進行使用,并開發一系列的插件工具促進設計與開發流程。

          Airbnb的DLS中的規范文檔

          Airbnb內網中的DLS

          而TED只有兩名 UX 設計師和四名前端工程師專職負責設計體系相關工作,因此就更稍顯松散;不同的程度都是和自身組織的團隊文化和產品特征有關的,他們更加關注有效地實現產品設計目標。

          “我們鼓勵以正確的方式進行設計,而非一味強調一致性原則;頁面的性能表現對于我們來說更為重要,如果它無法有效地承載內容,我們會將其修改到能夠承載為止;一致性與模式化的信條對于我們來說無法成為驅動設計決策的關鍵要素?!薄狹ichael McWatters,TED UX 架構師

          TED的規范文檔

          是標準化還是松散化,更多依靠組織文化下的選擇。它們各有利弊。一個緊湊嚴格,利于精準,但有時較為死板,會限制設計師進行創造發揮;一個靈活適應,利于拓展和快速變更,但難以控制,它們都需要找到解決自身缺陷的方法。

          關于模塊化還是整合化,我們可以根據各自適應的產品特征進行抉擇。

          例如模塊化方式適用于:

          • 需要擴展與進化空間;
          • 需要適應不同類型的用戶需求;
          • 需要大量的可復用部件參與構建;
          • 需要多個團隊同步并行地參與構建。

          典型的例子包括電商產品、新聞類產品、在線教育平臺、金融平臺、政府信息平臺等等。

          而整合化方式則適用于:

          • 面向一個特定目標進行設計的;
          • 無需具備擴展性與適應性;
          • 需要在體系范圍之外進行風格探索的;
          • 部件復用率較低的;
          • 一次性的。

          典型的例子包括創意展示類頁面、一次性的運營活動頁面、作品集等等。

          當然有許多不同的特質讓每個設計體系各不相同,關鍵的是,我們如何找到適合的定位;而關于管理方式上的劃分,我將在第4章-如何構建設計體系中進行更多詳細的論述。

          四、關于設計體系的認知誤區

          知道設計體系是什么,更需要了解設計體系不是什么。

          關于設計體系有一些誤區,例如:

          設計體系是設計規范(Design Guidelines)嗎?

          許多人都會將設計規范與設計體系相提并論。但實際上,他們并不是一個層級的東西,或者更準確的說是設計體系包含了設計規范。

          設計體系是模式庫(Pattern Library)或組件庫(Component Library)嗎?

          模式庫的建立在設計體系內,而模式庫是記錄和共享設計模式的工具,只是設計體系的工具化和顯現化的部分;像Bootstrap這樣的工具包不被認為是設計體系,因為它們缺少一些定義設計系統的重要元素:模式庫、風格指南和設計語言。

          設計體系是否會扼殺組織內的創造力?

          不好的設計體系當然會,但好的設計體系往往會通過機制和流程,促進實際的創造力,因為來自終端的良好的解決方案可以更快被整個組織所采用,而不必擔心那些即將淪為沉沒成本的過往設計與技術資產的限制。

          設計體系是一勞永逸的嗎?

          設計體系是動態的,永遠是隨著組織需求和用戶需求而變化的,一切說自己已經完成了設計體系的建設的人都是將靜態的設計規范曲解成了設計體系。



          文章來源:人人都是產品經理  作者:
          龍哩個龍

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


          設計體系的涌現:適應組織的需要

          資深UI設計者

          編輯導語:設計在產品中日??梢?,但設計體系從何而來?很多時候,我們可以基于一套架構嚴謹、規則統一的體系框架,對產品表現層面的設計工作可以逐漸實現模塊化運作;本文作者分享了關于設計體系的整體詳細介紹,我們一起來了解一下。

          ——WHY 為什么?

          設計體系從何而來,為何出現?設計體系如何發展到現在的樣子?

          ——WHAT 是什么?

          設計體系是什么?不是什么?關于設計體系有哪些誤區?與設計規范、組件庫、模式庫的區別是什么?有哪些現存的設計體系?

          ——HOW 如何做?

          如何搭建自己公司的設計體系?

          ——FUTURE 設計體系的未來如何?

          這篇文章有大量我的個人理解,因此難免出錯或是不準確的地方。

          國內設計和前端界對Design System主要存在兩種叫法,設計系統和設計體系。

          看看百度詞條對兩個詞匯的解釋:

          系統,來源于古代希臘文(systεmα),英文為system,日文音譯,后引為中文,即形容若干部分相互聯系、相互作用,形成的具有某些功能的整體。
          體系,英文為structure,泛指一定范圍內或同類的事物按照一定的秩序和內部聯系組合而成的整體,是不同系統組成的系統。

          要了解Design System,首先就得了解到它一定不是一堆UI組件,不只是設計師的事;如果稱Design System稱為“設計系統”,則是把它當成“產品”存在了,過于靜態,失去了人之間的聯系,但恰恰是人之間的聯系才能促成優秀設計體系的生成。

          因此盡管原英文單詞不同,但依據實際表達的意思,本文偏向于認同“設計體系”的名稱,相信你讀完之后也會認同這樣的叫法。

          一、設計體系的涌現:適應組織的需要

          目前來說,設計體系尚未出現清晰的定義,我們可以看一些設計體系的專家的定義:

          “由明確的標準指導的可重用組件的集合,這些組件可以組裝在一起以構建任意數量的應用程序?!薄猈ill Fanguy(2017,inVision設計體系專家)

          “一組相互關聯的模式和實例的共享,通過將一致地組織它們以服務產品目標。模式(Pattern)是我們用來創建界面的重復元素:如用戶流、交互、按鈕、文本字段、圖標、顏色、排版、微復制等;實例(Practices)是我們在團隊工作中如何選擇創建、獲取、共享和使用這些模式。”—— Alla Kholmatova(2017,著有設計體系:數字化產品設計的系統化方法)

          “由個人、團隊或社區記錄和發布的視覺風格、組件和其他的庫,以作為代碼和設計工具,以便采用產品可以更加高效和有凝聚力?!薄狽athan Curtis(2017,設計體系咨詢專家,幫助多個企業搭建設計體系)

          在本文綜合的理解下,我試著為設計體系下了更加清晰的定義:

          設計體系(Design System,也可以叫設計系統)是可重用組件的集合,由清晰的標準引導,通過機制化的組織流程和具象的指南與工具加以整合,以幫助開發者(設計、工程等)高效且一致地創建大量的應用,并且動態地確保用戶體驗的一致性。

          如果你之前不太了解設計體系,可能現在有點懵,沒關系,相信讀完我這篇文章,你一定就能了解。

          二、小故事:一個按鈕的旅程

          試想一下,現在你現在是UX設計師A1,我們現在因為某項用戶需求或業務需求需要處理。

          1. 那么最開始我們需要考慮是這個需求用按鈕還是用其他解決方案解決。最后我們決定了使用按鈕的方式。
          2. 然后再考慮一些視覺因素,例如框線、背景塊、描述、顏色、陰影、字體等元素,每個因素都需要考慮一遍……
          3. 再考慮頁面中的位置關系,在頁面靠左還是靠右?與四面保持多大間距?……
          4. 再加上互動因素,懸停的時候、點擊的時候、選中的時候、不可用的時候,再加上后續結果是跳出彈窗?打開新頁面?還是僅僅是頁面的小變化?……
          5. 嗯,不錯好像設計做完了,評審一下,大家似乎都同意了。然后交給視覺設計師C1處理視覺。差不多之后,再交到前端工程師小B1手上,啪啦啪啦敲一堆代碼,好像實現了。
          6. 驗收的時候又發現和最初設計并不一樣。前端怪你某個標注沒做清楚,然后就又拉著前端改改改……
          7. 如果又要做個按鈕,設計師A2與工程師B1之間又如何進行設計連接?工程師B2如何快速修改工程師B1的代碼?他們與組織中其他的設計師AN和工程師們BN又如何連接?……
          8. 又到某次軟件需要版本升級,需要對按鈕進行統一的改色和調整,不過之前的幾個前端到換到其他部門了,新的前端工程師B3發現軟件中的按鈕,盡管都是按鈕,但代碼都不相同,他花了非常多的時間找到了各個按鈕的代碼并逐一進行了更改……
          9. 而這些僅僅是一個按鈕,如果再加入表單、選項卡、標簽欄、搜索欄、樹形控件等等組件……停停停,已經腦溢血了。

          盡管A1設計師和B1工程師的自己的習慣可能類似,但由于參與人數的增多和任務量的增多,每個人都有自己的見解與習慣;考慮這一個按鈕中的每一種元素,回憶一下數學中的排列組合問題,最后將發現同一個問題的解決方案的組合情況將會產生成百上千甚至萬種可能,而這里很多都是重復工作。

          怎么辦?我們需要定義明確清晰的規則,讓不同的人都能為統一問題達成相對一致的解決方案處理,即達成設計工程化。

          設計體系便是一種解決辦法。但盡管是叫“設計體系”而不是叫“開發體系”,但這并不意味著這只是設計的事情;因此接下來,我將談談設計體系是如何誕生的。

          三、源起何處?——應對組織的挑戰

          上面的故事已經從側面體現出,當業務與用戶的需求迫使組織面對一系列的問題,迫使企業需要探索合適的解決方法。

          總的來說,設計體系的出現便是用來應對組織在敏捷、協作和債務處理等方面的需求。

          ——敏捷響應需求:在多設備、多平臺的現在,組織不可能選擇每隔幾年再更新一個全新的數字產品,因為這意味著在交互上用戶需要重新學習,在戰略上這種方式的不確定性因素過大,如果失敗就意味資源的大量浪費。

          就特性而言,數字產品不同于實體產品,往往需要盡快上市,最小成本檢驗,盡快迭代,以獲取更強的競爭力,而且以往寫的代碼也不會被磨損,需要定期進行維護;因此這些便對組織滿足用戶體驗的速度做出了要求,因此更多的組織逐漸采用如等以敏捷(Agile)和精益(Lean)思維為基礎的敏捷開發(Scrum)、設計沖刺(Design Sprint)等方法。

          ——復雜的協作鴻溝:對用戶來說,只需要點擊升級便可獲得最新的體驗,但這意味著這種體驗的即時在線化將體驗迭代的簡單交給了用戶,而復雜就留給了組織;UX設計師、前端工程師、產品經理、內容策略師們、可訪問性專家等等組成的組織結構和工作流程都需要得到適應性的改變,才能提供快速迭代的流程去完成版本管理、設計管理、債務管理等工作?

          Alex Schleifer(Airbnb設計副總監)也提到這樣的情況:雖然工具的提升幫助編碼的速率和設計的效率都在提升,但最終使設計生效的是多方面的協作的結果,然而原有方式越來越多暴露出在跨學科溝通上的問題,這些依然阻礙著產品創新以實現更佳用戶體驗的效率。

          ——債務大量累積: 這里的債務不是指經濟上的債務,在設計上,由于設計人員的個體差別和缺乏系統性機制促進設計經驗溝通,設計往往在長期的開發過程中提供了許多定制化的解決方案;在UI上可以體現為不同樣式的按鈕或顏色等、UX上可以體現為同一軟件上的交互邏輯混亂等,這造成了設計債務(Design Dept)。

          而技術債務(Technical Dept)亦是如此,為同一個問題,不同的工程師使用不同的代碼或是令牌標記,加大了代碼設計與維護、拓展的難度;同時,我認為其中還存在一個債務,我將其稱之為產品債務(Product Dept),不同類別的產品經理等負責產品定義等職能的人員為同一產品或業務功能提供了不同,但效果相似的產品解決辦法。

          而且無論你是互聯網公司,亦或是傳統產品公司,越是龐大的體系,人員就越細分,在整體設計上的知識就越分裂,就越有可能出現同一問題多個定制化解決方案的情況,這會讓出現在工程、產品、設計上的債務就越龐大。

          這些設計、技術、產品債務讓管理、維護都異常艱難;而且只要審視一下我們日常工作的周遭,就會發現債務其實無處不在;那些雜亂的視覺形象應用、那些不統一的工業產品材料與色彩、那些無準則的交互行為、那些不一致的反饋聲音、同一數字產品不同的功能模塊定義等等……

          時至今日,設備和用戶的多樣性都在激增,以往的標準、工作流程和基礎設施都難以支撐;我們用設計和開發應對的問題越來越多,變化也越來越多,但我們一直在定制化和通用化之間無序游離。

          可以在一些軟件中看到同樣的一個功能按鈕出現十幾種形式,而它們要解決的問題卻幾乎一樣;也可以看到那些拙劣的設計規范中,萬物歸為一種單調樣式,降低了開發成本,卻帶來用戶認知的困難。它們都難以維護,極大地阻礙了組織創造體驗、達成商業可持續和創新的效率。

          四、組織的應對?996還是一勞永逸?

          面對著這些問題,公司只能存在幾種選擇(Suarez等人,inVison):

          • A-不改變速度雇傭更多的人(通過內部雇傭或業務外包);
          • B-提升員工設計與開發的速度(個人能力的極致壓制,996、007);
          • C-改變工作的方式,創建通配式的解決方案,提高設計與代碼復用率以提升效率(如模塊化)。

          大部分組織為了滿足快速發展的需要,往往更多采用A和B的方式(例如各種各樣的業務擴充,產生了大量對工程和設計人員的需求,如阿里、網易、字節、美團等)。

          但提升人員,仍然不能解決定制化方案的拓展問題,仍然存在大量不可復用的方案,造成效率的浪費;好比毒素累積,治標不治本,當達到足夠的毒素累積之后,創新將寸步難行。

          如果不首先創新構建方式,就無法創新產品,這是非常簡單的真理?!狝lex Schleifer(Airbnb設計副總監)

          雖然組織內也一直在提升效率,但管理只能提升局部效率,工具才能帶來系統的變革。

          設計體系的提出并不只是為了解決用戶體驗的問題,而是適應組織內的開發需求。而通配式解決方案的方法則更具系統性、遠期性。這便是設計體系的源頭,模塊化(Modularity)是一個關鍵詞。

          五、設計體系的發展歷程

          早在福特的時代,“流水線”思維就將生產流程模塊化進而提升生產效率和生產一致性,形成大批量的工業化時代,形成了強勢的美國汽車工業;二戰之后,20世紀60年代,豐田作為日本汽車制造商的一分子運用精益生產的小批量生產方法,注重發掘工人的創造力,即時解決問題,響應需求,降低遠期浪費。 (E Ries, 2012)

          回到軟件開發上來。20世紀60年代,越來越多組織發現軟件發展的速度已經跟不上硬件的升級,軟件開發越來越容易緩慢、難維護且容易出錯。在開發上,預算超支、超時運行,在使用效果上效率和質量都很低下;在運維上,不符合要求、難以維護管理代碼,容易造成軟件無法交付。

          硬件與軟件之間的差距以及解決這個問題而造成的困境,軟件危機(Software Crisis)便出現了。

          沒人能對這些問題視而不見,開發者與設計師的先驅們開始探索解決方案。

          1968年,第一屆北約軟件工程(NATO)會議上,道格拉斯·麥克羅伊(Douglas McIlroy)提出了基于組件(Component-based)的開發方法,通過復用代碼來提高編程潛力的方法,減少編程的工作量,同時能幫助編程工作更高效、更易于擴展且靈活,提升軟件開發速度;因此這被認為是有可能是解決“軟件危機”的方法之一,這種方法可以算是早期的設計體系的基礎雛形。(軟件危機&INvision)——維基百科,關于軟件危機的描述

          而在設計界,也有先驅提出了類似方法。1977年,Alexander等人通過其書A Pattern Language,提出了模式語言(Pattern Language),期望用系統化的方法解決設計建筑、城鎮和建設方式的問題,幫助形成一種實現為250多種不同類型建筑的持續性方式(Koivisto,2019);這種語言通過共享共同的模式,用共同設計的方式將更多人納入設計過程。

          如果每個模式都是解決共同的問題,那么當面向同樣的問題時,用模式等方式快速應用以前的解決方法將可能是高效的工具;這里的模式(Pattern)便是用戶界面設計中的循環解決方式,模式庫是特定用戶界面上重復設計元素的集合。

          在網頁開發時代,網頁設計師用基礎的網頁架構就能搭載數以萬計的頁面。

          21世紀初,YUI和jQuery UI等庫的引入,為開發人員提供了一套小部件和模式的工具包,以創建更一致的網站用戶界面(Forst, 2016)(例如Bootstrap是Twitter開發的基于網頁解決方案的前端工具包,供設計師和開發人員使用)。

          但這些方法也會些有優有劣,例如Mary Collin就曾對使用Bootstrap開發的網頁進行綜合對比,結果發現Bootstrap容易導致成果缺乏獨特性,看起來外觀非常一致;但在另一方面,在移動端響應性和拓展性方面效果很不錯,因為足夠穩定。

          Mary Collin的一些網頁對比

          在現代,互聯網興起,尤其是移動互聯網的興起,降低了信息分發與復制的邊際成本和提供了龐大的用戶量;即時在線的網絡為數字產品的測試和快速迭代提供了可能,良好的用戶體驗能為企業創造的價值將遠超傳統時代,體驗的重要性迫使數字產品不得不用更快速的升級換代過程滿足用戶需求?!ㄓ彳?,2020)

          但規范或庫本身是靜態的,依然具備過多的不確定性,并且缺乏對開發全鏈路的支持,尤其是未來的每一次的設計如何決策。

          因此進一步,一些通用設計資產(Design Assets)被逐漸固定下來,并輔以使用的規則描述,設計模式(Design Patterns)逐步形成,為協作而生,通過為重復的共同問題快速生成解決方案,并盡可能在整個組織內保持一致以提升效率。因為類似的原因和目的,也同時產生了例如樣式指南、設計語言、內容指南、甚至是品牌識別系統等等類似產物。

          在軟件開發問題上,設計規范和設計模式成為內部設計師們依靠復制粘貼進行傳播的文檔,亦或是前端工程們網上開源共享的模式庫(Pattern libraries)或組件庫。

          與設計模式不同,模塊化設計(Modular Design)引入了敏捷設計方法的思想;建立在以前的基礎上,讓解決方案的更快、更短的迭代,前端框架是提供特定解決方案和特定外觀和感覺的工具”(Frost,2013)。

          框架本質上是模塊化的,它們專注于單個項目或設計問題(Frost,2013);對于多個設計問題,框架、模式庫或模塊化設計本身不足以系統地使用,這樣的背景下,便迎來了設計體系的涌現。

          六、大量涌現的設計體系

          2013年,Brad Forst提出了原子設計(Atomic Design)理論為設計體系的出現奠定了一波理論熱度,提供了更加形象化的描述說明;這讓更多人意識到這些問題的存在,并且提供了易于理解且廣泛傳播的理論基礎和解決方案。

          Brad Forst,原子設計(Atomic Design)理論

          原子設計理論將交互元素似化學因子一般逐步拆分。

          • 在最底層級是原子(Atoms,例如按鈕、圖標的最小組件等);
          • 原子構成分子(Molecules,分子由兩個或多個攜帶自身屬性的原子組裝而成,并形成更實質性和功能性的組件,例如由表單標簽、輸入和按鈕組成的搜索表單);
          • 分子組成為有機體(Organisms,分子和原子組成的更大組裝體,是界面的一部分,如導航欄或標題);
          • 再組成為模板(Templates,將原子、分子和有機體等相對抽象的屬性放入情境中,接近最終解決效果,但更關注底層頁面結構);
          • 最后這些模板在設計師和工程師的協作下,變成實際的頁面(Pages)。

          這是一種逐步拆分式的模塊化方法。

          他建議用模式庫(Pattern Library,也被稱為用戶界面庫、組件庫、資產庫等)集合構成用戶界面的可重用組件,并通過指南(Guideline)指導如何創建,以進一步綜合了風格指南、流程指南、設計語言等等設計指南;包括他之內的幾位設計體系先驅都提出要進一步整合領域內語言,開始更多地使用設計體系(Design System)這樣的語言來代表類似的事物。

          理論如此,實踐永遠不會落下?;ヂ摼W的廣泛普及帶來用戶需求量爆炸,對公司來說,越來越多的業務量壓力和一致的體驗需求的迫使下,越來越多的企業推出了自家的設計體系。

          2014年伊始,Google推出了質感設計體系(Material Design System),類似的時間前后Atlassian搭建了Atlassian設計體系和Airbnb也在內部搭建設計體系(即后來的設計語言體系,DLS,Design Language System);在此之后,一系列公司跟進開始研究和開放自己的設計體系。

          例如Apple的人機界面指南(HIG),Microsoft的流暢設計體系(Fluent Design System)、IBM的碳設計體系(Carbon Design System),Salesforce的Lightning設計體系、Shopify的Polaris設計體系,甚至一些英國、美國、澳大利亞等公共部門也推出了自己的設計體系,如英國政府的GOV.UK設計體系。

          Google,Material Design System

          Microsoft,Fluent Design System

          Apple,Human Interface Guidelines

          IBM,Design Language

          而在國內,搭建的比較完善的有知名的螞蟻金服Ant Design設計體系,還有Element,以及View UI等中臺設計體系,以及許多存在于部門內部、仍然只是設計規范、或者設計體系不完全體的內容。

          螞蟻金服,Ant Design

          ——插個題外話,微軟的流暢設計體系(Fluent Design System)是我這篇文章最開始的起點,從簡單論述微軟如何統一用戶體驗聚焦到流暢設計體系。

          當然關于Fluent Design System的更多內容,我會在本系列文章之后,單獨出篇文章描述我的發現【稿子都差不多了,寫著寫著就寫成了設計體系系列文章哈哈】。

          我們現在知道設計體系是為了什么了,但在現在的階段,問題不是能搭建什么,而是如何能更好地搭建。

          “體驗工程的建設已經遠遠不止于一套設計規范或一套組件庫,他需要一套完整的系統來支撐,解決內部協作的一致性問題,解決設計系統更新的周期性問題,解決一群設計師與工程師如何規模化的生產各種業務 UI 的問題,從而最終解決用戶體驗一致性的問題“——Alibaba Fusion Design



          文章來源:人人都是產品經理  作者:
          龍哩個龍

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


          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合