当前位置: 首页 > 编程日记 > 正文

[转]如果我有jQuery背景,我应该如何切换到AngularJS的思维模式?

导言

stackoverflow上有一个人问了一个问题:如果我有jQuery背景,我应该如何切换到AngularJS的思维模式?

有一个回复非常经典,获得了两千多票。

为了让国内开发者也能领略到其中的核心思想,现把这个问题和答案翻译出来供大家参考。

Question

假设我已经熟悉了如何使用jQuery来开发客户端应用,我现在打算使用AngularJS。请描述一下有那些思维模式方面的东西需要转变吗?下面是举出一些具体的问题,用来帮助你回答我的这个问题:

  1. 我应该以何种不同的方式来架构和设计客户端web应用?最大的不同点是什么?
  2. 我应该停止使用哪些东西;又应该开始使用哪些东西来替代?
  3. 服务端有没有什么需要考虑或者说需要约束的地方?

PS:我不想详细对比jQuery和AngularJS之间的不同点。

Answer

1.不要预先设计页面,然后再用DOM操作去修改它

在jQuery里面,你会先设计好一个页面,然后再让它变成动态的。这是因为jQuery本身就是以混合使用的思路来设计的。基于这个简单的前提,jQuery目前已经变得臃肿不堪。

但是在AngularJS的世界中,你心中首先必须有整体架构,然后从零开始构建应用。而不是一开始的时候就去想:“我已经有了这样一块DOM结构,我想让它做×××”,你必须首先思考你到底要完成什么功能,然后再开始动手,然后再设计你的应用,最后再去设计你的视图。

2.不要混合使用jQuery和AngularJS

类似地,不要一开始就抱有这样的想法:jQuery可以实现X、Y和Z,所以我只要在上面再覆盖一层AngularJS,把模型和控制器加上即可。当你刚开始使用AngularJS的时候,这种想法实在诱人,这也是为什么我总是建议AngularJS新手彻底抛弃jQuery的原因,直到他们习惯了以“Angular风格”去做事为止。

在这里,以及在邮件列表里面,我看到过很多这种精心设计的解决方案,其中包含150或者200行代码的jQuery插件,然后他们再用一大堆回调函 数和$apply把这些插件粘到AngularJS上,这种做法非常复杂而且令人困惑不已;但是,他们最终居然能把这货弄跑起来了!这里的问题在于,在大 多数情况下,只需要很少的AngularJS代码就可以把这些jQuery插件重写一遍,然后所有事情都会突然变得简洁明了起来。

底线是:在解决问题的过程中,首先“Think in AngularJS”(以AnguarJS的方式思考问题);如果你想不到解决方案,请求助于社区;如果在尝试了所有这些方法之后还找不到简单的解决方案,然后再求助于jQuery。但是,不要让jQuery变成绊脚石,否则你永远无法真正掌握AngularJS。

3.保持以架构的角度思考

首先要明确一点,单页面应用是一种应用,它们不是web页面。所以,我们需要像服务端开发者那样去思考,而不是像客户端开发者那样思考。我们必须思考如何把我们的应用切分成独立的、可扩展的、可测试的组件。

那么,你怎么才能做到这一点呢?你应该如何以AngularJS的方式思考问题呢?下面是一些基本的原则,与jQuery做个对比。

假设有一个叫做“官方记录”(official record)的视图

在jQuery里面,我们会用编程的方式来修改视图,我们会像下面这样用ul标签来定义一个下拉列表:

<ul class="main-menu"><li class="active"><a href="#/home">Home</a></li><li><a href="#/menu1">Menu 1</a><ul><li><a href="#/sm1">Submenu 1</a></li><li><a href="#/sm2">Submenu 2</a></li><li><a href="#/sm3">Submenu 3</a></li></ul></li><li><a href="#/home">Menu 2</a></li>
</ul>

在jQuery里面,我们的应用逻辑中会像下面这行代码一样来创建这个下拉列表:

$('.main-menu').dropdownMenu();

如果我们仅仅看视图代码,我们无法立刻发现它有什么功能。对于小型的应用来说,这样做还算可以。但是对于大型应用来说,很快就会变得混乱并难以维护。

然而,在AngularJS中,视图是一种功能,它是基于视图的“官方记录”。我们的ul声明看起来就像下面这样:

<ul class="main-menu" dropdown-menu>...
</ul>

两种实现方式的效果完全相同,但是在AngularJS的版本中,每一个看到模板的人都知道它在做什么。 不管什么时候开发团队有新人进来,她看到这种代码之后就会立即明白,存在一个叫做dropdownMenu的指令,这个指令负责操控这个视图。她凭直觉就可以知道答案,而没有必要查看任何代码。视图本身已经告诉了我们这里会发生什么。这样就更加清晰了。

AngularJS新手经常会问这样的问题:我怎么才能找出某种类型的所有超链接,然后在上面加上指令呢?我们会这样回答他:你不应该这么做。然后 他总是一副惊呆了样子。你不应该这么做的原因是:这是一种半jQuery半AngularJs式的思维方式,这不科学。用这种方式思考问题永远得不到很好 的结果。你看到的应该是“官方记录”。除了指令之外(不只包括以下代码),你永远、永远、永远不应该去修改DOM。同时,指令会用在视图上,这样一来思路就清晰了。

记住:不要先设计,然后编写标签。你必须先架构,然后去设计。

数据绑定

到目前为止,这是AngularJS最赞的特性,利用这一特性可以省掉我在上一小节中提到的大量DOM操作代码。AngularJS会自动为你刷新视图,所以不需要你自己去做这件事!在jQuery中,我们会响应事件然后刷新页面内容。示例如下:

$.ajax({url: '/myEndpoint.json',success: function ( data, status ) {$('ul#log').append('<li>Data Received!</li>');}
});

对应的视图代码如下:

<ul class="messages" id="log">
</ul>

这种方式除了会把注意点混在一起之外,还有我在前面所提到的思维模式问题。但是,更加重要的一点是,这样做我们必须手动引用并更新DOM节点。同 时,如果我们想删掉一个log对象,我们必须针对DOM重新进行编码。这样一来我们如何脱离DOM来测试这些逻辑呢?同时,如果我们要修改显示效果又应该 怎么做呢?

这样有点儿乱,代码既琐碎又脆弱。但是在AngularJS中,我们可以这样做:

$http( '/myEndpoint.json' ).then( function ( response ) {$scope.log.push( { msg: 'Data Received!' } );
});

然后我们的视图代码是这样的:

<ul class="messages"><li ng-repeat="entry in log">{{ entry.msg }}</li>
</ul>

对于上面所提的删除log对象这个问题,我们可以把视图写成这样:

<div class="messages"><div class="alert" ng-repeat="entry in log">{{ entry.msg }}</div>
</div>

这里我们用Bootstrap的alert块替换了无序列表。并且我们永远不需要修改控制器代码!同时更重要的是,无论何时或者何地更新了log对象,视图都会自动**刷新。高贵优雅!

虽然我没有在这里展示,其实数据绑定操作是双向的。所以,在视图中也可以编辑log信息,只要这样做即可:<input ng-model="entry.log"/>。另外还有更多惊喜。

区分数据模型层

在jQuery中,DOM有类似数据模型的意味。但是在AngularJS中,我们有一个独立的数据模型层,我们可以按照自己的想法管理它,它和视 图层完全独立。对于前面例子中的数据绑定操作来说,这一点很有用,并且保持了注意点分离的原则,同时还可以引入更强的测试功能。在其它很多解答中都提到了 这一点,所以这里我就不再赘述了。

注意点分离

以上所有一切都是为了实现这样一个远大的目标:让你的注意点保持分离。你的视图的角色是展示“官方记录”所能进行的所有操作(绝大部分);你的数据 模型用来代表你的数据;你还有一个service层用来执行可复用的任务;你进行DOM操作并把指令混入到视图中;最后你再用controller把所有 东西粘到一起。在其它很多回复里面都提到了这一点,我唯一想要补充的一点是关于测试方面,在下面的小节中我会来讨论它。

依赖注入

用来帮助我们实现注意点分离的特性就是依赖注入。如果你是从服务端语言转过来的(例如从Java或者PHP),你可能对这个概念已经相当熟悉,但是如果你是一个前端仔,从jQuery转过来的,你可能会觉得这种概念很愚蠢、很多余、而且很装逼。但事实并非如此。

从大的层面上讲,DI意味着你可以自由地声明组件,然后在其它组件中,你可以请求所声明组件的实例,然后你就可以获得它。你没有必要知道加载顺序、文件路径,以及诸如此类的东西。这种概念的强大能量可能不是那么显而易见,这里我只举一个(通用的)例子:测试。

比方说在我们的应用中,根据应用的状态,我们需要通过一个REST API请求一个服务端的存储实现,以及本地的存储实现。当对我们的controller进行测试的时候,我们并不想和服务端进行通讯,毕竟我们正在测试的是controller而不是其它东西。我们可以仅仅添加一个虚拟的同名service作为前面所说的自定义组件,然后注射器将会保证controller能够自动获得这个虚拟的服务,我们的controller不会知道它们之间有什么不同,也没有必要知道。

关于测试再多说一点...

4.测试驱动开发---永远

这里的内容是关于架构方面的,实际上应该属于第三小节,但是这块内容极其重要,所以我把它独立成了一个单独的小节。

在你所见过、用过,或者写过的所有jQuery插件中,它们有多少个带有完整的测试用例?不是很多,因为jQuery不是太鸟这个原则。但是AngularJS非常看重这一点。

在jQuery中,唯一能够进行测试的方式通常是在一个sample/demo页面上创建独立的组件,通过这个页面我们可以进行DOM操作相关的测 试。所以,这样一来我们必须独立开发一个组件,然后再把它集成到我们的应用中去。好麻烦!在使用jQuery进行开发的时候,消耗的时间太多了,这是因为 我们选择了迭代的方式,而不是选择测试驱动开发的方式。如此一来,谁又能责怪我们呢?

但是,在AngularJS中,由于我们分离了注意点,所以我们可以用迭代的方式进行测试驱动开发!例如,比方说我们需要一个超级简单的指令,用来在菜单中显示当前的路由是什么。我们可以这样在视图中声明所需要的东西:

<a href="/hello" when-active>Hello</a>

好,现在我们来编写一个单元测试:

it( 'should add "active" when the route changes', inject(function() {var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope );$location.path('/not-matching');expect( elm.hasClass('active') ).toBeFalsey();$location.path( '/hello' );expect( elm.hasClass('active') ).toBeTruthy();
}));

我们运行这个单元测试,确认它是否会失败。然后我们再来编写指令:

.directive( 'whenActive', function ( $location ) {return {scope: true,link: function ( scope, element, attrs ) {scope.$on( '$routeChangeSuccess', function () {if ( $location.path() == element.attr( 'href' ) ) {element.addClass( 'active' );}else {element.removeClass( 'active' );}});}};
});

现在,我们的测试运行通过了,并且菜单的行为符合了我们的预期。这样一来,我们的开发既是可迭代的,也是测试驱动的。碉堡了。

5.从概念上说,指令并非打包好的jQuery

你经常会听到“只能在指令中操作DOM”之类的言论。这是必须的。请慎重对待这一原则。

我们再来稍微深入一点...

有一些指令只是用来装饰一下视图里面已经存在的内容(想想ngClass),有时候也会直接进行一些DOM操作,然后就没有然后了。但是,像 “widget”(小组件)这样带有模板的指令,它同样需要遵守注意点分离的原则。也就是说,模板自身同样需要保持很强的独立性,独立于link和 controller函数的具体实现。

AngularJS内置了完整的工具,让实现这一点非常容易;我们可以使用ngClass指令来动态更新CSS样式类;ngBind可以用来做双向 数据绑定;ngShow和ngHide可以以编程的方式来显示或者隐藏元素;诸如此类还有很多。我们也可以导入我们自己所编写的指令。换句话说,我们可以 实现各种绚丽的效果而不需要进行DOM操作。进行的DOM操作越少,指令测试起来就越容易、设置样式就越容易、在未来修改起来也会越容易、并且可复用性和 可分发性也会更好。

我看到很多AngularJS新手把指令当成容纳各种jQuery代码的场所。换句话说,他们的想法是:“既然我不能在控制器里面做DOM操作,那我就把DOM操作相关的代码放到指令里面好了”。这种做法确实是好一些了,但是通常还是是错误的

思考一下我们在第三小节里面所编写的logger应用。即使我们把相关的操作放到了指令里面,我们还是用一种“AngularJS的方式”来实现了 它。它仍然没有做任何DOM操作!在很多情况下DOM操作是必须的,但是这种情况比你想象的要少得多!当你在应用里面的任何地方进行DOM操作之前,请问 问自己,是不是真的必须要这样做。很有可能存在更好的实现方式。

下面是一个小例子,用来说明我经常看到的一种模式。我们需要一个开关型的按钮。(注意:这个例子的代码有点装逼,并且有点冗长,只是为了用来代表更加复杂一些的例子,这些例子通常是以与此相同的方式来解决的。)

.directive( 'myDirective', function () {return {template: '<a class="btn">Toggle me!</a>',link: function ( scope, element, attrs ) {var on = false;$(element).click( function () {if ( on ) {$(element).removeClass( 'active' );}else {$(element).addClass( 'active' );}on = !on;});}};
});

这段代码里面有很多错误的地方。

第一,jQuery从来就不是必须的。我们这里要实现的东西实际上完全不需要jQuery!

第二,即使我们已经在页面上引入了jQuery,也没有必要在这里去使用;对于没有使用jQuery的项目,我们可以简单地使用angular.element,这样一来我们的组件同样能够很好地运行。

第三,假设这里必须使用jQuery我们的指令才能运行,jqLite(angular.element)总是会自动使用jQuery,如果jQuery已经加载了话!所以我们不需要使用$,我们只要使用angular.element就可以了。

第四,与第三点类似,jqLite元素没有必要使用$来进行包装,传递给link函数的element已经是一个jQuery元素了!

还有第五点,这一点我们在前面的小节中没有提到,那就是我们为什么要把模板相关的内容混合在我们的代码逻辑里面?

以上指令可以重写成下面这样(即使对于非常复杂的情况同样可以改写!),改写之后代码极其简单:

.directive( 'myDirective', function () {return {scope: true,template: '<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>',link: function ( scope, element, attrs ) {scope.on = false;scope.toggle = function () {scope.on = !$scope.on;};}};
});

再说一次,模板相关的内容位于template中,所以你(或者你的用户)可以简单地切换它,从而可以满足任何必要的样式要求,同时永远不需要去修改代码逻辑。可复用性---嘭!

这样改写之后还会带来其它好处,比如测试---这是必须的!不管模板里面是什么内容,指令内部的API永远不需要修改,这样一来重构就非常简单了。你可以随意修改模板的内容而没有必要去理睬指令。同时无论你修改了什么内容,你的测试依然能够运行通过。

w00t!

好吧,如果指令并非jQuery函数之类的集合,那么它们是什么呢?实际上指令是HTML扩展。如果HTML无法做到你想实现的某件事情,你就自己编写一个指令,然后再去使用这个指令,好像它就是HTML的一部分一样。

换句话说,如果AngularJS没有内置支持某件事情,请思考一下你的团队应该怎么样去实现它,参照ngClick,ngClass等指令的做法。

小结

不要使用jQuery。最好不要引入它。它只会拖你的后腿。当你遇到一个问题,而这个问题你知道如何使用jQuery去解决,那么在你使用$之前, 请思考一下如何以AngularJS的方式去解决它。如果你不知道,去问别人!最好的解决方式十有八九不需要使用jQuery,如果你用jQuery的方 式来解决,最终会给你带来更多工作量。

原文连接:http://damoqiongqiu.iteye.com/blog/1926475

转载于:https://www.cnblogs.com/kaima/p/4242742.html

相关文章:

[微信小程序]实现一个自定义遮罩层组件(完整示例代码附效果图)

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文&#xff1a; 先上效果图: 点击按钮Show显示遮罩层,再次点击屏幕任何地方隐藏遮罩层; <button bindtap"showview">Show</button> <view class"bg" bindtaphide…

网红快餐店_在一家快餐店工作解释了AJAX基础知识

网红快餐店by Kevin Kononenko凯文科诺年科(Kevin Kononenko) 在一家快餐店工作解释了AJAX基础知识 (AJAX Basics Explained By Working At A Fast Food Restaurant) AJAX (Asynchronous JavaScript And XML) can be pretty confusing if you do not have a firm understandin…

ThinkPHP 3.2 中获取所有函数方法名,以及注释,完整可运行

<?phpnamespace Home\Controller;use Common\Controller\BaseController;class AuthController extends BaseController{/*** cc index主页面*/public function index(){$modules array(Home); //模块名称$i 0;foreach ($modules as $module) {$all_controller $this-…

减少Building 'Xxx' Gradle project info等待时间

转载请注明出处&#xff1a;http://www.cnblogs.com/cnwutianhao/p/6640279.html 从Github上看到好的Demo想要Download下来学习。导入到Android Stduio的时候经常会碰到这样的事情。。。 等了半天没反应还是这个界面&#xff0c;老子要报警了&#xff01;&#xff01;&#xf…

js表单验证,如果不为空时自动改变提交按钮的背景色

<!DOCTYPE html><head><title>js验证表单,如果表单都不为空,则按钮颜色自变,某为空时恢复原本背景色</title><script language"javascript" type"text/javascript">var a ;var b ;function chadnge(e) {a e;if(a ! &…

ux可以去哪些公司_忽略UX会如何伤害您的API以及您可以如何做

ux可以去哪些公司by Ifeoluwa Arowosegbe通过Ifeoluwa Arowosegbe 忽略UX会如何伤害您的API以及您可以如何做 (How ignoring UX hurts your API and what you can do about it) Creating experiences that users love is crucial to the success of any product. Companies in…

初识java类的接口实现

初识java类的接口实现 如果两个类之间不存在继承关系&#xff0c;且两个类都想实现同一个接口&#xff0c;两个类都必须实现接口中全部方法&#xff0c;否则报语法错误如果两个类之间存在继承关系也想实现同一个接口&#xff0c;父类如果实现了某个接口的全部方法&#xff0c;从…

KMP的next[]数组

KMP是众多字符串问题的基础 理解next数组尤为重要 next又称前缀数组 是 它所处位置的前一个位置的元素 与 该链 链首开始 几个元素相匹配(即相同) 举个实例来说明&#xff1a; next对应的是该位置的前一个元素&#xff0c; 即next[i]对应a[i-1] 因为-1头指针的存在 next均对应…

[微信小程序]手指触摸动画效果(完整代码附效果图)

微信小程序开发交流qq群 173683895 本文共有两个示例,先上图 示例一: 示例二: 示例一代码(微信小程序): // pages/test/test.js Page({containerTap: function (res) {var that thisvar x res.touches[0].pageX;var y res.touches[0].pageY 85;this.setData({rippleS…

webpack 占位符_通过示例学习Webpack:占位符图像模糊

webpack 占位符by Kalalau Cantrell通过Kalalau Cantrell 通过示例了解Webpack&#xff1a;占位符图像模糊 (Learn Webpack by Example: Blurred placeholder images) The repo that goes along with this post uses webpack 3. If you are interested in learning webpack 4,…

UIImage 各种处理(分类)

1 interface UIImage (conversion)2 3 //压缩图片到宽度10244 (UIImage *)imageCompressSizeToMin1024Width:(UIImage *)image;5 6 7 //修改图片size8 (UIImage *)image:(UIImage *)image byScalingToSize:(CGSize)targetSize;9 10 //UIColor 转UIImage 11 (UIImage *)…

Matlab随笔之矩阵入门知识

直接输入法创建矩阵 – 矩阵的所有元素必须放在方括号“[ ]”内&#xff1b; – 矩阵列元素之间必须用逗号“&#xff0c;”或空格隔开&#xff0c;每行必须用“;”隔开 – 矩阵元素可以是任何不含未定义变量的表达式。可以是实数&#xff0c;或者是复数。 – 例a[1,2;3,4] 或 …

[微信小程序]提交表单返回成功后自动清空表单的值

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文&#xff1a; 实现思路: 给每一个input绑定相同的value对象,提交成功后把这个对象赋值为空. 下面看代码: <form bindsubmitformsubmit><view><span>* </span>公司名称:&l…

xebium周末启动_我如何在周末建立和启动聊天机器人

xebium周末启动by Mike Williams由Mike Williams 我如何在周末建立和启动聊天机器人 (How I Built And Launched A Chatbot Over The Weekend) 在数小时内将您的想法带入功能性bot&#xff0c;获得真实的用户反馈&#xff0c;并在周末结束前启动&#xff01; &#xff1f; (Ta…

transition属性值

一、transition-property: transition-property是用来指定当元素其中一个属性改变时执行transition效果&#xff0c;其主要有以下几个值&#xff1a;none(没有属性改变)&#xff1b;all&#xff08;所有属性改变&#xff09;这个也是其默认值&#xff1b;indent&#xff08;元素…

[微信小程序]下拉菜单

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文&#xff1a; 动画效果是使用CSS3 keyframes 规则(使 div 元素匀速向下移动) <view class page_row><view class"nav" wx:for{{nav_title}} wx:key"index"><vi…

文件解析库doctotext源码分析

doctotext中没有make install选项&#xff0c;make后生成可执行文件在buile目录下面有.so动态库和头文件&#xff0c;需要的可以从这里面拷贝build/doctotext就是可执行程序。doctotext内置了两种检测文件类型方法&#xff1a;1、以后缀为依据检测文件类型2、以内容为依据检测文…

tmux系统剪切板_实践中的tmux:与系统剪贴板集成

tmux系统剪切板by Alexey Samoshkin通过阿列克谢萨莫什金(Alexey Samoshkin) 在实践中使用tmux&#xff1a;与系统剪贴板集成 (tmux in practice: integration with the system clipboard) 如何在tmux复制缓冲区和系统剪贴板之间建立桥梁&#xff0c;以及如何在OSX或Linux系统…

【Java面试题】54 去掉一个Vector集合中重复的元素

在Java中去掉一个 Vector 集合中重复的元素 1)通过Vector.contains&#xff08;&#xff09;方法判断是否包含该元素&#xff0c;如果没有包含就添加到新的集合当中&#xff0c;适用于数据较小的情况下。 import java.util.Vector; public class DeleteVector {public static v…

tornado+nginx上传视频文件

[http://arloz.me/tornado/2014/06/27/uploadvideotornado.html] [NGINX REFRER: Nginx upload module] 由于tornado通过表达上传的数据最大限制在100M&#xff0c;所以如果需要上传视屏文件的情况在需要通过其他方式实现&#xff0c; 此处采用nginx的nginx-upload-module和jQu…

微信小程序swiper组件宽高自适应方法

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文&#xff1a; 我把 swiper 的 width 设定成了屏幕的95%宽度, 如果想宽度也自适应的话请改成 width:{{width*2}}rpx <swiper classadvertising2 indicator-dots"true" styleheight:{{…

全面访问JavaScript的最佳资源

Looking for a new job is a daunting task. There are so many things to consider when trying to find the perfect role - location, company, job responsibilities, pay and compensation, training and much more.找一份新工作是艰巨的任务。 试图找到理想的职位时&…

Redis集群官方推荐方案 Redis-Cluster

Redis-Cluster redis使用中遇到的瓶颈 我们日常在对于redis的使用中&#xff0c;经常会遇到一些问题 1、高可用问题&#xff0c;如何保证redis的持续高可用性。 2、容量问题&#xff0c;单实例redis内存无法无限扩充&#xff0c;达到32G后就进入了64位世界&#xff0c;性能下降…

[微信小程序]单选框以及多选框实例代码附讲解

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文&#xff1a; 效果图 <radio-group class"radio-group" bindchange"radioChange"><label class"radio" wx:for"{{k7}}" wx:key"index&q…

IDL_GUI

菜单栏设计 PRO IDLGui;构建界面;显示;添加事件tlbWIDGET_BASE(xsize400,ysize400,/column,mbarmbar);实现基类fileWIDGET_BUTTON(mbar, $ &#xff1b;新建button&#xff0c;value文件)openwidget_button(file,value打开,/menu)jpgwidget_button(open,valuejpg)existwidget_…

git隐藏修改_您可能不知道的有关Git隐藏的有用技巧

git隐藏修改I have launched a newsletter Git Better to help learn new tricks and advanced topics of Git. If you are interested in getting your game better in Git, you should definitely check that out.我已经发布了Git Better通讯&#xff0c;以帮助学习Git的新技…

css 层叠式样式表(2)

一&#xff0c;样式表分类 &#xff08;1&#xff09;内联样式。 --优先级最高&#xff0c;代码重复使用最差。 &#xff08;当特殊的样式需要应用到单独某个元素时&#xff0c;可以使用。 直接在相关的标签中使用样式属性。样式属性可以包含任何 CSS 属性。&#xff09; &…

Hadoop学习笔记之三 数据流向

http://hadoop.apache.org/docs/r1.2.1/api/index.html 最基本的&#xff1a; 1. 文本文件的解析 2. 序列文件的解析 toString会将Byte数组中的内存数据 按照字节间隔以字符的形式显示出来。 文本文件多事利用已有的字符处理类&#xff0c; 序列文件多事创建byte数组&#xff0…

[微信小程序]星级评分和展示(详细注释附效果图)

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文&#xff1a; 星级评分分成两种情况: 一:展示后台给的评分数据 二:用户点击第几颗星星就显示为几星评分; <!--pages/test/test.wxml--> <view> <view>一:显示后台给的评分</…

uber_这就是我本可以免费骑Uber的方式

uberby AppSecure通过AppSecure 这就是我本可以免费骑Uber的方式 (Here’s how I could’ve ridden for free with Uber) 摘要 (Summary) This post is about a critical bug on Uber which could have been used by hackers to get unlimited free Uber rides anywhere in th…