- 小程序原生高颜值组件库--ColorUI
[图片] 简介 ColorUI是一个Css类的UI组件库!不是一个Js框架。相比于同类小程序组件库,ColorUI更注重于视觉交互! 浏览GitHub:https://github.com/weilanwl/ColorUI [图片] 如何使用? 先下载源码包 → Github 引入到我的小程序 将 /demo/ 下的 colorui.wxss 和 icon.wxss 复制到小程序的根目录下 在 app.wxss 引入两个文件 [代码]@import "icon.wxss"; @import "colorui.wxss"; [代码] 使用模板全新开发 复制 /template/ 文件夹并重命名为你的项目,微信开发者工具导入为小程序就可以使用ColorUI了 体验沉浸式导航 [图片] App.js 获取系统参数并写入全局参数。 [代码]//App.js App({ onLaunch: function() { wx.getSystemInfo({ success: e => { this.globalData.StatusBar = e.statusBarHeight; let custom = wx.getMenuButtonBoundingClientRect(); this.globalData.Custom = custom; this.globalData.CustomBar = custom.bottom + custom.top - e.statusBarHeight; } }) } }) [代码] Page.js 页面配置获取全局参数。 [代码]//Page.js const app = getApp() Page({ data: { StatusBar: app.globalData.StatusBar, CustomBar: app.globalData.CustomBar, Custom: app.globalData.Custom } }) [代码] Page.wxml 页面构造导航。更多导航样式请下载Demo查阅 操作条组件。 [代码]<view class="cu-custom" style="height:{{CustomBar}}px;"> <view class="cu-bar fixed bg-gradual-pink" style="height:{{CustomBar}}px;padding-top:{{StatusBar}}px;"> <navigator class='action border-custom' open-type="navigateBack" delta="1" hover-class="none" style='width:{{Custom.width}}px;height:{{Custom.height}}px;margin-left:calc(750rpx - {{Custom.right}}px)'> <text class='icon-back'></text> <text class='icon-homefill'></text> </navigator> <view class='content' style='top:{{StatusBar}}px;'>操作条</view> </view> </view> [代码] 自定义系统Tabbar [图片] 按照官方 自定义 tabBar 配置好Tabbar (开发工具和版本库请使用最新版)。 使用ColorUI配置Tabbar只需要更改 Wxml 页的内容即可。 更多Tabbar样式请下载Demo查阅 操作条组件。 /custom-tab-bar/index.wxml [代码] <view class="cu-bar tabbar bg-white shadow"> <view class="action" wx:for="{{list}}" wx:key="index" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab"> <view class='icon-cu-image'> <image src='{{selected === index ? item.selectedIconPath : item.iconPath}}' class='{{selected === index ? "animation" : "animation"}}'></image> </view> <view class='{{selected === index ? "text-green" : "text-gray"}}'>{{item.text}}</view> </view> </view> [代码] 作者叨叨 ColorUI是一个高度自定义的Css样式库,包含了开发常用的元素和组件,元素组件之间也能相互嵌套使用。我也会不定期更新一些扩展到源码。 其实大家都在催我写文档,但这个库源码就在这,所见即所得,粘贴复制就可以得到你想要的页面。当然,文档我还是要写的,也希望大家多多提意见。 现在前端的开发方向基本都是奔着Js方向的,布局和样式大家讨论的有点少。以后我会在开发者社区多聊一聊关于开发中的布局和样式。 [图片] 感谢阅读。
2019-02-26 - Fiddler实现微信授权开发调试
一、下载、安装Fiddler https://link.jianshu.com/?t=https%3A%2F%2Fwww.telerik.com%2Ffiddler 二、微信授权调试 案发现场: 某天,一名正儿八经的开发"猿",在疯狂一顿Coding之后,他完成了微信授权登录功能的编码。下来他想先在本地调试一下,然后再部署到线上环境。于是在本地Run起了Project,假设微信回调的地址是:localhost:9002。这时,他就可以利用Fiddler进行代理测试,具体操作实现请参考以下两种方法。 PS: 请先自行登录微信公众平台进行相关配置。 Fiddler + 微信web开发者工具 打开微信web开发者工具,选择公众号网页开发: [图片] 修改Fiddler中的Hosts配置信息( Fiddler 的 Tools > HOSTS修改host配置) host修改参考https://blog.csdn.net/liguilicsdn/article/details/51286623 [图片] 完成以上配置,即可利用微信web开发者工具在PC本地进行微信授权调试,就这么简单。 Fiddler + 手机(需结合方法1的配置操作) 确保手机、电脑在同一个局域网,查看PC的ip地址 [图片] Fiddler代理配置 [图片] [图片] 手机代理信息配置 [图片] [图片] 完成以上配置,即可使用手机进行微信授权(可自行构造请求微信授权),微信回调后会走PC运行的项目接口,大概就这么简单。 三、推荐两个小工具 内网映射工具(第三种调试方法,具体请参考在线教程):NATAPP https://natapp.cn/ Hosts修改软件:SwitchHosts https://oldj.github.io/SwitchHosts/ 使用eclipse+fiddler+微信web开发者工具调试本地微信页面推荐文章 http://www.cnblogs.com/Gabriel-Wei/p/5981028.html
2019-03-06 - 纵观JS对象的“简”与“繁”(下)
上篇文的最后,我们聊到了JS对象的一个重磅成员——原型模式,本以为迎来了对象领域的终极大boss,却发现它仍然存在局限性,这种局限就是: 不需要共享的也会被共享,导致出现期望之外的结果。 什么不需要共享?比如,如果我们这样操作: [代码]function Person(){ } Person.prototype.friends=["1","2","3","4"]; var person1 = new Person(); var person2 = new Person(); person1.friends.push("5"); alert(person1.friends); alert(person2.friends); [代码] 会输出什么?你应该猜对了,两个都是 [代码]1,2,3,4,5 [代码] person2需要friends么,不一定,他需要push进来一个新的“5”吗?也不一定,那么在完全被动的情况下,因为我们把friends定义在了原型里,且由于person1对其进行了操作,就同时影响到了person2,显然,这是不合适的。 怎么破? 当我们进行了代码的简化,作用域的优化之后,似乎仍有进一步改善的空间。要么是纯粹的私有,要么是纯粹的共享,有中和的方式吗? 构造函数和原型组合模式 看到这里,你脑海中是否闪过一个念头——“我早该想到的!”。 没错,既然他们一个那么自私,一个那么大方,把它们结合起来不就有所平衡了么? 看代码: [代码]function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.friends = ["lili","lucy"]; } Person.prototype = { constructor : Person; sayName : function(){ alert(this.name); } } [代码] 这段代码,既让每个实例都有自己的一份属性副本,同时又共享着对方法的引用,是现在使用最广泛的方式,最大限度地节省了内存。 其实这里,相比具体的方案,我们更应该重视一个思路,就是“组合”,我们常常面临方案的选择,选A,或者B,或者C,多数情况下,每种方案都有其优点和局限性,而组合使用不失为一种“两全”之策。 but,虽然功能上它是兼备的,并不能说它是完美的。 回想一下,前面我们看到过的,直接创建对象也好,对象字面量也好,或者构造函数、原型模式,我们都倾向于去使其具有封装性,而这里它们却是相互独立的,能否将其封装起来呢? 动态原型模式 所谓动态原型,似乎不太好理解,不论是书籍还是网上能够查到的文章,大都简单罗列,而没有解释得很清楚,我反复看过一些代码和短文,下面是我的理解。 其实这个模式是在“构造函数和原型模式”的基础上做了两个方面的改良,看代码: [代码] function Person(name,age,job){ this.name = name; this.age = age; this.job = job; if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); } } } [代码] 一、封装,sayName没有单独放在函数的外部,而是内部。 二、创造私有实例的时候,去判断某个需要的共有方法是否已经存在,因为你可能已经在别的地方创建过了,而这种共有的方法只需要创建一次即可,如果有,忽略此段,没有,则对其初始化,避免时间和空间的浪费,动态体现在这里,从用意上来看,应该是一种预判,并不是共享方法这样写有什么好处。 需要注意的一点是:在这种模式下,不宜使用字面量重写原型,因为在已经创建了实例的情况下重写原型会切断现有实例和原型之间的联系。 到了这里,有关对象的高潮似乎已经过去,其实除此之外,还有两个“小”角色值得我们关注: 寄生构造函数模式 《高程》上说,在前面几种模式都不适用的情况下,使用这个模式,我觉得这么说有点不负责任,这样说等于没交代它的使用场景,有敷衍之嫌,不知道是原文的问题还是翻译的问题,或者是篇幅所限,暂且不管。 不妨顾名思义,分拆来看: 寄生:对某个东西有所依托 构造函数:用起来像构造函数 上代码: [代码]function Person(name,age,job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } var friends = new Person("alien",29,"teacher"); friends.sayName(); [代码] 你没看错,我也没写错,这里,除了创建实例的时候用了new操作符之外,它和工厂模式一模一样… 它看起来是个函数,但这个函数只起到封装作用,执行的结果是将在其中创建的对象给返回出来。 这种模式(就目前研究)主要是可以用来给一些内置构造函数增加新的方法,大家都知道,构造函数的属性和方法是可以改的,但直接改原生方法是不推荐的,那么寄生模式就派上用场,比如这样: [代码]function SpecialArray(){ var values = new Array(); values.push.apply(values, arguments); values.toPipedString = function(){ return this.join("|"); } return values; } var a = new SpecialArray(2,6,8,9,4); document.write(a.toPipedString()); [代码] 上面这段代码输出的值将会是: [代码]2|6|8|9|4 [代码] 而正常情况下,都会输出 [代码]2,6,8,9,4 [代码] 也就是说,根据个性化需要改变了数组的输出方式。 上面提过,“寄生”是一种依存关系,它是给已经存在的东西添加“功能”。 这么说你应该已经有大概的理解了,但到这一步我并不是很满意,感觉还可以挖掘出更多东西,如果你看到这篇文章,并且有不同的意见或者看法,欢迎交流。 稳妥构造函数模式 稳妥,听起来就很保守,也意味着安全。 先看代码: [代码]function Person(name,age,job){ // 创建要返回的对象 var o = new object(); //私有变量和方法 //添加方法 o.sayName = function(){ alert(name); } //返回 return o; } [代码] 稳妥构造函数的两个特点: 1、没有公共属性 2、方法不引用this的对象 这种模式是在某些禁用了this和new的环境下可使用的。 最后这两种模式,使用的场景较少,知道就好,重点还是前面那些方法的练习和运用。 总结 写这两篇文章,是因为“对象”这个东西一直都像是难啃的骨头,但其实任何显得复杂或者困难的东西,都是从简单慢慢演变而来的,如果循序渐进地加入一些有血有肉的思考,就能更容易地对其进行理解和记忆。 写文过程中,我尽量做到不生搬概念,加入个人的思考过程,但认知有限,不足在所难免,还望读者朋友不吝赐教。 后面还会继续跟大家一起啃硬骨头,下次见!
2019-03-11 - 纵观JS对象的“简”与“繁”(上)
JS这门语言,曾被不少开发者视为玩乐的语言,没有厚度和技术含量的语言,但发展到现在,想必没有人敢再这么说,它能做的事越来越多,所以,这门语言看似知识结构简单,但却在代码的行与行之间藏着很多细节和玄机。 “对象”在JS中是个很有意思的东西,它随处可见,说简单可以很简单,但也可以复杂到让人头皮发麻。 简单 如何简单? [代码]var person = new Object(); [代码] 这样就可以创建一个名为“person”的对象。 但事实上,没有人会在意它的简单,因为简单的东西往往承担不了重任。 所以,我们可以从另一个角度去理解它的复杂,就是强大——每一种形式,每一个特性,都为了解决更多问题而生。 复杂 像上面那样,我们可以轻松创建一个对象,进一步,为其添加一些属性和方法: [代码]person.name = "idea"; person.age = 18; person.run = function(){ alert("I can run!"); } [代码] 但其实这里我们就会发现需要写很多的“person”,代码不够简洁。 可以进行如下改进,也就是另外一种写法——“对象字面量”: 对象字面量 [代码]var person = { name : "idea"; age : 18; run : function(){ alert("I can run!"); } } [代码] 它有两个优点:简化代码、凸显封装性。 如果你对js不熟,但对css预处理还算熟悉,这就像是less或者sass的嵌套。(后面更深入的东西我还会拿css类比,以帮助理解。 由此,我们可以像这样创建对象: [代码]var person1 = { name : "tom"; age : 18; run : function(){ alert("I can run!"); } } var person2 = { name : "lili"; age : 16; run : function(){ alert("I can run!"); } } ... [代码] 但其实我们好像又发现一点不那么好的地方,这样以来,我们每创建一个新的实例,都要写这么一大块的代码,显然是冗余的,于是,有人发动脑筋,想了一种办法——“工厂模式”。 工厂模式 对于工厂模式,可以这么理解,我们需要制作100个同类的产品,但不需要为每件产品都弄一个模子,而是一个模子可以反复用,生产很多很多产品。 代码就像这样: [代码]function createPerson(name, age, job){ var o = new object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } var person1 = createPerson("tom",18,"teacher"); var person2 = createPerson("lili",16,"doctor"); [代码] 这段代码的亮点在最后,我们可以只用一行代码就创建一个对象,并赋予其属性值。 看起来很不错,但它存在一个难以觉察的不足——我们好像无法获知这个对象的类型。 这么说其实并不准确,每个对象都有其类型,大不了是Object,但这个结果给不了我们更有价值的东西。所以,要引荐出一个对象世界里的重要角色——“构造函数”。 构造函数 先看代码: [代码]function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } }; var person1 = new Person("tom",18,"teacher"); var person2 = new Person("lili",16,"doctor"); [代码] 从面上看,这段代码跟上面那段有这么几点不同: 没有显式创建对象 属性和方法直接给了this 没有返回 创建新实例的时候,使用了“new”关键字 名称首字母大写 为什么说它重要,上面我们只是创建了一个自定义的构造函数,其实js当中有很多内置的构造函数,我们会无数次地使用,比如Array、Date、String等等。 构造函数和普通函数有什么不同?好像只是首字母大写? 这么说也没错,它可以当做普通函数使用,就像这样: Person(“tom”,18,“teacher”); 但当它被这样使用了之后,就是作为构造函数: var person1 = new Person(“tom”,18,“teacher”); 会经历完全不同的过程。 构造函数看起来很好用,但它还有需要改进的地方吗?往下看。 上面那段代码里,有这么一行: this.sayName = function(){ alert(this.name); } 它会为新创建的实例新建一个sayName方法,别忘了,方法是赋予对象的函数,函数本身也是对象,所以,person1和person2是两个不同的对象实例,同样,它们的sayName方法也不同(虽然看起来是一个样子)。 这样以来,name、age和job都共用了,完成同样任务的方法却没有共用,每一个新的实例都会创建一次,显然,这不是最理想的,有办法解决吗? 我们可以做这样的尝试: [代码]function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; }; function sayName(){ alert(this.name); } var person1 = new Person("tom",18,"teacher"); var person2 = new Person("lili",16,"doctor"); [代码] 和之前的区别就在于,我们把sayName方法提到了函数体的外面,意味着,它是个全局的函数,而不属于某一个。 这个时候,你会发现一个有趣的现象,如果你写下这么一行代码: alert(person1.sayName() == person2.sayName()); 它会弹出三个值:“tom、lili、true”。 首先是里面两个分别执行,然后是外层,这说明,它们俩共用了同一个,不需要担心多余创建的那个函数实例。 终于皆大欢喜! 可是…慢着,好像哪里不对? 你可能记得,说对象字面量的时候,我们提到了封装性,你会发现,这里的sayName方法在函数体的外部,如果有很多个,就会有很多个方法散落在外部,这感觉很糟,这不是我们要的,so,必须找到一个办法解决它,就像上面做的那样。 原型模式 我们终于迎来了这个重磅的概念,关于这个概念,往往让人觉得是复杂的,抽象的,高深莫测的,其实并不,让我们来看看它具体的表现: [代码]function Person(){ } Person.prototype.name = "alien"; Person.prototype.age = "23"; Person.prototype.job = "teacher"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); [代码] 我们创建一个函数,但里面什么都没有。 接下来用到了“prototype”,其实每个函数都有一个prototype属性,这个属性是一个指针,所谓指针,就是建立A和B相关联的一个中介,prototype指向一个对象,这个对象,可以为我们提供所有同一类型实例能够共享的属性和方法,听起来是不是很熟悉?——它能为我们带来前面提到的所有。 但这么说似乎仍然不好理解,所以,你应该对CSS很熟悉,prototype,就相当于为所有可能的子元素,提供了一个父元素,这个父元素的所有属性,都能为子元素所共享,同时,它也不限制子元素的行为。 即,person1和person2具备Person.prototype所指对象的所有属性和方法,并且能够对其进行覆盖或者添加自身特有的新属性和方法。 看到这,我们是不是应该准备欢呼“大结局”了呢?的确,已经有不少内容了,可是,事情从来都不像我们想想的那么简单。 来思考一下,原型虽好,但它是否让我们走向了另一个极端?所有的属性和方法我们都需要共享吗?往往并不是,很多时候,对于某个属性,我们只需要私有即可,而不必共有,那么,什么样的属性私有更合适?既具备私有,又能共有的方案,存在吗? 想知道答案,且看下回分解~ 纵观JS对象的“简”与“繁”(下)
2019-03-11