首页

JavaScript - 数组排序 6 种常见算法

前端达人

开发中,遇到数组排序的需求很频繁,这篇文章会介绍几个常见排序思路。

一、希尔排序(性能最好)

如果要从大到小排列,则 while(arr[n] > arr[n - interval] && n > 0) 。

// 希尔排序算法 function xier(arr){ var interval = parseInt(arr.length / 2);//分组间隔设置 while(interval > 0){ for(var i = 0 ; i < arr.length ; i ++){ var n = i; while(arr[n] < arr[n - interval] && n > 0){ var temp = arr[n]; arr[n] = arr[n - interval]; arr[n - interval] = temp; n = n - interval; } } interval = parseInt(interval / 2); } return arr; } // Array var arr = [10, 20, 40, 60, 60, 0, 30] // 打印排序后的数组 console.log(xier(arr))//[0, 10, 20, 30, 40, 60, 60]  

二、sort排序(普通数组 / 数组嵌套对象)

一堆数组排序

// Array var arr = [10, 20, 40, 60, 60, 0, 30] // 排序方法 arr.sort(function(a,b){ /*
    * return b-a; —> 降序排序
    * return a-b; —> 升序排列
    */ return a-b; })//括号里不写回调函数则默认按照字母逐位升序排列 // 打印排序后的数组 console.log(arr)//[0, 10, 20, 30, 40, 60, 60]  

对象数组排序(数组套对象)

//对象数组排序 var arr = [ {name:'syy', age:0}, {name:'wxy', age:18}, {name:'slj', age:8}, {name:'wj', age:20} ]; // 排序方法 function compare(property) {//property:根据什么属性排序 return function(a,b){ var value1 = a[property]; var value2 = b[property]; /*
        * value2 - value1;  ——> 降序
        * value1 - value2;  ——> 升序
        */ return value1 - value2;//升序排序 } } // 打印排序后的数组 console.log(arr.sort(compare('age'))) /*
0: {name: "syy", age: 0}
1: {name: "slj", age: 8}
2: {name: "wxy", age: 18}
3: {name: "wj", age: 20}
*/  

三、桶排序

特点:简单,但非常浪费内存,几乎不用。

桶中出现的数组元素都做个标记 1,然后将桶数组中有 1 标记的元素依次打印。

// Array var arr = [] // 每个数组项做标记(1) for(let i = 0; i < arr.length; i++) { let key = arr[i] arr[key] = 1 } // 遍历打印出每项 for(let j in arr) { debugger console.log(j) }  

四、冒泡排序

性能:一般(需要每项进行比较)。

每一趟找出最大的值。

// Array var arr = [10, 20, 40, 60, 60, 0, 30] /*
* 总共比较次数为arr.length-1次
* 每次的比较次数为arr.length-1次
* 依次递减
*/ var temp;//交换变量标识 // 两层for分别表示当前项与第二项 for(let i = 0; i < arr.length - 1; i++) { for(let j = 0; j < arr.length - 1; j++) { // 如果当前项大于第二项(后一项)则交换 if(arr[j] > arr[j+1]) { temp = arr[j] arr[j] = arr[j+1]; arr[j+1] = temp; } } } // 打印排序后的数组 console.log(arr)//[0, 10, 20, 30, 40, 60, 60]  

五、选择排序

性能:一般(需要每项进行比较)。

假定某个位置的值是最小值,与冒泡排序类似。

// Array var arr = [10, 20, 40, 60, 60, 0, 30] var temp;//交换变量标识 // 两层for分别表示当前项与第二项 for(let i = 0; i < arr.length - 1; i++) { for(let j = i + 1; j < arr.length; j++) { // 假设第二项是最小值(是则交换/否则继续比较) if(arr[i] > arr[j]) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } // 打印排序后的数组 console.log(arr)//[0, 10, 20, 30, 40, 60, 60] 

六、插入排序

// Array var arr = [10, 20, 40, 60, 60, 0, 30] // 排序算法 for(var i = 0; i < arr.length; i++) { var n = i; while(arr[n] > arr[n+1] && n >= 0) { var temp = arr[n]; arr[n] = arr[n+1]; arr[n+1] = temp; n--; } } // 打印排序后的数组 console.log(arr)//[0, 10, 20, 30, 40, 60, 60]



转自:https://blog.csdn.net/weixin_44198965/article/details/107996497?utm_medium=distribute.pc_category.none-task-blog-hot-4.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-4.nonecase&request_id=

作者:

手机appUI界面设计赏析(七)

前端达人

手机UI中的交互是保持产品鲜活生命力的源动力。好的交互可以帮助用户快速地获得反馈,认知布局,增强体验感和沉浸感。

手机UI中的交互是保持产品鲜活生命力的源动力。好的交互可以帮助用户快速地获得反馈,认知布局,增强体验感和沉浸感。这里为大家整理了一些优秀并富有创意的交互作品,为你的产品设计注入灵感。

专业又贴心医疗App页面设计

医疗行业设计案例

微信图片_20200818185149.jpg

   --手机appUI设计--

微信图片_20200818185156.jpg

   --手机appUI设计--微信图片_20200818185200.png

   --手机appUI设计--微信图片_20200818185204.jpg

   --手机appUI设计--微信图片_20200818185208.png

   --手机appUI设计--微信图片_20200818185211.png

   --手机appUI设计--微信图片_20200818185217.png

   --手机appUI设计--微信图片_20200818185221.jpg

   --手机appUI设计--微信图片_20200818185226.jpg

   --手机appUI设计--微信图片_20200818185229.jpg

   --手机appUI设计--微信图片_20200818185235.png

   --手机appUI设计--微信图片_20200818185239.png

   --手机appUI设计--微信图片_20200818185242.png

   --手机appUI设计--微信图片_20200818185246.png

   --手机appUI设计--微信图片_20200818185249.png

   --手机appUI设计--微信图片_20200818185254.jpg

   --手机appUI设计--微信图片_20200818185257.jpg

   --手机appUI设计--微信图片_20200818185301.jpg

   --手机appUI设计--微信图片_20200818185307.jpg

   --手机appUI设计--微信图片_20200818185320.png

   --手机appUI设计--微信图片_20200818185323.jpg

   --手机appUI设计--微信图片_20200818185326.jpg

   --手机appUI设计--微信图片_20200818185333.jpg

   --手机appUI设计--微信图片_20200818185336.jpg

   --手机appUI设计--微信图片_20200818185339.png

   --手机appUI设计--




(以上图片均来源于网络)



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



  更多精彩文章:

       手机appUI界面设计赏析(一)

       手机appUI界面设计赏析(二)

       手机appUI界面设计赏析(三)

       手机appUI界面设计赏析(四)

       手机appUI界面设计赏析(五)

       手机appUI界面设计赏析(六)



Flutter 实战:增删查改功能示例代码

seo达人

七月,我们上线重磅基础能力——实时数据库,并开了实战直播课,让大家可以更好的理解并使用该服务。你的聊天室、站内信、投票、小游戏等需要高实时的功能正在想你招手,赶紧使用实时数据库服务又快又简单的开发它们吧。


点击此处回顾教学视频,看看知晓云大前端组长如何在十分钟内搞定一个视频弹幕微信小程序。


Ps:目前实时数据库限时免费,就算以后收费,费用也是低到忽略不计。速速用上,不要错过这么硬核的能力。


八月,我们迎来知晓云三周年,推出各式各样的福利活动。开发者在这个全年最优惠的时间里,升级、续费,甚至购买三年期包年套餐,与知晓云锁定下一个三年。非常感谢大家的支持,我们会继续努力,不断输出更强大的能力。


九月初,Flutter SDK 已进入测试阶段,很快就可以跟大家见面了。

Flutter SDK 的使用比较简明易懂,例如对数据表的增删查改,在指定数据表后,对数据项进行对应操作即可,例如新增(create)、查找(get)、修改(update)和删除(delete)。


以下是对 Flutter 增删查改功能进行展示:


TableObject product = new TableObject('product'); // 获取名为 product 的数据表


// 新增数据

TableRecord record = product.create(); // 创建一条空白记录


// 为属性字段赋值

record.set('name', '知晓云 flutter sdk'); // 对 name 字段进行赋值

record.set('version', '1.0'); // 对 version 字段进行赋值


// 将数据保存到服务器

record = await record.save(); // 保存


// 从服务器获取一条数据

TableRecord record = await product.get(record.id);


// 更新数据

record.set('version', '1.1');

await record.update();


// 删除数据

await product.delete(recordId: record.id);

目前知晓云 Flutter SDK 支持的功能如下:


数据表

用户

内容库

文件

云函数调用

获取服务器时间

本地存储

Flutter SDK 正式上线后,我们还会输出实战教学视频,敬请期待!


另外,我们提前开启内测申请通道,点击此处或微信扫一扫扫描下方卡片二维码即可申请,获得内测资格的开发者,不仅可优先体验新功能,同时还可以与知晓云工程师近距离交流,你使用后的建议也可以得到更快的反馈与实现。


知晓云 Flutter SDK


2020 年已过去三分之二,好消息是,即将到来的中秋&国庆小长假以及知晓云近期的更新内容,除了即将上线的 Flutter SDK ,还有以下更新。


1. 支持 QQ 小程序订阅消息,消息能力又前进一步。

与微信订阅消息不同在于,QQ 小程序订阅消息不仅支持分为「一次性订阅」,还支持「长期订阅」,如果用户之前已经同意授权长期订阅,则不会再出现弹窗询问。>>> 查看开发文档


2. iOS 和 Android SDK 支持微博登录。


查看 iOS 开发文档

查看 Android 开发文档

如果你有其他需求,可以通过文末

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

高手如何从零开始设计 UI 界面?这个实战案例告诉你!

周周

这是 UI 设计师 Diana Malewicz 的一篇 UI 界面设计的分享。怎样在保证基本的可用性和易用性的同时,让界面柔和、富有亲和力?如何在让用户愉悦的同时,还能用设计取悦自己?Diana 的方法谈不上有多神奇,但是让人眼前一亮,值得借鉴。

真的关注趋势变化,你会清晰的感受到,视觉效果和设计技巧一直在变……它们一直是设计师们的话题中心。但是这篇文章并不打算讨论这个事儿,无论渐变是否流行,新拟物化的可访问性是否不足,都不在今天的讨论范围内。

对于各种风格、方法,我的观点始终是:做出来的设计要可用,有用,有良好的可访问性,用户可以轻松理解,就行了。不过,我更乐于从趋势中获得乐趣,而不是将它视作为约束,如果每个界面看起来都是一样的,那该是一件多么无聊的事情啊。

关键在于,要让产品的视觉样式和你的用户群体匹配起来。

我个人非常喜欢漂亮的渐变和微妙的阴影,这样的设计常常显得魅力非凡。这种自然的过渡和光影的变化,非常贴合我们对于现实世界的感知,这就是为什么这样的设计能够俘获大量没有技术背景的用户的心——因为它们看起来友好,并且易于理解。

在这篇文章当中,我将分享如何将 UI 效果设计得出彩又友好,让视觉效果柔和又让人感觉舒适。本文围绕着一个「面向年轻人的金融 APP」虚拟设计项目来进行展示。

下面我们开始吧!

视觉层次的一致性

怎么让我们的设计看起来柔和圆润呢?下面开始准备工作:

1、选择想要使用的配色(想想使用柔和的粉彩构成的背景主色调,搭配一个给人精致感的次要色,以及一个抓人注意力的强调色。)

2、选择合理的字体(我用的是 Brandon Grotesque,这是我最喜欢的字体,它足够友好,能够营造有趣的氛围,且具有良好的可读性)。接下来,给字体设计不同大小和字重(最好不超过5种不同的样式)。其中,标题字体应该较大,正文字体较小,最小的字体用于细节呈现。注意,尽量不要在长句子里面使用全大写。

3、确定你所需要的阴影的高程(Height)和模糊度。

4、如果使用的是图标,确定使用填充样式还是描边样式。尽量不要混用。

至此,一个小型的设计系统就已经确定了。挺好看的!

uni-app提交表单到后端,接收表单数据

seo达人

要想接收表单数据,首先要在表单进行数据的绑定,我们可以使用v-model="keyword"进行绑定。


然后在js获取这个绑定的值。


index.vue


<template>

<view>

   <view class="search-con">

           <view class="form-con">

           <form class="search-form">

               <input type="text" v-model="keyword" @tap="showsearchbtn" focus="true"/>

               <button form-type="submit" hover-class='none' @tap="keyword">提交</button>  

           </form>

           </view>

   </view>

</view>

<template>

js


<script>

export default {

   data() {

       return {


           }

       },

       methods: {

           keyword(e){

               // 获取表单值

               let kw = this.keyword;

               console.log(kw);

           }

       }

   }

</script>

Author:TANKING

Web:http://www.likeyun.cn

Date:2020-8-13

WeChat:face6009

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

滴滴出行小程序I18n最佳实践

seo达人

背景

I18n = Internationalization,国际化,因为单词由首末字符i/n和中间18个字母组成,简称i18n。对程序来说,就是要在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面,以支持不同语言的人顺利使用程序。

业务背景

互联网行业进入下半场,精细化运营是关键。多语言支持能让产品更好地服务境内的其他语言用户,也为产品出海打下基础,随着 WeChat/Alipay 的全球化,你的小程序是否做好准备了呢?

4月初,滴滴出行小程序团队接到支持英文版的需求,预计上线时间为6月上旬。当前滴滴出行小程序集成的众多业务线和各种公共库,展示给用户的有前端硬编码的静态文本和服务端下发的文案,都要同步接入多语言。考虑到小程序当前的体量,光文本收集、语料翻译、npm package 支持,联调,测试,沟通成本等等,并且前端开发只投入1.5人力的情况下,时间是蛮紧迫的,但是我们抗住了压力,最终英文版滴滴出行小程序如期上线,截止目前运行稳定,用户反馈良好,得到了超出预期的收益。

当然这一切得益于各团队同学的工作,和各团队的通力配合,更得益于部门技术团队 Mpx框架优雅的多语言能力支持。划重点来咯,所谓工欲善其事必先利其器,如果你的公司业务需要开发小程序,也需要接入多语言,那么请搬好小板凳,我们来看一下小程序框架 Mpx 是如何优雅支持多语言能力。相信看完这篇,可以帮助你认识 Mpx(https://github.com/didi/mpx) ,加深对框架的理解,最终利用 Mpx 框架迭代小程序,年终奖多出那部分可以打赏一下作者,买杯咖啡哈(偷笑.jpg)

以下是滴滴出行小程序的中英文版本对比:

滴滴出行微信小程序i18n

也欢迎大家在微信/支付宝里搜索滴滴出行小程序,实际使用感受下。PS:切换语言的方法是,打开小程序,点击左上角用户头像,进入侧边栏设置页面,点击切换中英文即可体验。

技术背景

在上述业务背景下,Mpx 框架——滴滴自研的专注提升小程序开发体验的增强型小程序框架,内建 i18n 能力便提上日程。

与 WEB 不同,小程序(本文以微信小程序为例)运行环境采用双线程架构设计,渲染层的界面使用 WebView 进行渲染,逻辑层采用 JSCore 线程运行 JS脚本。逻辑层数据改变,通过 setData 将数据转发到 Native(微信客户端),Native 再将数据转发到渲染层,以此更新页面。由于线程间通信成本较高,实际项目开发时需要控制频次和数量。另外小程序的渲染层不支持运行 JS ,一些如事件处理等操作无法在渲染层实现,因此微信官方提供了一套脚本语言 WXS ,结合 WXML ,可以构建出页面的结构(不了解 WXS ?戳这里)。

基于小程序的双线程架构设计,实现 i18n 存在一些技术上的难点与挑战,由于 Mpx 框架早期构建起来的强大基础,最终得以优雅支持多语言能力,实现了和vue-i18n 基本一致的使用体验。

使用

在使用上,Mpx 支持 i18n 能力提供的 API 与 vue-i18n 大体对齐,用法上也基本一致。

模板中使用 i18n

编译阶段通过用户配置的 i18n 字典,结合框架内建的翻译函数通过 wxs-i18n-loader 合成为可执行的 WXS 翻译函数,并自动注入到有翻译函数调用的模板中,具体调用方式如下图。

// mpx文件 <template> <view> <view>{{ $t('message.hello', { msg: 'hello' })}}</view> 

<!-- formattedDatetime计算属性,可基于locale变更响应刷新 --> <view>{{formattedDatetime}}</view> </view> </template>

JS 中使用 i18n

通过框架提供的 wxs2js 能力,将 WXS 翻译函数转换为 JS 模块注入到 JS 运行时,使运行时环境中也能够调用翻译函数。

// mpx文件 <script> import mpx, { createComponent } from '@mpxjs/core' createComponent({ 

ready () { // js中使用 console.log(this.$t('message.hello', { msg: 'hello' }))

// 局部locale变更,生效范围为当前组件内 this.$i18n.locale = 'en-US' setTimeout(() =>

{ // 全局locale变更,生效范围为项目全局 mpx.i18n.locale = 'zh-CN' }, 10000)

}, computed: { formattedDatetime () { return this.$d(new Date(), 'long') } } }) </script>

定义 i18n 字典

项目构建时传入 i18n 配置对象,主要包括语言字典和默认语言类型。

new MpxWebpackPlugin({ i18n: { locale: 'en-US',

// messages既可以通过对象字面量传入,也可以通过messagesPath指定一个js模块路径,

在该模块中定义配置并导出,dateTimeFormats/dateTimeFormatsPath和numberFormats/numberFormatsPath同理

messages: { 'en-US': { message: { hello: '{msg} world' }

}, 'zh-CN': { message: { hello: '{msg} 世界' } } }, // messagesPath: path.resolve(__dirname, '../src/i18n.js') } })

如果是通过 Mpx 提供的 cli 工具生成的项目,这部分配置会在 mpx.conf.js 文件中,不光可以直接内联写在该文件中,也可以指定语言包的路径。

以上,Mpx 的 i18n 方案接入成本低,使用优雅,体验优秀。直观感受可参考下面 mpx i18n demo :https://github.com/didi/mpx/t...

方案

Mpx框架的 i18n 支持几乎完全实现了 vue-i18n 的全部能力,下面我们来详细说明 Mpx 框架 i18n 能力的具体实现。

方案探索

基于小程序运行环境的双线程架构,我们尝试了不同方案,具体探索过程如下:

方案一:基于 Mpx 框架已提供的数据增强能力 computed 计算属性,来支持 i18n 。该方案与 uniapp 的实现思路相似(后文会进行对比分析),存在一定不足,包括线程通信带来的性能开销和for循环场景下的处理较复杂等,最终放弃。
方案二:基于 WXS + JS 支持 i18n 适配。通过视图层注入 WXS,将 WXS 语法转换为 JS 后注入到逻辑层,这样视图层和逻辑层均可实现 i18n 适配,并且在一定程度上有效减少两个线程间的通信耗时,提高性能。

从性能和合理性上考虑,我们最终采用了方案二进行 Mpx 的 i18n 方案实现。

mpx-i18n内部流程示意图

Mpx i18n 架构设计图

由于各大小程序平台上,WXS 语法和使用均存在较大差异,因此该方案实现过程中也存在一些技术上的难点,这些难点基于 Mpx 框架的早期构建起来的跨平台能力也一一得以攻克,具体如下。

实现难点

WXS 在模板中运行的跨平台处理

WXS 是运行在视图层中的 JS,可以减少与逻辑层通信耗时,提高性能。因此 Mpx 框架在迭代初期便已支持在模板和 JS 运行环境使用 WXS 语言,并且针对小程序跨平台 WXS 语法进行抹平。
在模板中,Mpx 自定义一个 webpack chunk template,以微信 WXS 作为 DSL,利用 babylon 将注入的 WXS 转化成 ast,然后遍历 ast 节点,抹平各大平台对 WXS 语法的处理差异,输出各平台可以识别的类 WXS 文件。目前主要支持微信(WXS)、支付宝(sjs)、百度(filter)、QQ(qs)、头条(sjs)等小程序平台。

WXS 在逻辑层运行的跨平台处理

WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。并且 WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。
因此在逻辑层,Mpx 将注入的 WXS 语法转化为 JS,通过 webpack 注入到当前模块。例如 WXS 全局方法 getRegExp/getDate 在 JS 中是无法调用的,Mpx将它们分别转化成 JS 模块,再通过 webpack addVariable 将模块注入到 bundle.js 中。
同理,Mpx 会将编译时注入的 i18n wxs 翻译函数和 i18n 配置对象挂载到全局 global 对象上,利用 mixin 混入到页面组件,并监听 i18n 配置对象,这样JS和模板中即可直接调用 i18n 翻译函数,实现数据响应。

以上便是 Mpx 框架在小程序中支持 i18n 能力的技术细节,由于 WXS 是可以在视图层执行的类 JS 语法的一门语言,这样就减少了小程序逻辑层和视图层的通信耗时,提升性能。但是由于实现依赖类 WXS 能力,以及 WXS 执行环境的限制,目前模板上可直接使用的翻译函数包括 $t/$tc/$te ,如果需要格式化数字或日期可以使用对应的翻译函数在 JS 中 Mpx 提供的计算属性中实现。

输出 web 时使用 i18n

Mpx同时还支持转换产出H5,而 Mpx 提供的 i18n 能力在使用上与 vue-i18n 基本一致,输出 web 时框架会自动引入 vue-i18n,并使用当前的 Mpx i18n 配置信息对其进行初始化,用户无需进行任何更改,即可输出和小程序表现完全一致的 i18n web 项目。

对比

上面分析了 Mpx 框架的 i18n 方案的技术细节,我们来看下和其他方案的对比,主要是和 uniapp - 基于 Vue 编写小程序的方案,和微信官方的方案,两者提供的 i18n 支持与Mpx的对比有何优劣。

uniapp的方案

uniapp 提供了对 i18n 能力的支持,是直接引入vue-i18n。但小程序中无法在模板上调用 JS 方法,本质上是利用计算属性 Computed 转换好语言,然后利用模板插值在小程序模板中使用。

模板中:
<view>{{ message.hello }}</view>

JS里需要写:

 computed: {  
    message () { return { hello: this.$t('message.hello') }
    }
  }

因此该方案存在一个性能问题,最终的渲染层所看到的文本还是通过 setData 跨线程通信完成,这样就会导致线程间通信增多,性能开销较大。

并且,早期这种形式使用成本较高,后来 uniapp 也针对其做过优化,实现了可以在模板上写 $t() 的能力,使用上方便了不少。

这个 t() 的实现是在编译时候识别到t 就自动替换,帮你替换成一个 uniapp 的 computed 数据,因此数据部分还是和之前一样要维护两份。尤其是模板上的for循环,即使 for 里只有一个数据要被转换,整个列表都要被替换成一个计算属性,在线程间通信时进一步加大了性能开销。

微信官方的方案

微信小程序本身也提供了一个 i18n 的方案,仓库地址是:wechat-miniprogram/miniprogram-i18n 。

这个方案从 i18n 本身的实现来讲和Mpx框架的设计是类似的,也是基于 WXS 实现(英雄所见略同啊)。但因为周边配套上没有完整的体系,整体使用体验上就也略逊于基于Mpx框架来开发支持 i18n 的国际化小程序了。

主要的点就是,官方提供的方案,要基于 gulp 工具进行一次额外构建,同时在JS中使用时候还要额外引入一个 behavior 去让JS中也可以使用翻译能力。

而Mpx框架通过一次统一的Webpack构建产出完整的内容,用户无需担心语言包更新后忘记重新构建,在JS中使用的时候不光更方便,而且语言信息还是个响应式的,任何组件都可以很方便地监听语言值的变化去做一些其他的事情。

最后,Mpx的 i18n 方案对比微信官方的方案还有个巨大的优点,结合Mpx的跨平台能力,能实现均以这个方案,一套代码产出支持微信/支付宝/百度/QQ/头条多个平台的支持 i18n 的小程序。

总结

Mpx 框架专注小程序开发,期望为开发者提供最舒适的开发体验,有众多优秀的功能特性,帮助开发者提效。本文介绍的是其内置的 i18n 能力,通过对比分析得出相比其他框架方案在使用成本和性能等方面有明显的优势,欢迎各位有相关需求的同学进行体验尝试。

未来 Mpx 还会持续迭代优化,提供更多更好的能力帮助小程序开发者提效。在使用过程中遇到任何问题,欢迎大家在 Git 上提 issue,团队成员会及时响应。同时也鼓励大家一起为开源社区做贡献,参与到 Mpx 共建中来,为小程序技术发展添砖加瓦。

Git地址 [https://github.com/didi/mpx]
Mpx文档 [https://mpxjs.cn/]

欢迎技术交流与反馈,顺便star一下鼓励开源项目贡献者,我们将持续发力贡献社区。

附:以往Mpx文章链接
滴滴开源小程序框架Mpx - https://mpxjs.cn/articles/1.0.html
滴滴小程序框架Mpx发布2.0,支持小程序跨平台开发,可直接转换已有微信小程序 - https://mpxjs.cn/articles/2.0.html
小程序开发者,为什么你应该尝试下MPX - https://mpxjs.cn/articles/mpx1.html
Mpx 小程序框架技术揭秘 - https://mpxjs.cn/articles/mpx2.html

滴滴出行小程序体积优化实践 - https://mpxjs.cn/articles/size-control.html

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

日期排版没灵感?我总结了10套排版案例

资深UI设计者

版式设计在我们的设计中是非常重要的技能,无论是UI设计还是平面设计,都会运用到版式设计相关的知识,在版式设计中最常见的就是图文排版、文文排版。一张图片一段文案在不同的需求情况下我们都可以排版出很多种样式,每一种样式展现出来给人的感觉也是不一样的,美的排版总是会使人眼前一亮,也会使整体的设计更耐看。

排版也是会根据重要程度划分层级,我们都知道主题文案都需要醒目,让人一眼就能看到,这样才能达到宣传的作用,当然仅仅只是展示主题文案也是远远不够的,达到主题排版,主图排版,小到副标题排版,我们都需要精心的排版,还可以更精细到小到辅助文案以及图形的排版,而今天我们就来看一下日期这样的文案我们可以怎么排版呢?

日期在一些重要的活动中也是比较重要的信息,比如展会时间,我们需要突出时间,不能用极小的文字排版在角落,用户不注意的地方,这样会给人一种焦虑的情绪,既然是展会活动,那么用户关心的是展会的主题是什么?活动时间是什么时候?活动地址在什么地方?所以这些重要的信息就需要重要突出。而在一些做纪念性的日期我们就可以小化(例如我自己记录自己的学习打卡练习)

案例分享

我们常见的日期有年、月、日、时、分、秒,接下来我们就通过对日期的展现做一些不同的排版方式,通过与日期的普通排版方式做对比,我们就可以看出微小的日期排版对整体的设计展现也是有很大影响的。

简单的日期排版我们通常就只是将年月日对齐排版就算完成了,但是这样的排版方式会影响整体画面的美观,我们对于小文案也需要花一定心思去整理以及排版出更精细的样式,这样给用户的感觉就会觉得你的每一步设计都是用心设计的,并且为了整体的美观,我们 也不得不从细微之处出发。

日期排版01

例如下面对于日期的排版,TIME这个文案有时候我们也可以去掉,因为用户看到时间就会明白这是什么,在一定的情况下也是可以去掉的,当然有时候为了整体页面的展示效果,我们也可以加上,便于排版,左边只是将年、月、日并排,时间节点作为一个点排列,下面的文案我们可以根据实际情况选择一些特殊的提示文案做装饰

而通过对左边简单的日期排版进行改版后,我们会发现右边的日期排版会显得更美观,排版更精妙,也有更多的细节之处,例如2020后紧接着年(YEAR)的提示,08后面标识是周六(SAT.),年月日和时间节点也同时做了层次区分,这样更有利于阅读。

日期排版没灵感?我总结了10套排版案例

日期排版02

对于上面同样的日期文案,我们还可以排出右边不同的样式,整体采用横排的方式,将年、月、日同排,时间段缩小处理,使时间之间也能有层次感

日期排版没灵感?我总结了10套排版案例

日期排版03

下面的日期是年、日期段、时间段的组合,左边的排版显然是比较常规的分层排版,却主要突出了2020,而一般时间我们在这一年将要发生的事,我们更关心的是哪一天那个时间点,而右边的排版主要突出时间段/点,更能让用户看到自己关心的事件。

日期排版没灵感?我总结了10套排版案例

日期排版04

下面这一组日期是有不同年份的,所以我们在排版的时候可以突出显示年份,这样在排版的时候就可以注意层级关系,排除层次感

日期排版没灵感?我总结了10套排版案例

日期排版05

这一组日期是比较简单的,只有一个时间点,没有时间段,如果直接按照左边这样的日期排版方式,显然整体看着就很单薄,把这样的日期排版方式融入到版式整体画面中,也一定会显得毫无设计感,而我们只需要将简单的日期经过简单的排版,从年、月、日、时,从上至下依次排列,这样就可以显得信息有层次感,并且阅读也不会有困惑,加上精致的icon做装饰,这样的日期排版就显得更耐看。

日期排版没灵感?我总结了10套排版案例

日期排版06

这一组日期也很简单,只有月、日、时,都是属于时间段的信息,通过分析这个时间,月都是10月,是相同的,所以我们可以将月份单独拿出来,作为共用信息,这样就可以精简画面重复的信息,依然采用月、日、时这样从上至下的顺序排列,时间小化,但是利用色块突出,也不会柔化时间点的阅读,再通过一条线的连接,将斜线和时间icon相连,形成一个有趣味性的时间装饰,这样的排版更容易吸引用户的眼球

日期排版没灵感?我总结了10套排版案例

日期排版07

下面的日期也是年、日期段、时间段的组合,和第三个日期排版的案例类似,所以存在同样的问题,左边的排版显然是比较常规的分层排版,却主要突出了2020,右边改版后,我们同样弱化年份(2020),提取相同的月份(8月),突出显示日期

日期排版没灵感?我总结了10套排版案例

日期排版08

这一个和第五个也是一样的,左边都是年、月、日、时的时间点,没有时间段,第五个我们是采用竖排的方式,而这里我们改版后采用的是横排的方式,突出显示月、日,让整体的层次更加清晰

日期排版没灵感?我总结了10套排版案例

日期排版09

下面这一组时间改版,我们主要采用错位竖排的方式,像这样的排版方式,我们可以多用于一些比较有设计感或者比较唯美的画面中,显得每一个小的点,都有用心设计,并且也符合这样的气质

日期排版没灵感?我总结了10套排版案例

日期排版10

这一组日期只有年、月、日。左右两边的排版看起来很相似,但是通过对细节的调整,例如2020的弱化,间距的把控,星期几的友好提示,这样就会使整个日期排版看起来更精细、耐看。

日期排版没灵感?我总结了10套排版案例

案例实操

我们通过对上面日期的排版分析和总结,会发现小小的日期排版也是很关键也很追重要的,所以下面我们将通过一张海报案例,来真正体现日期排版对整体画面的重要性。

海报主题是选择的立秋,虽然立秋以及过去两天了,但是我又学会了这个立秋新的排版技巧,所以我想将这一技巧分享出来,但是这里就不详细讲解海报的设计过程了,主要还是分享日期排版对整体画面的影响作用

这里就简单的说一下海报设计的思路,海报主题是立秋,所以我现在一片黄色的枫叶作为画面的主视觉,画面整体体现秋天的感觉,一片黄灿灿的画面,给人感觉就像是秋天到了,画面元素简约,只选择了一片枫叶加上它的投影,体现空间感,主题文案排版在枫叶上,与枫叶融为一体,这样用户得分第一视觉就会被主图吸引,同时看到主题相关文案,下面的其它文案通过从|秋|字垂落的竖线,分别右对齐以及左对齐,显得画面规整

日期排版没灵感?我总结了10套排版案例

第一张海报的日期排版就是采用普通常规的排版方式,我们会发现这样的日期排版方式,在整个画面中会显得有点僵硬,并且左右两边不对称的关系,会显得右边偏轻,使画面的平衡感缺失,也正是日期的排版太粗糙的原因,导致整张海报的精细度大减。

日期排版没灵感?我总结了10套排版案例

样机效果

日期排版没灵感?我总结了10套排版案例

我们保持其它元素以及排版都一致,只改变日期的排版方式,我们就会发现右边的海报整体给人的感觉更精美,平衡感更强烈,所以我们在做设计的时候不要忽略每一个点。将每一个点都细心的设计,这样的作品才会更耐看。

总结

版式设计是我们设计中最基本的知识,我们在做设计的时候,通常会注意主题主图的排版,而经常会忽略哪些不是很重要的信息,但是我们在分析文案信息的时候,也需要考虑整体设计的目的,有时候日期信息也是非常重要的信息,所以我们在做排版的时候,也需要认真考虑日期与整体需求的关系,并且日期排版风格也会影响整体的气质。


文章来源:优设    作者:设计小余

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

微软设计负责人专访:我们是如何创造双屏设计的?

资深UI设计者

接下来的访谈翻译自微软官方博客,微软的 Office 设计部门的两位主管 Jon Friedman 和 Deepak Menon 在访谈中聊了一下 Surface Duo 背后的设计故事:

微软设计负责人专访:我们是如何创造双屏设计的?

在过去的几十年当中,数码产品制造商经常会为了适应用户的习惯和需求,来不断创造产品。我们倾向于让事物变的更小、更轻、响应更快、更具包容性。我们将不同感官融入程序,创造而优雅的产品。

随着日常生活节奏和生产力的观念变化,我们经常需要反思一个问题:如何赋予人们在创作和消费、专业和个人之间流畅切换的可能性?

即将发售的 Surface Duo 是一款独特的双屏移动设备,它有着一套专门为它的硬件所定制化的产品体验,而它的设计也折射出我们探索问题的方式。

对于设计师来说,创造这样的独特产品的机会是难得的,就像你在一个住了十几年的房子里面,发现新的房间一样。会打开的是哪扇门?会通向哪个区域?会延伸出哪些创意?

对于 Surface Duo ,我们想知道,它的两块屏幕会延伸出哪些全新的工作流程,它的接缝要如何处理,怎样减轻用户的认知负荷?

受多年来我们在用户研究上的成果所启发,我们通过软硬件结合的方式来进行 Surface Duo 的研发,让它能适合你日常的需求,还可以带来独特的体验,比如在双屏上并排打开文档。

Surface Duo 仍然处于起步阶段,我们知道,它还有很多待解决的问题,这也是为什么微软会引入更多的用户和设计师,来不断地完善它。

为了让大家更好地了解 Surface Duo 的设计历程,我们请来了 Deepak Menon ,他不仅参与了 Surface Duo 的研发和设计,还是 Office 设计团队的负责人,让他来告诉大家,Surface Duo 背后的创意、研究和设计决策。

微软设计负责人专访:我们是如何创造双屏设计的?

Jon:谢谢你能来,Deepak,在过去的2个月时间里,我们一直在非常密集地使用和测试 Surface Duo~

Deepak:实际上,我干脆是拿它单主力机,现在我都觉得我已经不需要其他的任何设备了。

Jon:我们当然会这么说,毕竟是我们设计了它。但是,我想这也证明了一件事情,就是这种拓展式的双屏,已经具备应对日常工作的能力,并且贴合大家的需求了。

Deepak:对。这不仅仅是「2块屏幕智能手机」所带来的体验,它更接近于是一款「折叠式的平板电脑」的感觉。它是新事物,尽管是通过铰链和转轴来实现这种可能性。

Jon:我们接触 Surface Duo 的时候,我们首先想到的一问题是:人类还有哪些需求是未曾被实现的?人们在达成目标过程中,有哪些问题是需要工具来弥合的?我们要如何来帮助用户达成这个目标?双屏的这种形态,让我们有重新思考生产力的切入点。

Deepak:对,尤其是在移动端的生产力上。

微软设计负责人专访:我们是如何创造双屏设计的?

在双屏界面下,使用 Office 在 PDF 文档上签名,然后使用 Outlook 发送出去,签合同的便捷操作。

Jon:确实,你的团队在中国和印度这样移动端优先的国家做了非常深入的调研。

Deepak:我们注意到很多用户在同一设备上执行并完成一系列的任务,他们需要更快地切换。同时,企业也正在倚靠我们过去认为非常「娱乐化」的媒介来进行必要的经营。

Jon:在过去,生产力有这非常清晰的定量标准,比如一秒生产多少零件。但是如今,生产力和创意息息相关,你的情绪状态和输出的内容是一样重要的。我们在不断消费又不断创造,反思和行动来回切换。其实这都涉及到一种倾向或者流程,你会按照一定的方式来处理信息,或者当你脑中突然划过一个想法的时候,你会想立刻构建或者制作某个东西,而这也需要一系列的操作和任务来支撑。

从整个数字设备的发展历程来看,双屏的设备可能是最适合处理这种带有步骤的「流程」。Surface Duo 最精巧地的地方,就在于它可以按照你的各种需求来折叠翻转和交互,可大可小,同时也是一款贴合你的口袋尺寸的设备。

微软设计负责人专访:我们是如何创造双屏设计的?

在横屏模式之下,你可以像翻书一样浏览 Word 文档

Deepak:当然,它将内容消费提升到一个全新的层次,对于丰富内容的处理,Surface Duo 更加适合和专业。在 Outlook 当中,你可以快速浏览整个星期的工作安排,在 Word 中,你可以像翻书一样阅读内容。屏幕 折叠所赋予的空间让更多的信息有了自然的展现空间。

借助 Surface Duo ,创造性的工作也得到了增强。当我使用 PowerPoint 来制作幻灯片的时候,我喜欢在一个屏幕上编辑,在另外一块屏幕上预览,两块屏幕当中,一块帮我保持专注内容制作,另一块帮我统领全局。另外,我也会在屏幕上开启多个不同的应用。

微软设计负责人专访:我们是如何创造双屏设计的?

将团队的视频通话和 PowerPoint 并列摆放,让你一边沟通一边查看内容

Jon:使用它来进行远程会议可能是我最喜欢的场景之一。我喜欢在开会的时候使用双横屏模式,将视频置于顶端,在下面的屏幕浏览文档。

Deepak:或者用另外一块屏幕来调用婴儿监视器!哈哈,疫情让我们和家庭的关系更加密切,Surface Duo 让我可以更多兼顾到家庭这边。

Jon:对,很多人认为在疫情期间,家里有这么多人,移动设备的使用量可能会降低,但是很多数据表明,情况恰恰相反(仅2月初到3月下旬,微软的 Team 移动端的用户数量就增加了超过300%)。就我个人而言,我不想一直待在一个房间里面,盯着一块屏幕,其他人也都反映,需要四处走动,或者在外面工作。当我开始使用Surface Duo 的时候,开始从中获得更为强大的支撑,获得更加有效的体验。

当然,它最优雅的还是在窗口的管理上。打开多个窗口是一种非常常见的 PC 体验,但是在单屏的移动端设备上其实还不算太普遍和舒适,但是在 Surface Duo 上则很自然。

微软设计负责人专访:我们是如何创造双屏设计的?

Outlook 中双屏带来的额外空间让你可以更快查看相关的收件箱和日历

Deepak:关于用户如何使用窗口来提高生产力,有过很多研究,并且两块屏幕之间的天然接缝,或者说转轴,其实很自然地造就了「两块屏幕」和「多窗口」的认知。在某些情况下,因为接缝的存在,在两块屏幕上打开完全不同的两个应用,其实是非常自然的事情。

在很多其他的情况下,用户可能会在一个屏幕中打开一个新的程序,打开新的界面,执行单独的操作,或者通过一个程序,在另外一个屏幕中打开下一步操作,然后再在两个界面之间来回操作,这都是非常平稳的。这种被分割开的两块屏幕,创造了一种全新的交互契机,而不是制造约束。

Jon:对于 Surface 的软硬件团队,我最为欣赏的一点,就是这种共生和互相促进的模式。使用 Surface Duo,你可以拥有更大的屏幕空间,而且拥有众多不同的使用应用的新方法,而 Surface Duo 也正好可以适应各种各样不同的使用场景。而我们在创建这个产品的过程中,想要兼顾到如此之多的场景和需求,其实是需要两个团队亲密无间地协作,才能做好。

对了,你刚刚说道关于照片、视频、语音等内容——这些输入方式的协作,对于创造性的工作到底有多重要?

Deepak:的确,在移动端设备上,摄像头和麦克风是必不可少的。我们希望最大限度地让 Office 最大限度地利用这些传感器,在移动地使用过程中进行协同。用户在通勤过程中如何参与到线上课程的互动?老师如何更快地给孩子批阅作业,家长要如何协助孩子?其实,Surface Duo 在研发探索的过程中,就有意识地在兼顾这些场景和问题。

微软设计负责人专访:我们是如何创造双屏设计的?

从媒体库当中,将媒体拖放到 PowerPoint 当中

Jon:我喜欢这些富有包容性的解决方案。人们的学习方式和工作方式通常是截然不同的,这些自适应性良好的输入模型,能够帮助能力各异的用户完成他们所需的工作。

Deepak:当我们将新的输入模型和智能化的功能结合到一起的时候,有趣的事情就开始发生了。我们几乎还没有涉及到创作方面的内容,用户就已经拥有很多契机自由发挥,他们可以轻松、清晰地借用这种交互模式来表达自己。比如可以更加顺畅地利用模板来制作精美的 Word 文档和 PowerPoint 。

微软设计负责人专访:我们是如何创造双屏设计的?

Jon:物理世界中有太多东西,我们可以将其逐渐的数字化。

Deepak:的确,将智能化的程序和多样的传感器耦合到一起,提高生产力的方式有很多——无论是提升工作效率、家庭安全性还是让内心更加平静。其实第三方开发者身上,我看到了更多思维和想法的延展,以及可能性。

Jon:对,我们已经看到很多非常有趣智能的东西了!在 Microsoft Hackathon 大会上,有人为 Surface Duo 设计了一款双人游戏,两个玩家各占一块屏幕,隔着转轴来来操作,彼此面对面,非常有趣!

Deepak:确实如此!

Jon:我们很高兴 Surface Duo 最终能够面向普通用户,我很期待它最终会在普通用户手中会迸发出怎样的创意和灵思,他们能够构建出什么样的创新软件。

Deepak:有太多值得期待的东西了 !

译者按:

微软在硬件产品上,有着丰富的翻车历史。90年代的事情太过久远姑且不说,最近十几年,出过很多比较失败的产品,比如上架仅 6 天就全线下架的时尚社交手机 Kin One 和 Kin Two,比如被支付宝团队戏称为「1%」的 Windows Phone 系统和手机,比如几乎不存在兼容性的 Surface RT 系列的平板电脑。这些硬件我全都买过,可以说全是坑。

微软设计负责人专访:我们是如何创造双屏设计的?

微软设计负责人专访:我们是如何创造双屏设计的?

这些产品单独来看是失败的,但是放在更长的时间跨度上来看,却又是微软整个生态和产品链条的构成和发展上,不可或缺的部分。Kin One 是整个 Metro 设计美学真正成型并走入移动端智能设备的里程碑(之前仅用于Zune系列播放器上),Windows Phone 则是 Windows 系统向小屏幕探索的必经之路,而 Surface RT 固然失败,但是它是带着桌面端 Windows 系统从传统 X86 架构走上 ARM 的一次大胆尝试。

微软设计负责人专访:我们是如何创造双屏设计的?

失败总是难免的,而微软这种大厂更是有着试错买单的底气。从内部设计和产品团队各自为战,到统一到一个部门来统一管理,Surface 系列产品的诞生就是分水岭,而这件事情是在 10 年发生的。

当然,在此之后翻车的产品依然会有,但是成功的概率比起更早的阶段(比如应对 iPad 诞生时,仓促推出的触摸屏PC),已经提升很多了。

如今只剩下拼硬件参数数字产品的世界简直是太无聊了。我很期待 Surface Duo 这类双屏折叠硬件能带来改变。


文章来源:优设    作者:Jon Friedman

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

你不知道的vue——vue不常用的知识点的整理

前端达人

你不知道的vue——vue不常用的知识点的整理

  1. v-cloak: 使用 v-cloak 指令可以有效解决屏幕闪动。

    有时候,页面没渲染之前就会出现vue代码块,例如下图。使用v-cloak可以很好解决这种问题。
    在这里插入图片描述

    <template> <div class="hello"> <span v-cloak>{{ content }}</span> </div> </template> <script> export default { name: "hello", data() { return { content: "测试" }; } }; </script> <style scoped> /* v-cloak这个属性会在页面渲染前作用于对应dom 在渲染完毕这个里面的样式将被移除 */ [v-cloak] { display: none; } </style>  
            
  2. keep-alive

    官网是这么解释的:

    在这里插入图片描述

    例如:可以实现页面缓存,比如从编辑页切出去再切进来,页面还是处于编辑状态.

    1. 需要在router.js中设置meta属性,meta下的keepAlive属性设置为true,代表这个页面需要进行缓存。

      import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import is from '@/view/is' import list from '@/view/list' import detail from '@/view/detail' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld, meta: { keepAlive: false, title: 'HelloWorld' } }, { path: '/is', name: 'is', component: is, meta: { keepAlive: false, title: 'is' } }, { path: '/list', name: 'list', component: list, meta: { keepAlive: true, title: 'list' } }, { path: '/detail', name: 'detail', component: detail, meta: { keepAlive: true, title: 'detail' } } ] })  
                      
    2. app.vue中修改一下代码<router-view />

      <template> <div id="app"> <keep-alive> <!--缓存组件--> <router-view v-if="$route.meta.keepAlive" /> </keep-alive> <!--非缓存组件--> <router-view v-if="!$route.meta.keepAlive" /> </div> </template> <script> export default { name: "App" }; </script> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } </style>  
                      
    3. 在详情页detail.vue中,注意beforeRouteEnterbeforeRouteLeave两个方法。

      <template> <div class="detail"> <!-- form表单,用于测试是否缓存 --> <Form ref="formCustom" :model="formItem" :label-width="80"> <FormItem label="Input"> <Input v-model="formItem.input" placeholder="Enter something..."></Input> </FormItem> <FormItem label="Select"> <Select v-model="formItem.select"> <Option value="beijing">New York</Option> <Option value="shanghai">London</Option> <Option value="shenzhen">Sydney</Option> </Select> </FormItem> <FormItem label="DatePicker"> <Row> <Col span="11"> <DatePicker type="date" placeholder="Select date" v-model="formItem.date"></DatePicker> </Col> <Col span="2" style="text-align: center">-</Col> <Col span="11"> <TimePicker type="time" placeholder="Select time" v-model="formItem.time"></TimePicker> </Col> </Row> </FormItem> <FormItem label="Radio"> <RadioGroup v-model="formItem.radio"> <Radio label="male">Male</Radio> <Radio label="female">Female</Radio> </RadioGroup> </FormItem> <FormItem label="Checkbox"> <CheckboxGroup v-model="formItem.checkbox"> <Checkbox label="Eat"></Checkbox> <Checkbox label="Sleep"></Checkbox> <Checkbox label="Run"></Checkbox> <Checkbox label="Movie"></Checkbox> </CheckboxGroup> </FormItem> <FormItem label="Switch"> <i-switch v-model="formItem.switch" size="large"> <span slot="open">On</span> <span slot="close">Off</span> </i-switch> </FormItem> <FormItem label="Slider"> <Slider v-model="formItem.slider" range></Slider> </FormItem> <FormItem label="Text"> <Input
                          v-model="formItem.textarea" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="Enter something..." ></Input> </FormItem> <FormItem> <Button type="primary">Submit</Button> <Button style="margin-left: 8px">Cancel</Button> </FormItem> <FormItem> <router-link :to="{name:'list'}"> <Button size="small" type="primary">跳转到列表页</Button> </router-link> <router-link :to="{name:'is'}"> <Button size="small" type="primary">跳转到is页</Button> </router-link> </FormItem> </Form> </div> </template> <script> export default { name: "detail", mixins: [], components: {}, filters: {}, props: [], computed: {}, data() { return { formItem: { input: "", select: "", radio: "male", checkbox: [], switch: true, date: "", time: "", slider: [20, 50], textarea: "" } }; }, watch: {}, created() { }, mounted() { }, methods: { // 重置表单 init() { this.$refs[formCustom].resetFields(); } }, // 路由进来之前,判断是从哪个页面过来的,设置不同的keepAlive属性 beforeRouteEnter(to, from, next) { if (from.name === "list") { to.meta.keepAlive = true; } else { to.meta.keepAlive = false; } next(); // beforeRouteEnter不能通过this访问组件实例,但是可以通过 vm 访问组件实例(刚开始错误写法) // next(vm => { //     if (from.name === "list") { //         // 在这里修改keepAlive值,是不能缓存数据的,因为在next()里面的代码,是在vue挂载之后执行,处于activated之后,此时activated中keepAlive还是false //         vm.$route.meta.keepAlive = true; //     } else { //         vm.$route.meta.keepAlive = false; //     } // }); }, // 路由离开之前,判断去往哪个页面,设置不同的keepAlive属性 beforeRouteLeave(to, from, next) { if (to.name === "list") { this.$route.meta.keepAlive = true; } else { this.$route.meta.keepAlive = false; } next(); }, activated() { // 此方法在页面缓存时会被调用(this.$route.meta.keepAlive为true时),根据路由元信息决定是否重新加载数据。不加载则是上次填写完的数据 // console.log(this.$route.meta.keepAlive); } }; </script> <style scoped lang="less"> .detail { position: relative; height: 100%; width: 100%; } </style>  
                      
  3. 插槽slot
    解构插槽 Prop:可以传递子组件的变量

    // 子组件 <template> <div class="isComponent"> <slot name='one' :childStr='childStr'></slot> <slot name='two'></slot> <slot></slot> </div> </template> <script> export default { name: "isComponent", data() { return { childStr: 'i am a child', }; } }; </script> <style scoped> </style> // 父组件 <is-component> <template #one="{childStr}">{{childStr}}</template> <template v-slot:two> two </template> <template> default </template> </is-component>  
            

    效果:// i am a child two default

  4. 强制刷新某个div

    vue实现F5刷新整个页面无空白无间隔时间

  5. 修饰符
    事件修饰符:

    1. .stop:相当于原生JS中event.stopPropagation(),阻止事件冒泡。

    2. .prevent:相当于原生JS中event.preventDefault(),阻止默认事件的发生。

    3. .capture:事件冒泡的方向相反,事件捕获由外到内。即有冒泡发生时,有该修饰符的dom元素会先执行,如果有多个,从外到内依次执行。

    4. .self:只会触发自己范围内的事件,不包含子元素。
      在这里插入图片描述

    5. .once:事件只能触发一次。

    6. .passive:事件会执行默认方法。

      注:

      1. 每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。
      2. passiveprevent冲突,不能同时绑定在一个监听器上

    按键修饰符: 去官网查看即可,这里不过多解释。Vue.js-修饰符

  6. :is: 动态组件

    优点:使代码更符合HTML语法验证

    官网是这么解释的
    在这里插入图片描述

    // 父组件: <template> <div class="is"> <table> <tr :is='is'></tr> </table> </div> </template> <script> import isComponent from '../components/isComponent' export default { name: "is", components: { isComponent }, data() { return { is: 'isComponent' }; } }; </script> <style scoped> </style> // 子组件: <template> <div class="isComponent"> <span>我是tr</span> </div> </template> <script> export default { name: "isComponent", data() { return {}; } }; </script> <style scoped> </style>  
            
  7. @click.native: 在封装好的组件上使用,要加上.native才能click。

    1. router-link 加上@click事件,绑定的事件会无效因为:router-link的作用是单纯的路由跳转,会阻止click事件,你可以试试只用click不用native,事件是不会触发的。此时加上.native,才会触发事件。
    2. 根据Vue2.0官方文档关于父子组件通讯的原则,父组件通过prop传递数据给子组件,子组件触发事件给父组件。但父组件想在子组件上监听自己的click的话,需要加上native修饰符。

    // router-link <router-link :to="{name:'detail'}" @click.native="handleNative"> <Button size="small" type="primary">测试native</Button> </router-link> // 自己封装的组件 <is-component @click.native="handleNative"></is-component>


作者:

转自:https://blog.csdn.net/a5252145/article/details/107316953?utm_medium=distribute.pc_category.427508.nonecase&depth_1-utm_source=distribute.pc_category.427508.nonecase

JavaScript专题之深浅拷贝(系列五)[转载]

前端达人

JavaScript专题之深浅拷贝

了解拷贝背后的过程,避免不必要的错误,Js专题系列之深浅拷贝,我们一起加油~

目录

一、拷贝示例

当我们在操作数据之前,可能会遇到这样的情况:

  1. 会经常改动一组数据,但可能会用到原始数据
  2. 我需要两组一样的数据,但我不希望改动一个另一个随之改动
  3. 我需要对数据操作前后进行对比

当我们遇到类似需要场景时,首先想到的就是拷贝它,殊不知拷贝也大有学问哦~

下面简单的例子,你是否觉得熟悉?

1.1 基本类型拷贝示例
var str = 'How are you'; var newStr = str; newStr = 10 console.log(str); // How are you console.log(newStr); // 10 

大家都能想到,字符串是基本类型,它的值保存在栈中,在对它进行拷贝时,其实是为新变量开辟了新的空间。 strnewStr就好比两个一模一样的房间,布局一致却毫无关联。

1.2 引用类型拷贝示例
var data = [1, 2, 3, 4, 5]; var newData = data; newData[0] = 100; console.log(data[0]); // 100 console.log(newData[0]); // 100 

类似的代码段,但这次我们使用数组这个引用类型举例,你会发现修改赋值后的数据,原始数据也跟着改变了,这显然不满足我们的需要。本篇文章就来聊一聊引用数据拷贝的学问

如果大家对Js的数据类型存在着疑问,不妨看看《JavaScript中的基本数据类型》

在这里插入图片描述

二、浅拷贝

拷贝的划分都是针对引用类型来讨论的,浅拷贝——顾名思义,浅拷贝就是“浅层拷贝”,实际上只做了表面功夫:

var arr = [1, 2, 3, 4]; var newArr = arr; console.log(arr, newArr); // [1,2,3,4] [1,2,3,4] newArr[0] = 100; console.log(arr, newArr) // [100,2,3,4] [100,2,3,4] 

不发生事情(操作)还好,一旦对新数组进行了操作,两个变量中所保存的数据都会发生改变。

发生这类情况的原因也是因为引用类型的基本特性:

  • 存储在变量处的值是一个指针(point),指向存储对象的内存地址。赋值给新变量相当于配了一把新钥匙,房间并没有换。

数组中的slice和concat都会返回一个新数组,我们一起来试一下:

var arr = [1,2,3,4]; var res = arr.slice(); // 或者 res = arr.concat() res[0] = 100; console.log(arr); // [1,2,3,4] 

这个问题这么快就解决了?虽然对这一层数据进行了这样的的处理后,确实解决了问题,但!

var arr = [ { age: 23 }, [1,2,3,4] ]; var newArr = arr.concat(); arr[0].age = 18; arr[1][0] = 100; console.log(arr) // [ {age: 18}, [100,2,3,4] ] console.log(newArr) // [ {age: 18}, [100,2,3,4] ] 

果然事情没有那么简单,这也是因为数据类型的不同。

S 不允许我们直接操作内存中的地址,也就是说不能操作对象的内存空间,所以,我们对对象的操作都只是在操作它的引用而已。

既然浅拷贝达不到我们的要求,本着效率的原则,我们找找有没有帮助我们实现深拷贝的方法。

在这里插入图片描述

三、深拷贝的方法?

数据的方法失败了,还有没有其他办法?我们需要实现真正意义上的拷贝出独立的数据。

3.1 JSON

这里我们利用JSON的两个方法,JSON.stringify()JSON.parse()来实现最简洁的深拷贝

var arr = ['str', 1, true, [1, 2], {age: 23}] var newArr = JSON.parse( JSON.stringify(arr) ); newArr[3][0] = 100; console.log(arr); // ['str', 1, true, [1, 2], {age: 23}] console.log(newArr); // ['str', 1, true, [100, 2], {age: 23}] 

这个方法应该是实现深拷贝最简洁的方法,但是,它仍然存在问题,我们先来看看刚才都做了些什么:

  1. 定义一个包含都过类型的数组arr
  2. JSON.stringify(arr), 将一个 JavaScript 对象或值转换为 JSON 字符串
  3. JSON.parse(xxx), 方法用来解析JSON字符串,构造由字符串描述的值或对象

理解:

我们可以理解为,将原始数据转换为新字符串,再通过新字符串还原为一个新对象,这中改变数据类型的方式,间接的绕过了拷贝对象引用的过程,也就谈不上影响原始数据。

限制:

这种方式成立的根本就是保证数据在“中转”时的完整性,而JSON.stringify()将值转换为相应的JSON格式时也有缺陷:

  • undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
  • 函数、undefined 被单独转换时,会返回 undefined,
    • 如JSON.stringify(function(){})
    • JSON.stringify(undefined)
  • 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
  • NaN 和 Infinity 格式的数值及 null 都会被当做 null。
  • 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。

所以当我们拷贝函数、undefined等stringify转换有问题的数据时,就会出错,我们在实际开发中也要结合实际情况使用。

举一反三:

既然是通过改变数据类型来绕过拷贝引用这一过程,那么单纯的数组深拷贝是不是可以通过现有的几个API来实现呢?

var arr = [1,2,3]; var newArr = arr.toString().split(',').map(item => Number(item)) newArr[0] = 100; console.log(arr); // [1,2,3] console.log(newArr); // [100,2,3] 

注意,此时仅能对包含纯数字的数组进行深拷贝,因为:

  1. toString无法正确的处理对象和函数
  2. Number无法处理 false、undefined等数据类型

但我愿称它为纯数字数组深拷贝

在这里插入图片描述

3.2 Object.assign()

有的人会认为Object.assign(),可以做到深拷贝,我们来看一下

var obj = {a: 1, b: { c: 2 } } var newObj = Object.assign({}, obj) newObj.a = 100; newObj.b.c = 200; console.log(obj); // {a: 1, b: { c: 200 } } console.log(newObj) // {a: 100, b: { c: 200 } } 

神奇,第一层属性没有改变,但第二层却同步改变了,这是为什么呢?

因为 Object.assign()拷贝的是(可枚举)属性值。

假如源值是一个对象的引用,它仅仅会复制其引用值。MDN传送门

四、自己实现深浅拷贝

既然现有的方法无法实现深拷贝,不妨我们自己来实现一个吧~

4.1 浅拷贝

我们只需要将所有属性即其嵌套属性原封不动的复制给新变量一份即可,抛开现有的方法,我们应该怎么做呢?

var shallowCopy = function(obj) { if (typeof obj !== 'object') return; // 根据obj的类型判断是新建一个数组还是对象 var newObj = obj instanceof Array ? [] : {}; // 遍历obj,并且判断是obj的属性才拷贝 for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = obj[key]; } } return newObj; } 

我们只需要将所有属性的引用拷贝一份即可~

4.2 深拷贝

相信大家在实现深拷贝的时候都会想到递归,同样是判断属性值,但如果当前类型为object则证明需要继续递归,直到最后

var deepCopy = function(obj) { if (typeof obj !== 'object') return; var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]; } } return newObj; } 

我们用白话来解释一下deepCopy都做了什么

const obj = [1, { a: 1, b: { name: '余光'} } ]; const resObj = deepCopy(obj); 
  • 读取 obj,创建 第一个newObj
    • 判断类型为 []
    • key为 0 (for in 以任意顺序遍历,我们假定按正常循序遍历)
    • 判断不是引用类型,直接复制
    • key为 1
    • 判断是引用类型
    • 进入递归,重新走了一遍刚才的流程,只不过读取的是obj[1]

另外请注意递归的方式虽然可以深拷贝,但是在性能上肯定不如浅拷贝,大家还是需要结合实际情况来选择。




作者: 

转自:https://blog.csdn.net/jbj6568839z/article/details/107964274?utm_medium=distribute.pc_category.none-task-blog-hot-4.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-4.nonecase&request_id=

日历

链接

个人资料

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

存档