其三就是要养成写反思日记的习惯。

  《[一步步制作一个简单易行的 MVC 电商网站

BooksStore(四)](http://www.cnblogs.com/liqingwen/p/6658975.html%20)》(发布时间:2017-04-05)

 

而堵塞思维的人会想:这一个反对意见一定有用,我得以看看我是不是确实存在这样的阙如。

  《[一步步制作一个简单的 MVC 电商网站

BooksStore(一)](http://www.cnblogs.com/liqingwen/p/6640861.html)》(发布时间:2017-03-30 )

      《一步步制作一个简易的 MVC
电商网站 –
BooksStore(二)
》(发表时间:2017-03-31)

先是是从小事举行反思。

  《[一步步制作一个简单易行的 MVC 电商网站

BooksStore(三)](http://www.cnblogs.com/liqingwen/p/6652564.html)》(发布时间:2017-04-01)

原先,包括我在内的众六个人,都沦为了“低档次困苦陷阱”。

二、参预购物车

图片 1

 图 2

  界面的大约效用如图
2,在每本图书的区域新增一个链接(添加到购物车),会跳转到一个新的页面,显示购物车的详细音信

  • 购物清单,也得以经过“结算”链接跳转到一个新的页面。

  

  购物车是应用程序业务域的一片段,因而,购物车实体应该为域模型。

图片 2

  1.添加多少个类:

  Cart.cs 有加上、移除、清空和总结效率:

    /// <summary>
    /// 购物车
    /// </summary>
    public class Cart
    {
        private readonly List<CartItem> _cartItems = new List<CartItem>();

        /// <summary>
        /// 获取购物车的所有项目
        /// </summary>
        public IList<CartItem> GetCartItems => _cartItems;

        /// <summary>
        /// 添加书模型
        /// </summary>
        /// <param name="book"></param>
        /// <param name="quantity"></param>
        public void AddBook(Book book, int quantity)
        {
            if (_cartItems.Count == 0)
            {
                _cartItems.Add(new CartItem() { Book = book, Quantity = quantity });
                return;
            }

            var model = _cartItems.FirstOrDefault(x => x.Book.Id == book.Id);
            if (model == null)
            {
                _cartItems.Add(new CartItem() { Book = book, Quantity = quantity });
                return;
            }

            model.Quantity += quantity;
        }

        /// <summary>
        /// 移除书模型
        /// </summary>
        /// <param name="book"></param>
        public void RemoveBook(Book book)
        {
            var model = _cartItems.FirstOrDefault(x => x.Book.Id == book.Id);
            if (model == null)
            {
                return;
            }

            _cartItems.RemoveAll(x => x.Book.Id == book.Id);
        }

        /// <summary>
        /// 清空购物车
        /// </summary>
        public void Clear()
        {
            _cartItems.Clear();
        }

        /// <summary>
        /// 统计总额
        /// </summary>
        /// <returns></returns>
        public decimal ComputeTotalValue()
        {
            return _cartItems.Sum(x => x.Book.Price * x.Quantity);
        }
    }

  CartItem.cs 代表购物车中的每一项:

    /// <summary>
    /// 购物车项
    /// </summary>
    public class CartItem
    {
        /// <summary>
        /// 书
        /// </summary>
        public Book Book { get; set; }

        /// <summary>
        /// 数量
        /// </summary>
        public int Quantity { get; set; }
    }

 

  2.改动一下事先的 Details.cshtml,扩张“添加到购物车”的按钮:

@model Wen.BooksStore.WebUI.Models.BookDetailsViewModels

@{
    ViewBag.Title = "Books";
}

@foreach (var item in Model.Books)
{
    <div class="item">
        <h3>@item.Name</h3>
        @item.Description
        <h4>@item.Price.ToString("C")</h4>

        @using (Html.BeginForm("AddToCart", "Cart"))
        {
            var id = item.Id;
            @Html.HiddenFor(x => id);
            @Html.Hidden("returnUrl", Request.Url.PathAndQuery)

            <input type="submit" value="+ 添加到购物车" />
        }

        <br />
        <hr />
    </div>
}

<div class="pager">
    @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
</div>

 

  【备注】@Html.BeginForm() 方法默认会创立一个 Post
请求方法的表单,为啥不直接使用 Get 请求呢,HTTP
规范要求,会滋生数据变动时毫无接纳 Get
请求,将产品增长到一个购物车肯定会冒出新的数码变动,所以,这种情状不应当运用
Get 请求,直接呈现页面或者列表数据,这种请求才应该使用 Get。

 

  3.先修改下 css 中的样式

图片 3图片 4

body {
}

#header, #content, #sideBar {
    display: block;
}

#header {
    background-color: green;
    border-bottom: 2px solid #111;
    color: White;
}

#header, .title {
    font-size: 1.5em;
    padding: .5em;
}

#sideBar {
    float: left;
    width: 8em;
    padding: .3em;
}

#content {
    border-left: 2px solid gray;
    margin-left: 10em;
    padding: 1em;
}

.pager {
    text-align: right;
    padding: .5em 0 0 0;
    margin-top: 1em;
}

    .pager A {
        font-size: 1.1em;
        color: #666;
        padding: 0 .4em 0 .4em;
    }

        .pager A:hover {
            background-color: Silver;
        }

        .pager A.selected {
            background-color: #353535;
            color: White;
        }

.item input {
    float: right;
    color: White;
    background-color: green;
}

.table {
    width: 100%;
    padding: 0;
    margin: 0;
}

    .table th {
        font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
        color: #4f6b72;
        border-right: 1px solid #C1DAD7;
        border-bottom: 1px solid #C1DAD7;
        border-top: 1px solid #C1DAD7;
        letter-spacing: 2px;
        text-transform: uppercase;
        text-align: left;
        padding: 6px 6px 6px 12px;
        background: #CAE8EA no-repeat;
    }

    .table td {
        border-right: 1px solid #C1DAD7;
        border-bottom: 1px solid #C1DAD7;
        background: #fff;
        font-size: 14px;
        padding: 6px 6px 6px 12px;
        color: #4f6b72;
    }

        .table td.alt {
            background: #F5FAFA;
            color: #797268;
        }

    .table th.spec, td.spec {
        border-left: 1px solid #C1DAD7;
    }

Site.css

 

  4.再添加一个 CartController

图片 5

    /// <summary>
    /// 购物车
    /// </summary>
    public class CartController : Controller
    {
        private readonly IBookRepository _bookRepository;

        public CartController(IBookRepository bookRepository)
        {
            _bookRepository = bookRepository;
        }

        /// <summary>
        /// 首页
        /// </summary>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public ViewResult Index(string returnUrl)
        {
            return View(new CartIndexViewModel()
            {
                Cart = GetCart(),
                ReturnUrl = returnUrl
            });
        }

        /// <summary>
        /// 添加到购物车
        /// </summary>
        /// <param name="id"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public RedirectToRouteResult AddToCart(int id, string returnUrl)
        {
            var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id);

            if (book != null)
            {
                GetCart().AddBook(book, 1);
            }

            return RedirectToAction("Index", new { returnUrl });
        }

        /// <summary>
        /// 从购物车移除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public RedirectToRouteResult RemoveFromCart(int id, string returnUrl)
        {
            var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id);

            if (book != null)
            {
                GetCart().RemoveBook(book);
            }

            return RedirectToAction("Index", new { returnUrl });
        }

        /// <summary>
        /// 获取购物车
        /// </summary>
        /// <returns></returns>
        private Cart GetCart()
        {
            var cart = (Cart)Session["Cart"];
            if (cart != null) return cart;

            cart = new Cart();
            Session["Cart"] = cart;

            return cart;
        }
    }

  【备注】这里的购物车是通过 Session 会话状态举行保存用户的 Cart
对象。当会话过期(典型的状况是用户很长日子尚无对服务器发起任何请求),与该会话关联的数码就会被删除,这就表示不需要对
Cart 对象开展生命周期的田间管理。

  【备注】RedirectToAction() 方法:将一个 HTTP
重定向的命令发给客户端浏览器,要求浏览器请求一个新的 Url。

 

  5.在 Index 方法中拔取右键新建视图,专门用来体现购物清单:

图片 6

  Index.cshtml 中的代码:

@model Wen.BooksStore.WebUI.Models.CartIndexViewModel

<h2>我的购物车</h2>

<table class="table">
    <thead>
        <tr>
            <th>书名</th>
            <th>价格</th>
            <th>数量</th>
            <th>总计</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Cart.GetCartItems)
        {
            <tr>
                <td>@item.Book.Name</td>
                <td>@item.Book.Price</td>
                <td>@item.Quantity</td>
                <td>@((item.Book.Price * item.Quantity).ToString("C"))</td>
            </tr>
        }
        <tr>
            <td> </td>
            <td> </td>
            <td>总计:</td>
            <td>@Model.Cart.ComputeTotalValue().ToString("C")</td>
        </tr>
    </tbody>

</table>

<p>
    <a href="@Model.ReturnUrl">继续购物</a>
</p>

 

  我想,这一定是一个令人激动的随时,因为我们早已成功了这多少个基本的增长到购物车的功力。

图片 7

 

稍稍人说,我也不是讲师,怎么以教为学啊?其实很简短,我们可以享用给身边的同事朋友,或者举办有些享受活动。

简介

  上一遍大家尝试了:成立项目架构、成立域模型实体、创制单元测试、创建控制器与视图、创建分页和投入样式,而这一节我们会做到六个效率,分类导航与购物车。

  重要意义与知识点如下:

    分类、产品浏览、购物车、结算、CRUD(增删改查)
管理、发邮件、分页、模型绑定、认证过滤器和单元测试等(测度剩余两篇,臆想今天(因为星期天不放假)和周一(因为周四不上班)发表)。

     【备注】项目利用 VS2015 + C#6
举办付出,有问题请发布在留言区啊,还有,页面长得相比较丑,请见谅。

 

例如您想写作品,不停地报学习班,看外人的技巧,这样是很难提升的,真正该做的,应该是在左右基本技术未来,对协调早就写出的篇章举办总结,这一篇为啥阅读量低,那一篇有怎么着反对意见?

三、创设一个分部视图 Partial View

  分部视图,是放置在另一个视图中的一个内容片段,并且可以跨视图重用,这促进削减重复,尤其需要在多少个地点需要重复使用相同的数码时。

图片 8

  在 Shared 内部新建一个名为 _BookSummary.cshtml
的视图,并且把在此之前 Details.cshtml 的代码举办规整。

图片 9

 

  修改后的多少个视图:

  Details.cshtml

@model Wen.BooksStore.WebUI.Models.BookDetailsViewModels

@{
    ViewBag.Title = "Books";
}

@foreach (var item in Model.Books)
{
    Html.RenderPartial("_BookSummary", item);
}

<div class="pager">
    @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
</div>

 

  _BookSummary.cshtml

@model Wen.BooksStore.Domain.Entities.Book

<div class="item">
    <h3>@Model.Name</h3>
    @Model.Description
    <h4>@Model.Price.ToString("C")</h4>

    @using (Html.BeginForm("AddToCart", "Cart"))
    {
        var id = Model.Id;
        @Html.HiddenFor(x => id);
        @Html.Hidden("returnUrl", Request.Url.PathAndQuery)

        <input type="submit" value="+ 添加到购物车" />
    }

    <br />
    <hr />
</div>

 

 


【博主】反骨仔

【原文】http://www.cnblogs.com/liqingwen/p/6647538.html 

【参考】《精通 ASP.NET MVC …》

成甲在书里这么写道:只有可以转移您行动的新闻才是知识。

一步步制作一个简单易行的 MVC 电商网站 – BooksStore(二)

  本系列的
GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore

反思的意义在于,它可以发现我们是否留存文化误区,学习的知识是否使用,旧文化是否可以和新知识碰撞出火苗。

一、添加分类导航

  上一回我们把网页划分成了六个模块,其中左侧栏的一对没有形成,左侧栏拥有将图书分类彰显的效率。

图片 10

图 1

 

  1.回来从前的 BookDetailsViewModels
视图模型,我们分外再添加一个新的属性用作分类(CurrentCategory):

    /// <summary>
    /// 书籍详情视图模型
    /// </summary>
    public class BookDetailsViewModels : PagingInfo
    {
        public IEnumerable<Book> Books { get; set; }

        /// <summary>
        /// 当前分类
        /// </summary>
        public string CurrentCategory { get; set; }
    }

 

  2.修改完视图模型,现在就应当修改对应的 BookController 中的 Details
方法

图片 11

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="category">分类</param>
        /// <param name="pageIndex">页码</param>
        /// <returns></returns>
        public ActionResult Details(string category, int pageIndex = 1)
        {
            var model = new BookDetailsViewModels
            {
                Books =
                    _bookRepository.Books.Where(x => category == null || x.Category == category)
                        .OrderBy(x => x.Id)
                        .Skip((pageIndex - 1) * PageSize)
                        .Take(PageSize),
                CurrentCategory = category,
                PageSize = PageSize,
                PageIndex = pageIndex,
                TotalItems = _bookRepository.Books.Count(x => category == null || x.Category == category)
            };

            return View(model);
        }

图片 12图片 13

namespace Wen.BooksStore.WebUI.Controllers
{
    public class BookController : Controller
    {
        private readonly IBookRepository _bookRepository;
        public int PageSize = 5;

        public BookController(IBookRepository bookRepository)
        {
            _bookRepository = bookRepository;
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="category">分类</param>
        /// <param name="pageIndex">页码</param>
        /// <returns></returns>
        public ActionResult Details(string category, int pageIndex = 1)
        {
            var model = new BookDetailsViewModels
            {
                Books =
                    _bookRepository.Books.Where(x => category == null || x.Category == category)
                        .OrderBy(x => x.Id)
                        .Skip((pageIndex - 1) * PageSize)
                        .Take(PageSize),
                CurrentCategory = category,
                PageSize = PageSize,
                PageIndex = pageIndex,
                TotalItems = _bookRepository.Books.Count(x => category == null || x.Category == category)
            };

            return View(model);
        }
    }
}

BookController.cs

  

  参数扩充了一个 category,用于获取分类的字符串,对应 Books
中的属性的赋值语句改为 _bookRepository.Books.Where(x => category ==
null || x.Category == category),这里的 兰姆(Lamb)da 表明式 x => category
== null || x.Category == category 的趣味是,分类字符串为空就取库中具有的
Book 实体,不为空时按照分类开展对聚集举办筛选过滤。

  还要对性能 CurrentCategory 举行赋值。

  别忘了,因为分页是基于 TotalItems
属性举办的,所以还要修改地点 _bookRepository.Books.Count(x =>
category == null || x.Category == category),通过 LINQ
总结不同分类意况的个数。

 

  3.该控制器对应的 Details.cshtml
中的分页补助器也需要修改,添加新的路由参数:

<div class="pager">
    @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
</div>

图片 14图片 15

 1 @model Wen.BooksStore.WebUI.Models.BookDetailsViewModels
 2 
 3 @{
 4     ViewBag.Title = "Books";
 5 }
 6 
 7 @foreach (var item in Model.Books)
 8 {
 9     <div class="item">
10         <h3>@item.Name</h3>
11         @item.Description
12         <h4>@item.Price.ToString("C")</h4>
13         <br />
14         <hr />
15     </div>
16 }
17 
18 <div class="pager">
19     @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
20 </div>

Details.cshtml

 

  4.路由区域也应当修改一下

图片 16图片 17

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}",
                defaults: new { controller = "Book", action = "Details" }
            );

            routes.MapRoute(
                name: null,
                url: "{controller}/{action}/{category}",
                defaults: new { controller = "Book", action = "Details" }
            );

            routes.MapRoute(
                name: null,
                url: "{controller}/{action}/{category}/{pageIndex}",
                defaults: new { controller = "Book", action = "Details", pageIndex = UrlParameter.Optional }
            );
        }

RouteConfig.cs

 

  5.现在新建一个名为 NavController 的控制器,并丰硕一个名为 Sidebar
的措施,专门用来渲染左边边栏。

图片 18

  可是重回的 View 视图类型变成 PartialView 分部视图类型:

        public PartialViewResult Sidebar(string category = null)
        {
            var categories = _bookRepository.Books.Select(x => x.Category).Distinct().OrderBy(x => x);
            return PartialView(categories);
        }

  在方法体在右键,添加一个视图,勾上创造分部视图。

图片 19

  Sidebar.cshtml 修改为:

@model IEnumerable<string>

<ul>
    <li>@Html.ActionLink("所有分类", "Details", "Book")</li>
    @foreach (var item in Model)
    {
        <li>@Html.RouteLink(item, new { controller = "Book", action = "Details", category = item, pageIndex = 1 }, new { @class = item == ViewBag.CurrentCategory ? "selected" : null })</li>
    }
</ul>

  

  MVC 框架具有一种叫作“子动作(Child
Action)”的定义,可以适用于重用导航控件之类的东西,使用类似
RenderAction() 的措施,在此时此刻的视图中输出指定的动作方法。

  因为需要在父视图中表现另一个 Action
中的分部视图,所以本来的 _Layout.cshtml 布局页修改如下:

图片 20

 

  现在,启动的结果应当和图 1
是相同的,尝试点击左侧边栏的归类,阅览主区域的变动情形。

 

元认知是如何?元认知是对我们想想过程的考虑。

目录

  • 丰富分类导航

  • 进入购物车

  • 开创一个分部视图 Partial View

 

譬如说您在店铺提出一个方案,遭到了同事的不予,你第一时间想的是:我的方案不佳?你的方案才是一坨狗屎吗!这就是红灯思维。

除此以外,在教别人的时候,和不同的人举办思考的碰撞,我们反复可以发生新的了解。

咱俩在写反思日记的时候,应该多记录下我们的思辨过程,就像我们上学时做数学题,不要从来写答案,一步一步的步子都休想少,否则会扣分,我们写反思日记的时候,也休想漏写大家寻思的历程。

数学题的答案只假如不对的,那么势必是解题步骤出现了问题,假如我们写下去了,就能了然哪一步出错了,什么来头,这些分析解题步骤的进程,就叫元认知。

帮助是将生活案例化。

好为人师,假使用得好,不仅能匡助别人,也能帮忙我提高。

2,学习临界知识的多个重大心态。

成甲在书中强调的刻意磨炼,是要磨练我们的元认知。

书屋里的书一本接一本买回来,各类付费课程一个接一个,而且我们也落成了看书的速度跟上买书的快慢,各类学科的笔记也记了一大堆,可是就是心有余而力不足突破能力瓶颈。

相信明白了这一个办法,咱们增强协调的咀嚼水平并不是难事,紧要的是,我们要将这篇著作,从一带而过的音讯,变成可以付诸实践的,适合自己的学问。

在教别人的时候,大家往往能检查自己是否真的控制知识,有时候我们认为自己精通了,不过讲给人家的时候却讲不清,其实是因为其中的主干大家从没通晓。

前面提到大家每一日要写反思日记,那么提升元认知的一个好办法就是从反思日记开端。

自家自然安慰自己,读过的书和学过的知识,早就融入了自身的神魄,正在不停地滋养我,不过,前几日有时看到成甲的《好好学习:个人知识管理精进指南》,本来是消磨时光看的,没悟出看完未来,就找到了那个现象的原委。

诸如上班迟到这样的细枝末节,我们就可以考虑迟到的来由。

当大家明白了如何是文化后,就可以最先钻探成甲提议的逼近知识的概念。

大家所以会有习惯性防卫,就是因为咱们把别人对大家方案和见解的否认,当成对我们本身的否定,所以急于辩驳。

我们不少人在不停地学习看书,学习人家的学识,不过却没人意识到:咱们过去的阅历经验总和,本身就是一本无瑕的书。

从而,培育绿灯思维的首要就是,将人和事剥离。

所谓临界知识,便是我们经过深度思考后发觉的具备普遍引导意义的规律或定律。

自然,大量的开卷和读书必将是卓有效率的,不过只要我们能够左右科学的学习方法,不就可以节省时间和活力,用单薄的年华,做更多的事务啊?

大概,临界知识文化就是值得我们需要花80%的时间,去摸清的20%的平底规律。想要获取临界知识,就要磨炼大家深度思考的能力。

俺们要读书临界知识,首先要锤炼我们反思的能力,那么怎么着磨炼反思能力吗?

卡住思维

一,你陷入低档次困苦陷阱了吗?

1,什么是逼近知识?

总的说来,反思日子的重中之重不在结果,而在思考过程。

自我一度就是这么,为了APP
里的读书时间排行靠前,我赶紧一切碎片时间看书,晌午必将是边听书边洗漱,上班路上都挂个动圈耳机听书,上个厕所也要拿出去看个十秒钟,吃饭的时候也拿个手机边吃边看,就为了阅读时间在好友里能排行第一。

心绪学上有一个名词,叫做习惯性防卫。

2,以教为学

实质上她们混为一谈了总括和反思的定义,总计更多的是对结果的总括和记录,而反思是对发生结果的过程和原因的探索。

前阵子和对象聊天,发现我们多年来都深陷了一个瓶颈,就是奋力看书学习,不过能力却一味不能增强。

这两年,由于自媒体的隆起,各样共付会和阅读打卡群的勃兴,看书的人更加多了,社会上日渐形成一种新的攀比:比读书书籍的本数和阅读时间。

这听起来有些意料之外,其实也不难领会。

1,反思

诸五人有写日记的习惯,可是只是是写流水账,有时候看起来觉得浪费时间,其实我们转移一下写日记的情势就可以。

许六个人会说:我时时总括,周总括,月小结,年底统计。

《刻意训练》那本书应当有成千上万人看过,相信大家也清楚,刻意磨练并不是指花费大量年华,勤苦努力学习就能获取结果。

先是,在打听临界知识前,大家首先要了然一个概念,究竟怎么是文化?

说不上,在教旁人的时候,可以再一次加深我们的记忆,对文化展开重新梳理。

目前揣测,我只是是陷入了低品位劳累陷阱中,被自己的低档次艰苦感动得热泪盈眶,却丝毫从未有过发觉:我即便看了那么多书,不过才短短两个月过去,已经忘了内部的内容,我连它写了哪些都不记得了,它又怎么融入我的神魄呢?

咱俩要可以磨练的,就是分析解题步骤的能力。

反躬自省日记更多地应当是记录我们相见一件事的构思过程和研究方法,并且分析这种措施有无不妥。

以教为学就是把教外人的长河,当成自己学习的过程。

尚无哪本读本,比我们自身,对咱们尤其使得了。

自家还曾经一口气买了20本书,首个月就看了十本,当我在大团结成立的翻阅计划上一个一个打钩时,心里可有成就感了。

写反思日记的多少个小方法,书中也有提及:比如天天制定目的,核对是否做到,分析未成功原因。其余就是足以将每一天发生的风波分类记录,这样也便宜大家一天的办事梳理。

二,临界知识才是真的值得花时间学习的知识

其一定义讲简单了说,其实就是要爱慕我们本身。

几个人会认为每一天发生的业务太单调,没什么可以反思的,可是,要领悟,在遇见重大事件时,大家会有什么样的临场反应,完全出自我们平日拍卖小事的思想方法。

3,刻意磨炼

网络的普及让大家获取音讯变得分外容易,这多少个网页,在被人专注到在此之前,只但是是一串串数量,被人注意到后来,才是新闻,而当这条音讯,被人加以运用,并且改变了人们的缅怀方法和走路形式时,它才能变成知识。

在攻读思想的过程中,当大家发现自己的见地和端庄受到挑衅的时候,大家先是反响就是和它对着干,这是一种习惯性思维,也就是红灯思维。

三,提高学习能力的五个底层方法