对于一个小白来说,遇到的前端问题(1)

来源:互联网 发布:网络正常冒险岛老掉线 编辑:程序博客网 时间:2024/05/29 13:11

目录(?)[+]

1.写在前面

首先要声明一下我的立场,前端是个好东西,我希望我有。但是我之前对于前端确实不太熟悉,最近需要做一个项目,只好赶鸭子上架了。

对于前端还有很多不懂的地方,工期赶得紧,只能先能用再说,没考虑是不是正路子。下面是我最近在工程中所遇到的问题,分享给大家,也是提醒我自己。

2. js的若干问题

对于一位长期从事后端的人来说,JS的运作方式还是给我带来了很多颠覆性认识。 
但是其实主要有这么几个方面问题:

2.1. js是单线程工作

无论是有多少函数,什么样的情况下都是单线程在工作,而像回调函数那种,也不过是类似单线程操作系统中的“中断-响应”机制。

2.2. js的参数使用

js传说是基于对象的,也就是说,任何可操作的主体都是对象,当然也包括js最常见的函数也是对象,应该看过像下面的这种写法:

Fn2(); var Fn2 = function(){ alert("Hello wild!"); } 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

一个函数同样可以赋给一个变量。另外js的变量都是弱类型的,使用var可以自动转换,这点在字符型与数字型的变量中特别好用,在参数里不用声明其变量类型。那么这样子,所谓的委托,在js就变成了这样子:

function onBack(num){ alert("姗姗我来迟了"); // 执行num个耳光 } function dating(hours, callBack){ var SP= 0; // SP,愤怒值 //女猪脚在雪里站了hours个钟头 //循环开始.. SP ++; //循环结束... callBack(SP); } dating(1, onBack);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.3. js的分块写与放在一起写

这就相当于是一种作用域区分,如果同名的函数放在同一Script块下,会被覆盖掉一个,而如果分开写,则会被解析成2个不同函数。

<scripttype="text/javascript">        functionHello() {         alert("Hello");   }        Hello();      functionHello() {   alert("Hello World");    }        Hello();    </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这时候输出是两次Hello World,而不是Hello Hello World。但是如果像下面这样写的话,就达到了我们预期的效果:

<scripttype="text/javascript">      functionHello() {        alert("Hello");       }        Hello();  </script>   <scripttype="text/javascript">   functionHello() {          alert("Hello World");     }       Hello();  </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.4. js赋值函数执行与定义函数执行

首先我们来看一下赋值函数与定义函数的样子:

//“定义式”函数定义 Fn1(); function Fn1(){ alert("Hello World!"); } //“赋值式”函数定义 var Fn2 = function(){ alert("Hello wild!"); Fn2(); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

可以看到应该长得挺像的,那么他们有什么区别呢?我在做工程的项目中,发现如果是赋值式函数写错了,其实并不影响整个js,而只会影响这一个函数的输出。这是因为,如果是定义式函数,它会在执行前先编译一遍,而赋值式函数,则只会赋值,而并不会对函数本身进行预编译。

2.5 js的事件绑定问题

js中也有事件,而且确实挺像的,尤其是和C#中的事件特别类似。因为C#中的事件就是委托操作,而Java中大多使用的是监听器来进行,长得不太一样。

js的事件绑定一般就是长这样:

$('#btn').click(function () {    //点击事件发生后要做什么}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

看起来是不是和匿名内部方法一样呢?其实还有另外的事件绑定方法,我们这里就不详细谈了,毕竟我是小白。

3. bootstrap的若干问题

bootstrap可谓是不会前端样式的福音,毕竟bootstrap的意思就是自助。但是在学习上虽然可以节省大量学习的成本,但是毕竟是自助,比起专业来讲,还是差上许多,不过已经可以搭建出比较好的前端样式了。

3.1 bootstrap的栅格系统

bootstrap的最大特色在于栅格系统,这样可以在布局上省下许多功夫。我曾经就是这样以为,只需要使用class="col-md-x"就可以很好的来使用,因为一行是12个,每一个控件可以占用指定大小的部分。

但是其实是这样的,所谓的col,其实是column的缩写,既然有列了,当然应该有行了,因此row和col的搭配才能真正运用栅格系统,也就是行和列。但是这两个,都要在.Container中,不然,没有办法自动设置排列和间距。在这点上,我吃了很多苦头。

3.2 bootstrap的折叠样式使用

boostrap的另外一大特色就是丰富的js组件,可以提供一定程度上的动态效果。例如我在工程中用到的折叠样式。折叠样式如下:

<div class="panel-group" id="accordion">    <div class="panel panel-default">        <div class="panel-heading">            <h4 class="panel-title">                <a data-toggle="collapse" data-parent="#accordion"                 href="#collapseOne">                点击我进行展开,再次点击我进行折叠。第 1 部分                </a>            </h4>        </div>        <div id="collapseOne" class="panel-collapse collapse in">            <div class="panel-body">                Nihil anim keffiyeh helvetica, craft beer labore wes anderson                 cred nesciunt sapiente ea proident. Ad vegan excepteur butcher                 vice lomo.            </div>        </div>    </div>    <div class="panel panel-default">        <div class="panel-heading">            <h4 class="panel-title">                <a data-toggle="collapse" data-parent="#accordion"                 href="#collapseTwo">                点击我进行展开,再次点击我进行折叠。第 2 部分            </a>            </h4>        </div>        <div id="collapseTwo" class="panel-collapse collapse">        <div class="panel-body">            Nihil anim keffiyeh helvetica, craft beer labore wes anderson             cred nesciunt sapiente ea proident. Ad vegan excepteur butcher             vice lomo.        </div>        </div>    </div>    <div class="panel panel-default">        <div class="panel-heading">            <h4 class="panel-title">                <a data-toggle="collapse" data-parent="#accordion"                 href="#collapseThree">                点击我进行展开,再次点击我进行折叠。第 3 部分                </a>            </h4>        </div>        <div id="collapseThree" class="panel-collapse collapse">            <div class="panel-body">                Nihil anim keffiyeh helvetica, craft beer labore wes anderson                 cred nesciunt sapiente ea proident. Ad vegan excepteur butcher                 vice lomo.            </div>        </div>    </div></div>
  • 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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

这仅仅能展示出最基本的样式,但是如果细心的人可以看到,在第一部分是class="panel-collapse collapse in",而第二、第三部分则是class="panel-collapse collapse",他们分别对应着两种不同的状态:

class意义.collapse隐藏内容。c.collapse.in显示内容。

这只是状态,接下来是方法,分别是:Options、Toggle、Show、Hide,但是我目前还不太会用。我只用到了再往下的事件。事件绑定可以解决一个大问题,那就是在初始化的时候,除了展示的面板,其他面板都是被隐藏的,对于里面的元素操作可能会出现问题,例如我遇到了在里面放置echart的时候,没有办法初始化图表,这时候使用了下面的事件绑定,在面板展开后进行重新初始化图表,就解决了这个问题,它总共有4个事件:

class意义show.bs.collapse这个是只要点击就执行,执行完再执行面板展开shown.bs.collapse在CSS完成后执行,也就是面板展开后执行。hide.bs.collapse这个是只要点击就执行,执行完再折叠面板hidden.bs.collapse在CSS完成后执行,也就是面板折叠后再执行。

下面给出一个示例:

<script>$('#collapseexample').on('show.bs.collapse', function () {            alert('嘿,当您展开时会提示本警告');})</script>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

就是这么简单,当然这也是事件绑定的一种形式,使用的是jQuery的事件绑定,就像下面这样。

$('button').on('click',function(){});
  • 1
  • 1

4. 后端控制前端页面。

说到这,就不得不说这种架构,就是后端如何去控制前端页面,也就是View与Controller的关系。

成熟的话,View是依靠Model生成的,由Controller进行控制。但是通常我们不一定使用MVC架构。最新提出的MVVM(Model-View-ViewModel)架构,则是把M与V中间加一层过渡层,这样C的大部分细节操作从原来的MVP架构中P(Presenter),转移到了VM(ViewModel)中,从而可以使得界面变换更加随意与便捷,为前端开发人员提供了更加自由的开发环境,曾经的P毕竟还是绑定在IView中。二MVVM则彻底把V和P/C分离开来了。

上面说了这么多高大上的话,在我这个并不大的工程中,都用不了,毕竟我自己是小白,那么就选择了最简单的方式,直接用后端来控制前端的输出。

在Aspx中,对于页面前端控件来说,有一些是可以在后端直接获取和运行的,通常的标志就是runat="server"但是像表格(table)和列表(ol/ul/li)就没有办法进行操作。当然,可以使用数据绑定,这不是嫌太麻烦么,因此就是用了最笨的办法,输出html源码到页面文件中。

Aspx可以定义全局变量,这样前段后端都可以看到这个全局变量,总共需要两步,第一步是在页面中需要输出的部分写下这个变量,如下示例:

<%=zxInfo%>
  • 1
  • 1

这一点和jsp的输出没什么两样,第二步,则是在后端进行数据绑定:

public partial class Demo : System.Web.UI.Page{    public string zxInfo;}this.Page.DataBind();
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

这样就把前端和后端通过一个全局变量联系起来了,当然,你也可以使用Session来进行消息传递,这样就省去了绑定的过程: 
后端初始化Session

protected void Page_Load(object sender, EventArgs e)    {        Session["Zx"] = "";    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

前端使用Session

<%=Session["Zx"]%>
  • 1
  • 1

上面这两种方法里,变量里都是HTML源码,该是tr、td的就是tr、td。

5. jQuery的选择器

jQuery是对js的进一步封装,可以解决不同js引擎对于js解析的不同,而且可以简化编码者对于js的操作。尤其是以选择器为代表的一系列操作,极大的简化了dom结点操作。 
我之前就有疑问选择器里面的内容有什么区别:

$("p") //选取 <p> 元素。$("p.intro") //选取所有 class="intro" 的 <p> 元素。$("p#demo") //选取所有 id="demo" 的 <p> 元素。$("[href]") //选取所有带有 href 属性的元素。$("[href='#']") //选取所有带有 href 值等于 "#" 的元素。$("[href!='#']") //选取所有带有 href 值不等于 "#" 的元素。$("[href$='.jpg']") //选取所有 href 值以 ".jpg" 结尾的元素。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这都是很常见的选取规则,更具体的,大家可以参考一下这里: 
jquery选择器参考手册

6. canvas的width

canvas这个控件有一个非常奇怪的width,当然在代码上是有style里的width,在外面还有一个width,这两个是不同的。style里面的width是画布的宽度,而外面的width是窗口的大小。但是其实还有第三个width,那就是画本身的width,这第三个是canvas本身不能解决的,但是前两个是可以控制的,如果我们要改style里面的width,它是属于Css的,只需要使用如下代码:

$("canvas").css("width","100px");
  • 1
  • 1

但是如果要修改它本身的width,则需要使用下面这个语句:

$("canvas").attr('width', 100px)
  • 1
  • 1

这两点事不相同的,但是如果是图的宽度不符合条件,那么你需要从图生成的部分开始查起。

7. Ajax的若干问题

7.1 Ajax的跨域调用问题

Ajax的跨域问题由来已久,也是非常常见的问题,通常来讲,Ajax并不能请求别的网站的请求,那如果需要请求一个外部服务的时候,就产生了跨域问题,那么如何解决这个问题呢?

如果非要使用Ajax,使用jsonp可以解决这个问题,但这需要修改服务端代码,但是如果服务的代码是封装好的,你没有办法或者没有权限修改的时候,这时候就需要Jquery-jsonp插件,这个插件可以解决跨域问题而且不用修改服务端代码。

具体的大家可以看一下jsonp的使用。

7.2 Ajax中的回调函数

Ajax的回调函数也是一个新事物,我们在前面讲过js是单线程的,那么回调函数其实相当于委托事件,当程序执行完毕后,接下来如何处理返回的结果,就是回调函数所要做的事情,Ajax相当于一个发收过程,发送的事件Ajax自动做好了,不用程序员自己处理,但是收的过程需要自己来进行处理。

这和java与C#不同是因为,js一旦进行Ajax操作,就相当于是异步加载,等同于创建了一个线程,那这时候,主程序就失去了对于这个线程的实际控制权,也就是不会知道它什么时候停止,然后再做相应的事情,而回调函数就是主程序派给Ajax请求的一个接收员,等Ajax请求完毕收到返回值的时候,就由接收员来处理接下来的事情。这应该理解了。

0 0
原创粉丝点击