Visual Studio+JavaScript 的前后端调试方法你真的会了么?

2021-05-08 11:23:12 浏览数 (1)

对于.NET 的后端工程师来说,Visual Studio 是一款必须要掌握的 IDE。对于前端工程师来说,Javascript 是前端开发过程中必不可少的使用语言。但是,对于很多刚入门的程序员,或者已经入坑几年的所谓的有经验的程序员仍然在开发过程中,因为不知道、或者了解较少的调试技巧,调试方法,导致无法在项目开发过程中快速有效的开发, 或者无法在使用第三方框架的情况下,很好的阅读源码,导致没有办法很好的理解对应的实现过程,所以本 Chat 总结相关的调试技巧和学习方法。

在本场 Chat 中,会讲到如下内容:

  • Visual Studio 的常见调试方法
  • Javascript 的常见调试方法
  • 学习并引用第三方的 C#开源项目,ServiceStack.Redis
  • 学习并引用第三方的 Javascript 插件,Swiper.js

适合人群:需要高效调试项目和学习第三方开源项目的技术人员

在工作过程中,笔者发现有很多同学,或者是刚毕业的,或者是已经上班了好几年了都或多或少的对 C#的调试方法,或者是 JavaScript 的调试方法,掌握的不够。在这种情况下, 它就会影响调试的效率。不同的调试方法大同小异,如果选择一个更加合适的方法去调试,能够在单次调试中能够节省几秒钟,几分钟,乘以每天调试的次数,可能能够节省出很可观的时间。

下面直接介绍具体的执行过程。

Visual Studio 的常见调试方法

使用 ASP.NET MVC 应用程序的项目模板,如下图:

如下介绍三种调试方法

使用 IIS Express

让我们来正式认识一次,IIS Express,可能你知道它是干什么用的,但是从未了解过它的官方解释。

(图片来自:https://docs.microsoft.com)

从这一段描述中看出 IIS Express 对应的三个特点。

lightweight:轻量级

self-contained:独立的

optimized for developers:为开发人员优化的

在使用 IIS Express 调试的时候比较方便,直接点击 IIS Express 就能够启动调试,类似于 Eclipse 中的小蜘蛛。

点击后会直接启动浏览器,并打开对应端口的主页。

在任务栏中能够看到多处的 IIS Express 的小图标:

在 IIS Express 上鼠标点击右键会出现相应的选项:

可以看到 IIS Express 对应的信息:

另外 IIS Express 对应的浏览器,可以通过启动按钮的右侧倒三角符号,进行选择,这样启动后,会根据选择默认启动所选择的浏览器。

以上是第一种最简单的方法, 通过 IIS Express 启动项目,查看对应的运行过程,并根据需求进行跟踪调试。

例如,下默认的 HomeController 控制器下对应的 Index 方法中添加断点。

点击菜单栏中的工具栏中的 IIS Express,当运行到对应断点位置的时候,就能够直接命中断点,查看相应的信息。如下图:

以上就是使用 IIS Express 的调试方法, 也是创建 web 项目后,默认的运行方法

本地 IIS 调试

不同于上一种方法的是,本地 IIS 调试进行配置。但是当我们的解决方案中,项目比较多的情况下,使用本地 IIS 调试,可以固定对应的进程,便于附加到进程调试。

具体过程如下:

1)项目名称鼠标点击右键,选择“属性”,得到“属性”窗口,选择左侧 Web 选项,配置服务器

2)选择本地 IIS 后,会生成对应的项目 URL,一般不建议对默认的 URL 进行修改,否则会在使用过程中可能导致路由的解析需要进行额外的考虑。

选择后点击右侧的创建虚拟目录,便能够在本地的 IIS 下生成对应于 Default 站点下的应用程序

3)刷新后,得到上一步所创建的对应的应用程序。

4)浏览应用程序,在计算机默认浏览器中会打开对应的应用程序

通过这种方式,将应用部署到本地 IIS,可以在任何情况下,通过浏览器访问本机的 URL,直接查看应用运行的状况。如果单纯调试前端的 CSS 或者 JavaScript 的情况下,就不需要进行 visual studio 的调试了,具体方法稍后介绍。

5)本地 IIS 的基本配置完成以后,调试 MVC 的业务代码的时候,就需要启动 Visual Studio 的调试。

①直接点击启动调试的按钮,会像第一种方法一样,打开对应的 http://localhost/4visualstudiojavascriptdebug,但是这种情况下不会启动 IIS Express,而是访问刚才部署在 IIS 中的应用程序。

②第一种方法,当我们如果需要反复调试的时候,重复的启动,重复的生成,如果项目下模块比较多的情况下,有经验的同学会知道,可能要生成每一个启动项的关联项,就会耗时间很长,所以这时候,可以选择生成单个项目后,附加到进程调试。

开启附加到进程调试的方法,有两种。

a)菜单栏中“调试”下选择“附加到进程”

附加到 w3wp.exe 中,这是针对 web 程序的,其他情况根据特定的情况,附加到自己的目标进程,比如在编写 Windows Service 的时候,就可以选择对应服务的进程。

注意:有时候我们打开搜索的时候可能找不到进程,别忘了图中标识的左下角的“显示所有用户的进程”前的复选框选中,会多出来一些进程,再搜索。

b)另一种方法,其实不算一种别的方法,只是一种快捷操作

使用“Ctrl Alt P”,快捷键组合,弹出附加到进程窗口。介绍这种方式的目的是由于有一部分同学可能对于快捷键的使用不够熟练,这种情况下,只要我们在日常工作中多注意一下,就能发现,很多快捷键的说明,已经在菜单中对应栏目中标注。比如,上图中 F5,Ctrl F5,Alt F2,Shift Alt F2,此外,如下图:

学会了这种方式,我们就能够基本掌握大部分 IDE 对应的快捷操作,而不用导出去博客中去搜索,这种方式对于 Eclipse,IDEA 等编译器同样适用。

远程调试

1)要远程调试首先需要一个工具:

(图片来自:https://visualstudio.microsoft.com)

选择对应的系统位数和语种,下载得到“VS_RemoteTools.exe”,将工具拷贝到远程计算机上并安装。

2)在操作系统的起始页可以看到对应的新增快捷入口

3)点击 Remote Debugger,弹出 Visual Studio 2019 远程调试器(管理员)

可以看到其中的说明:“Msvsmon 启动了名为***:4024 的新服务器。正在等待连接。

4)回到本地的 Visual Studio 的开发环境中,使用 Ctrl Alt P 附加到进程调试,进行如下配置:

选择连接类型为“远程(无身份验证)”

连接目标为”远程计算机 IP:4042",其中的 4042 是是上一部中显示的端口号。可是如图所示,给出了提示框,无法连接,远程调试器拒绝了请求。

5)回到 visual studio 中,再次对应于“目标 IP:端口号”,回车,注意:这里不选择查找,查找的时候查不到对应的机器。

注意对于远程(无身份验证)连接说明,因为这种调试方法存在风险,所以我们使用这种方式应该在内网的开发和测试环境下进行,避免在生产环境下进行这种操作。

目标连接后,附加到目标机器上的进程,访问进程中寄宿的服务或者是应用,就能够实现本地编辑器调试远程计算机对应服务的方法。

另外,需要说明的是,在远程调试过程中,本地版本的程序应该和远程调试计算机上部署的程序是同步的,否则会导致无法命中本地的调试断点的情况。

其他调试方法

上述的这三种 visual studio 的调试方法是 web 程序员常用的三种调试方法。当然 visual studio 还有很多其他的调试方法,针对于不同语言,不同环境。如下图:

(图片来自:https://docs.microsoft.com)

在上述两个截图中,可以看到“Download PDF”和“下载 PDF”的字样,下载后就可以看到离线的整本 PDF 文档,用起来非常方便。

JavaScript 的常见调试方法

接下来介绍日常工作中三种常用的调试方法,基本上能够应对在工作中遇到的所有的前端问题,包括 Vue 这种 SPA 的脚本框架。

继续接着上面创建的项目进行描述。

为了便于演示,不再增加新的 View,直接在 Home 路径下,修改 Index.cshtml,如图所示,注释掉 class="row"的内容,增加一个 div 标签。

alert

使用 alert 调试,在关键地方,增加 alert 来提示我们想要看到的关键信息。

使用 alert,在浏览器的调试过程中,会以弹框的形式弹出,给与提示,帮助调试。这种方式用起来比较直白,便捷。但是如果我们需要追踪程序的运行过程的时候,在很多地方需要添加 alert,在 alert 弹出后点击确认后才能进行下一个步骤。如果不需要不断点击,过程又比较复杂的情况下,又需要快速查看需要监控的变量值的时候,常常使用 console.log。

console.log

修改上述代码如下:

在浏览器的开发者工具中,对应的 console 下能够看到对应的 console.log 的输出,没有弹框,不需要确认。

有些情况下,比如,在阅读一个第三方的脚本文件的时候,引用后想要知道源码的运行过程,这种方式类似于在浏览器开发者工具的 Source 下的文件添加断点。但是,这种方法对于自己明确的业务过程的调试更加明确,而且能够免去在开发者工具下添加断点的过程。一旦运行到想要暂停的地方,它就会停留在 debugger 处。

debugger

在上述代码添加内容如下:

然后在浏览器中打开开发者工具。

如图所示,不需要添加断点,直接暂停在 debugger 的位置。

以上就是对三种 JavaScript 的调试方式的三种介绍。

下面在结合实际的引用项目进行介绍。

学习并引用第三方的 C#开源项目

演示环境

这里结合对 Redis 的使用来进行演示。

首先安装 Redis,具体的安装过程,如下图:

(图片来自:https://www.runoob.com)

根据说明,为了避免每次使用的时候,打开 CMD 窗口去执行可执行文件,我们常常会选择把它安装成服务,但是安装服务的时候,有时候会出现 ”错误 1067,进程意外终止“,这种情况下解决方式见下图:

(图片来自:http://www.fangbangxin.com)

然后可以安装 Redis Desktop Manager 查看是否正常连接并运行,如下:

本地 Redis 的基本环境配置好以后,我们来看看,如何去使用引用的其他来源的封装代码。

搜索 dll,查看源码

之所以选择这种方式,是很多同学在 NuGet-解决方案中搜索 dll 的时候,可能没有注意过一个细节。

在图中的“区域 2”的位置,有关于这个 dll 的详细信息,尤其是项目 URL 中的 github 地址。就这个 ServiceStack.Redis 而言,跟随右侧的 github 地址:https://github.com/ServiceStack/ServiceStack.Redis,就能够找到如下的内容:

当我们对于这个 dll 了解不够的时候,我们就可以通过这种方式,查看对应 github 主页上,下方的 ReadME.md 文件是否有详细的文件,一般这一操作并不会令我们失望。事实证明如下:

(图片来源:https://github.com)

不仅仅会有基本的描述信息,有时候还会为我们提供相关的参考文件,比如上图中标注的“view the docs”,它的链接会帮我们指向 https://docs.servicestack.net/

(图片来自:https://docs.servicestack.net/)

安装程序包

安装上一步骤中搜索到的符合要求的程序包。

点击安装,提示安装的 dll,并且在控制台的输出中也会输出对应的信息。如下图:

插入 redis 键值对

上述代码编译生成后运行前文提到的本地运行 http://localhost/4visualstudiojavascriptdebug 不需要其他的工作就能看按到 redis 插入了两条数据

这种情况下,就避免了启动调试,也避免了启动 IIS Express,本地 IIS 调试的优点就能够显现出来了。

那么如果我们想利用源码查看 ServiceStack.Redis 是插入数据的实现过程的情况下,应该如何操作呢?

查看源码执行过程

1)查看方法的定义位置

2)找到对应的命名空间

3)下载源码

4)解压后查看对应于命名空间的,项目文件所在的位置,如下图:

5)记录当前使用 dll 的磁盘位置(便于还原),删除

6)在解决方案下添加步骤 4)中解压的现有项目,如下图:

出现错误提示的情况下,需要解决:

查看最新的稳定版本为 5.8.0,所以安装 5.8.0 后,发现错误消失。

7)添加对于 ServiceStack.Redis 项目的引用

再次转到定义,就能够看到实现过程:

8)重新生成项目后,附加到进程调试

9)回到浏览器刷新页面,就能够看到断点命中

使用 F11 逐语句调试就能看到,进入到了 ServiceStack.Redis 对应的项目源码中

通过这种方式继续向下跟踪,就能知道 client.Set 的完整的实现过程。

学习并引用第三方的 Javascript 插件

在产品开发过程中,你可能会被产品经理要求画出各种各样的轮播图,带箭头的,不带箭头的,显示圆点的,不显示圆点的,圆点在下面的,圆点在两侧的,等等等等,让你焦头烂额的要求。下面我们来使用一个 JavaScript 插件来解这个难题。

在 github 上搜索 swiper,得到的第一个,可以看到 23k 颗星,经过考察的确是一个不错的插件。

(图片来自:https://github.com)

一步步的查找,看到了很多对应的 demo,可以直观的查看应用的效果:

(图片来自:https://swiperjs.com/demos/)

各种各样的 swiper 的 demo 映入眼帘。相信肯定能够发现你日常产品中的原型。

下载源码

下载页面 URL:https://github.com/nolimits4web/swiper

解压后可以看到对应 demo 的文件夹:

为了演示方便,这里将整个解压的文件夹拷贝到项目的 Content 目录下,为了避免项目中过多的无关文件,最好只引用使用到的文件。

引用 demo

选择其中的一个 demo,尝试把它用到项目的首页上,并根据需求调整:

代码语言:javascript复制
@{
    ViewBag.Title = "Home Page";
}
@section styles{
    <!-- Link Swiper's CSS -->
    <link rel="stylesheet" href="@(Url.Content("~/Content/swiper-master/package/css/swiper.min.css"))">
    <!-- Demo styles -->
    <style>
        html, body {
            position: relative;
            height: 100%;
        }

          /*注释掉 swiper 对于 body 的样式,否则原有样式会被覆盖上一层黑色*/
        /*body {
            background: #000;
            font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
            font-size: 14px;
            color: #000;
            margin: 0;
            padding: 0;
        }*/

          /*为指定的 swiper 区域添加高度,否则可能会导致外层 div 没有高度不显示*/
        #swiper {
            height: 400px;
        }

        .swiper-container {
            width: 100%;
            height: 300px;
            margin-left: auto;
            margin-right: auto;
        }

        .swiper-slide {
            background-size: cover;
            background-position: center;
        }

        .gallery-top {
            height: 80%;
            width: 100%;
        }

        .gallery-thumbs {
            height: 20%;
            box-sizing: border-box;
            padding: 10px 0;
        }

            .gallery-thumbs .swiper-slide {
                width: 25%;
                height: 100%;
                opacity: 0.4;
            }

            .gallery-thumbs .swiper-slide-thumb-active {
                opacity: 1;
            }
    </style>
}
<div class="jumbotron">
    <h1>ASP.NET</h1>
    <p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
    <p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
</div>

<div class="row">
    @*<div class="col-md-4">
            <h2>Getting started</h2>
            <p>
                ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that
                enables a clean separation of concerns and gives you full control over markup
                for enjoyable, agile development.
            </p>
            <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301865">Learn more &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Get more libraries</h2>
            <p>NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.</p>
            <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301866">Learn more &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Web Hosting</h2>
            <p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p>
            <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more &raquo;</a></p>
        </div>*@
    <div class="col-md-12">
        <input type="text" placeholder="用户名" id="username" />
        <input type="password" placeholder="密码" id="password" />
        <button>submit</button>
    </div>
</div>
<div id="swiper">

    <!-- Swiper -->
    <div class="swiper-container gallery-top">
        <div class="swiper-wrapper">
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-1.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-2.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-3.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-4.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-5.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-6.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-7.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-8.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-9.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-10.jpg")))"></div>
        </div>
        <!-- Add Arrows -->
        <div class="swiper-button-next swiper-button-white"></div>
        <div class="swiper-button-prev swiper-button-white"></div>
    </div>
    <div class="swiper-container gallery-thumbs">
        <div class="swiper-wrapper">
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-1.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-2.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-3.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-4.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-5.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-6.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-7.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-8.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-9.jpg")))"></div>
            <div class="swiper-slide" style="background-image:url(@(Url.Content("~/Content/swiper-master/demos/images/nature-10.jpg")))"></div>
        </div>
    </div>
</div>

@section scripts{
    <!-- Swiper JS -->
    <script src="~/Content/swiper-master/package/js/swiper.js"></script>

    <!-- Initialize Swiper -->
    <script>
        var galleryThumbs = new Swiper('.gallery-thumbs', {
            spaceBetween: 10,
            slidesPerView: 4,
            freeMode: true,
            watchSlidesVisibility: true,
            watchSlidesProgress: true,
        });
        var galleryTop = new Swiper('.gallery-top', {
            spaceBetween: 10,
            navigation: {
                nextEl: '.swiper-button-next',
                prevEl: '.swiper-button-prev',
            },
            thumbs: {
                swiper: galleryThumbs
            }
        });
    </script>

    <script>
        $(function () {
            if (!$('#username').val()) {
                console.log('用户名为空');
            }
            if (!$('#password').val()) {
                console.log('密码为空');
            }

        })
    </script>
}

修改对应图片,脚本和样式文件的路径。

这样就能够在首页看到对应的轮播图:

调试源码

F11 后会跳转到 core-class.js 文件中:

查看对应的加载脚本文件的路径:

0 人点赞