结对第二次作业——编程实现

222200101王统涵 2024-09-30 23:13:37
这个作业属于哪个课程 FZU_SE_teacherW_4
这个作业要求在哪里结对第二次作业——编程实现
结对学号222200101,222200102
这个作业的目标编程实现结对第一次作业的网页原型
其他参考文献《构建之法》

目录

  • 1. CodeArt项目地址
  • 2. PSP表格
  • 3功能展示
  • 3.1 首页和公有头尾导航栏展示
  • 3.1.1首页展示
  • 3.1.2公有顶部导航栏展示
  • 3.1.3底部导航栏展示
  • 3.2 奖牌榜
  • 3.3 每日赛程
  • 3.3.1 日期切换与概览
  • 3.3.2打包的赛事浏览
  • 3.3.3点击跳转详细赛况
  • 3.4 详细赛程
  • 3.5 对阵图
  • 3.6了解更多
  • 3.6.1概览和顶部定位
  • 3.6.2外部链接跳转
  • 4结对过程
  • 4.1结对交流
  • 4.2 仓库commit信息截图如下
  • 5设计实现过程
  • 5.1功能结构图
  • 5.2设计实现过程
  • 6代码演示
  • 6.1奖牌榜关键代码展示
  • 6.2每日赛程关键代码展示
  • 6.2.1 训练赛和开幕式的输出
  • 6.2.2 打包项目的判断
  • 6.2.3 奖牌项目的判断
  • 6.2.4 没有奖牌的详细赛况
  • 6.3 详细赛事
  • 6.4 对阵表
  • 7心路历程与评价
  • 7.1心路历程
  • 7.2互相评价


1. CodeArt项目地址

CodeArt仓库地址
项目地址:114.55.130.95


2. PSP表格

222200101:

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划2020
• Estimate• 估计这个任务需要多少时间2020
Development开发18002380
• Analysis• 需求分析 (包括学习新技术)120120
• Design Spec• 生成设计文档3030
• Design Review• 设计复审60120
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)1010
• Design• 具体设计30800
• Coding• 具体编码1200880
• Code Review• 代码复审340120
• Test• 测试(自我测试,修改代码,提交修改)20300
Reporting报告100100
• Test Report• 测试报告6060
• Size Measurement• 计算工作量1010
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划3030
合计19202500

222200102:

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3060
• Estimate• 估计这个任务需要多少时间3060
Development开发9002220
• Analysis• 需求分析 (包括学习新技术)200400
• Design Spec• 生成设计文档2520
• Design Review• 设计复审6020
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)3020
• Design• 具体设计300600
• Coding• 具体编码6001200
• Code Review• 代码复审20120
• Test• 测试(自我测试,修改代码,提交修改)180240
Reporting报告90110
• Test Report• 测试报告5060
• Size Measurement• 计算工作量1010
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划3040
合计10202390


3功能展示

3.1 首页和公有头尾导航栏展示

首页集成了其他网站的入口与介绍

3.1.1首页展示

演示如下

在这里插入图片描述

3.1.2公有顶部导航栏展示

每个页面可以通过左上角的小球呼出导航栏,点击对应网页标题即可完成跳转
演示如下

在这里插入图片描述

3.1.3底部导航栏展示

底部导航可以直接跳转到对应网页,并引入了一些外部链接
演示如下

在这里插入图片描述

3.2 奖牌榜

奖牌榜演示如下

在这里插入图片描述

3.3 每日赛程

设计参考了官网,除了赛事筛选器,基本复刻了官网的交互.

3.3.1 日期切换与概览

点击日期可以呼出日历,点击其他日期可以切换到该日期对应的赛事列表

在这里插入图片描述

3.3.2打包的赛事浏览

点击打包项目预览的'+'按钮即可呼出每一个项目的结果信息,点击减号即可收齐

在这里插入图片描述

3.3.3点击跳转详细赛况

点击图标可以跳转到对应详细赛况界面,打包项目需要点开赛事列表,在点击跳转.
演示如下
普通情况:

在这里插入图片描述

打包情况:

在这里插入图片描述

3.4 详细赛程

通过点击每日赛程跳转,或者通过导航跳转(此方法将默认展示足球界面)
可以切换不同赛事阶段并且点击赛事显示详细信息演示如下

在这里插入图片描述

3.5 对阵图

通过点击详细赛程的对阵图按钮跳转,或者通过导航跳转(此方法将默认展示足球界面)
演示如下

在这里插入图片描述

3.6了解更多

页面设计参考了官网,旨在完善补充除了比赛信息以外的别的奥运资讯

3.6.1概览和顶部定位

页面具有一些外部链接按钮,以及顶部可以直接定位页面内模块,具体演示如下

在这里插入图片描述

3.6.2外部链接跳转

该页面的每个按钮都可以点击跳转到对应的网页,演示如下

在这里插入图片描述


4结对过程

4.1结对交流

由于我们两个是舍友,结对过程讨论都是面对面的,线上聊天记录部分截图如下

在这里插入图片描述


在这里插入图片描述

4.2 仓库commit信息截图如下

在这里插入图片描述


5设计实现过程

5.1功能结构图

附图如下

在这里插入图片描述

5.2设计实现过程

    主要设计思路是根据页面划分模块,以页面为单位进行划分职责并且维护对应的js以及css文件.
首页,奖牌榜,和了解更多的设计较为简单.奖牌榜利用之前爬取的数据,通过设置元素与布局已经写一些简单的就完成了,首页和了解更多则是通过图片和布局设计添加外部链接完成.

    每日赛程由于文件量较大,选择根据日期显示不同赛事(也符合JSON文件根据日期保存的格式),由于赛事数组的属性有不同,固使用了if,else判断这个数组元素的属性格式,进行判断选择那种输出方式,打包赛事由于具体赛事可能时间不同固处于文件的不同位置,采取将JSON文件数组读入程序数组中,遍历到有goupid的元素时,以其为起点遍历文件添加并且将数组内对所有groupip相同的元素移动到其后面,之后如上过程遍历数组.

    详细赛程包括显示每个项目的不同阶段,如D组、C组、B组、半决赛、决赛等,以及选择不同比赛项目查看比赛的详细信息,详细信息显示默认为足球,由每日赛况点击进入时,向网页传入包含比赛信息的参数,依次跳转到相应的比赛界面。还包括跳转到对应项目的对阵表功能,如果该项目有对阵表可以选择跳转到相应链接。每个项目具有不同的阶段,对 json 文件进行读取时,可以判断 phase 类型来确定是否是一个阶段,使用循环添加元素,以适应不同的比赛项目需求。选择不同阶段的各比赛场次时,会显示该项目的详细信息。

    对阵表的实现基于每个比赛项目的数据实现,由于比赛项目不一定具有对阵表,通过判断比赛参与者进行简单判断,由于赛事项目过多,项目的对阵表或是没有或是具有各种差异,因此可能存在显示问题,对于明确没有的项目会提示不存在对阵表。对阵表实现鼠标悬浮在某个国家时,可以高亮显示该国家在对阵表中的所有位置。通过比赛详细信息查看对阵表时,会向页面传入对应的项目参数,以获取相关数据。


6代码演示

6.1奖牌榜关键代码展示

通过fetch获取JSON文件之后,利用信息按照指定格式构建组件,然后添加到容器里
具体代码如下

fetch('./data/countrymedals.json')
.then(response => response.json())
.then(data => 
{
 const itemsContainer = document.getElementById('medal-list-items');
 data.forEach(item => 
 {
  const leaderboardItem = document.createElement('div');
  leaderboardItem.className = 'medal-list-item';
  leaderboardItem.innerHTML = 
  `
   <span class="item_rank">${item.rank}</span>
   <img src="./img/flag/${item.code}.png" class="item_flag">
   <span class="item_name">${item.countryName}</span>
   <span class="item_gold">${item.gold}</span>
   <span class="item_silver">${item.silver}</span>
   <span class="item_bronze">${item.bronze}</span>
   <span class="item_total">${item.total}</span>
  `;
  itemsContainer.appendChild(leaderboardItem);
 });
})
.catch(error => console.error('Error fetching JSON:', error));

6.2每日赛程关键代码展示

由于本人水平较低,写的代码很冗余,固根据划分的情况进行关键代码展示
以下代码均在如下循环中进行

 console.log(date);
 let day = String(date.getDate()).padStart(2, '0'); // 获取日期并补零
 let month = String(date.getMonth()).padStart(2, '0'); // 获取月份并补零
 let jsonFilePath = `./data/2024-${month}-${day}.json`;

 fetch(jsonFilePath) // 获取对应日期的JSON 文件(文件名为YYYY-MM-DD.json)
 .then(response => response.json())  // 解析 JSON 文件
 .then(data => 
 {
  //代码部分
 }

6.2.1 训练赛和开幕式的输出

每日赛程展示中训练赛和开幕式是很特殊的两种格式,没有对应的项目跳转所以放在if判断中的第一个判断

if (data[index].phaseCode=="TRNO") //训练赛赛事阶段为TRNO不设置跳转
   {
    const detailText = document.createElement('p');
    detailText.className = 'day_game_previev_detailnametxt';
    detailText.innerText = data[index].eventUnitName;
    dayGamePreviev.appendChild(detailText);
    container.appendChild(dayGamePreviev);
    continue;
   }
   

6.2.2 打包项目的判断

打包项目需要特殊的输出格式,单独赛事还要判断有无奖牌进行进一步判断输出格式,固将其放在,第二个判断if里
一下展示进入if后的遍历数组进行项目打包的代码

 var group_game_name = [];//详细赛程名数组
 group_game_name.push(event.eventName);
 for (let i = index; i < data.length; i++) 
    {
     if (data[i].groupId == event.groupId) 
     {
      /*
      进行对应元素的添加与打包具体过程略
      */
       //数组内的元素移动避免重复打包
      if (!group_game_name.includes(data[i].eventName)) group_game_name.push(data[i].eventName);
      let temp = data.splice(i, 1)[0];
      data.splice(index++, 0, temp);
      group_num++;
     }
     
       
      if(!data[i].competitors||data[i].competitors.length==0||!data[i].competitors[0].results||!(data[i].competitors[0].results.winnerLoserTie)) 
      {
       day_game_result_group.classList.add("pre");
      }//如果小项赛程不符合详细展示格式,则将展现的打包赛事仅输出赛事预览     
    }
   index--;//抵消下次循环的自增使得可以成功指向下一组
   container.appendChild(dayGamePreviev);//比赛项目栏处理完毕
   container.appendChild(day_game_result_group_continer);
   continue;//该打包项目结束

符合输出具体信息格式后,判断胜负方进行加粗等

 else
      {
       const day_game_result_group_name1 = document.createElement('label');//名字1添加
       day_game_result_group_name1.className='day_game_result_group_name1';      
       const day_game_result_group_name2 = document.createElement('label');
       day_game_result_group_name2.className='day_game_result_group_name2';    
       console.log(data[i].id) 
       if(data[i].competitors[0].results.winnerLoserTie=="W")
       {
        day_game_result_group_name1.innerHTML = data[i].competitors[0].name + "&nbsp;&nbsp;&nbsp;&nbsp;Winner"; 
        day_game_result_group_name1.style.fontWeight=700;
        day_game_result_group_name2.innerText = data[i].competitors[1].name;
       }
       else
       {
        day_game_result_group_name1.innerText = data[i].competitors[0].name;
        day_game_result_group_name2.innerHTML = data[i].competitors[1].name+ "&nbsp;&nbsp;&nbsp;&nbsp;Winner";   
        day_game_result_group_name2.style.fontWeight=700;
       }

判断是否需要输出比分信息,如果是则添加对应比分样式

       if(data[i].competitors[0].results.detailedMark)
       {
        day_game_result_group_point1.className='day_game_result_group_detailpoint1'; 
        day_game_result_group_point2.className='day_game_result_group_detailpoint2'; 
        
        for(let j=0;j<data[i].competitors[0].results.detailedMark.length;j++)
        {
         
         day_game_result_group_point1.innerHTML+= data[i].competitors[0].results.detailedMark[j][0].padStart(2, '0')+"&nbsp;&nbsp;&nbsp;&nbsp;";
        }
        day_game_result_group_point1.innerHTML+=data[i].competitors[0].results.mark;
         
        for(let j=0;j<data[i].competitors[1].results.detailedMark.length;j++)
        {
         day_game_result_group_point2.innerHTML+= data[i].competitors[1].results.detailedMark[j][0].padStart(2, '0')+"&nbsp;&nbsp;&nbsp;&nbsp;";
        }
        day_game_result_group_point2.innerHTML+=data[i].competitors[1].results.mark;  
       }
       else
       {      
        day_game_result_group_point1.className='day_game_result_group_point1'; 
        day_game_result_group_point1.innerText=data[i].competitors[0].results.mark;
        day_game_result_group_point2.className='day_game_result_group_point2'; 
        day_game_result_group_point2.innerText=data[i].competitors[1].results.mark;
       }

6.2.3 奖牌项目的判断

如果有奖品将进行如下代码,确保奖牌样式被正确添加

  if(data[index].medalFlag!=0)//有奖牌的情况
    {
       /*
      进行对应元素的添加与打包具体过程略
      */
      continue;
    }
   else ....

6.2.4 没有奖牌的详细赛况

如果没有奖牌将判断是否可以输出具体比分的赛事信息

 else if((data[index].eventUnitType=="HATH"||data[index].eventUnitType=="HTEAM")&&data[index].phaseType!=1)// 个人/团体 比赛
 {
  /*
  进行对应元素的添加与打包具体过程略
  */
  
 }
 else//不符合输出具体信息的情况则只添加预览部分
 {
  dayGamePreviev.style.cursor='pointer';
  dayGamePreviev.addEventListener('click', function() 
  {
   const url = 'game_detail.html?phaseId=' + encodeURIComponent(data[index].phaseId);
   window.open(url, "",);
  });
  container.appendChild(dayGamePreviev);//比赛项目栏处理完毕
 }
  continue;//一次json数组元素的判断结束

6.3 详细赛事

使用 fetch 获取 json 数据,页面默认读取足球运动的信息,从每日赛程选择项目进入时会传入项目的参数以读取项目的 json 文件:

var url = decodeURI(window.location.href);
var argsIndex = url.split("?phaseId=");
console.log(argsIndex)
var arg;
if (argsIndex.length === 1)
    arg = "FBLWTEAM11------------";
else
    arg = argsIndex[1].substring(0, 22);

let defaultGroup;
fetch("./data/detailgame/" + arg + ".json")
    .then(response => response.json())
    .then(data => {
        let title = document.getElementById("game-detail-title");
        let sportName = data.event.description;
        title.textContent = sportName + "-详细赛况";

        let container = document.querySelector(".tab-panel-container");
        container.innerHTML = '';
        container.appendChild(createTabContainer(data.event.phases));
        container.appendChild(createPanelSwiperContainer(data.event.phases))
        addBracketSelectEvent();
        addPanelClickEvent();
    })
    .catch(err => {
        console.error(err);
    });

不同的项目有不同的比赛阶段,使用 js 动态创建内容,以适应不同的项目:

function createTabContainer(phases) {
    let tabContanier = document.createElement("div");
    tabContanier.classList.add("tab-container");

    phases.sort((a, b) => b.order - a.order).forEach(phase => {
        if (phase.type === "3" && phase.units != undefined) {
            if (defaultGroup === undefined)
                defaultGroup = phase.shortDescription;
            let button = document.createElement("button");
            button.setAttribute("group", phase.shortDescription);
            button.type = "button";
            button.textContent = phase.shortDescription;
            button.addEventListener("click", () => {
                let buttons = document.querySelectorAll(".tab-container button");
                buttons.forEach(button => {
                    button.classList.remove("selected");
                })
                button.classList.add("selected");
                switchGroup(button.textContent, phases);
                addPanelClickEvent();
            });
            tabContanier.appendChild(button);
        }
    });
    return tabContanier;
}

点击不同的项目时,显示项目详细信息:

function updateDetailPrev(panel) {
    let detailPrevContainer = document.querySelector(".detail-prev-container");
    let nocImgs = panel.querySelectorAll(".noc-flag");

    let scores = panel.querySelectorAll(".score");
    let leftScore, rightScore;
    if (scores[0].textContent > scores[1].textContent) {
        leftScore = `<p class="left-score detail-winner">${scores[0].textContent}</p>`;
        rightScore = `<p class="right-score">${scores[1].textContent}</p>`;
    } else {
        leftScore = `<p class="left-score">${scores[0].textContent}</p>`;
        rightScore = `<p class="right-score detail-winner">${scores[1].textContent}</p>`;
    }
......

6.4 对阵表

对阵表需要对数据进行一定的排序,使连接时可以对应到不同的场次,读取数据后找到不同的比赛阶段,排序后加入同一个列表中:

function processData(data) {
    let flag = true;
    data.event.phases.forEach(bracketPhase => {
        if (bracketPhase.shortDescription === "1/4决赛") {

            bracketPhase.units.sort((a, b) => a.order - b.order).forEach(bracketItem => { // 比赛信息
                let liItem = document.createElement("li");
                liItem.classList.add("bracket-match-container")
                // 比赛的具体数据添加在下方
                liItem.appendChild(createMatchCard(bracketItem));
                QFNL_ul.appendChild(liItem);
            });
        } else if (bracketPhase.shortDescription === "半决赛") {
            bracketPhase.units.sort((a, b) => a.order - b.order).forEach(bracketItem => {
                let liItem = document.createElement("li");
                liItem.classList.add("bracket-match-container")
                liItem.appendChild(createMatchCard(bracketItem));
                SFNL_ul.appendChild(liItem);
            });
        } else if (bracketPhase.shortDescription === "决赛") {// 决赛
            if (bracketPhase.units[0].schedule.start === undefined ||
                bracketPhase.units[0].schedule.start.length != 2
            ) {
                flag = false;       
            }
            // 空白
            let liItemBlank = document.createElement("li");
            liItemBlank.classList.add("bracket-match-container", "blank")
            liItemBlank.appendChild(createMatchCard(0));
            FFNL_ul.appendChild(liItemBlank);
            bracketPhase.units.sort((a, b) => a.order - b.order).forEach(bracketItem => {
                let liItem = document.createElement("li");
                liItem.classList.add("bracket-match-container")
                liItem.appendChild(createMatchCard(bracketItem));
                FFNL_ul.appendChild(liItem);
            });
        }
    });

    bracketBody.appendChild(QFNL_ul);
    bracketBody.appendChild(SFNL_ul);
    bracketBody.appendChild(FFNL_ul);

    return flag;
}

要实现鼠标悬浮高亮显示相同国家的信息,可以为每个需要高亮显示的元素添加一个表示国家的属性,鼠标悬浮时首先获取当前的属性,使用循环找到所有相同属性并使用css添加高亮效果:


function addMouseHoverEvent() {
    let scoreLines = document.querySelectorAll(".score-line");
    scoreLines.forEach(scoreLine => {

        scoreLine.addEventListener("mouseenter", () => {
            // 获取选择的国家名
            let hoverNoc = scoreLine.getAttribute("noc");
            let sameNocs = document.querySelectorAll(`[noc=${hoverNoc}]`);
            sameNocs.forEach(noc => {
                noc.classList.add("currentIndicator")
            })
        })

        scoreLine.addEventListener("mouseleave", () => {
            // 获取选择的国家名
            let hoverNoc = scoreLine.getAttribute("noc");
            let sameNocs = document.querySelectorAll(`[noc=${hoverNoc}]`);
            sameNocs.forEach(noc => {
                noc.classList.remove("currentIndicator")
            })
        })
    });
}

7心路历程与评价

7.1心路历程

222200101:首先是不熟悉html,css,JavaScript,花了两个小时入门了一些基础语法,之后边做边学,写了一些很丑陋的码orz,首页和奖牌榜的添加逻辑相对较简单,每日赛程每个输出项目需要详细的判断,加上没什么json文件的读取经验,导致了写JavaScript的时候很痛苦,后面上手了后面还是很快乐的,尤其是我们两个都是初学者,逐渐开始入门,掌握一些效果实现的时候都会互相鼓励,极大的提升了开发的热情,后面写起来虽然每天基本都在写,也挺累的但是精神上比较快乐.

222200102: 一开始对 web 编程完全没有了解,在开始的两三天对html、css、JavaScript 进行了快速的了解和学习,开始做项目后,发现 web 编程十分耗费时间,尤其是对像我这样刚开始学习而完全不熟悉的人来说,往往需要花费很长的时间完成一个功能或是一个页面效果。在经过一周以来的高强度作业后,感到很幸运有一位很好的结对伙伴来完成项目,两个人共同的开发使学习和项目开发的进展都更为顺利。能够顺利完成这个作业收获很多

7.2互相评价

222200101 to 222200102:很好的队友,学习能力很强,技术很过硬,做事情认真也不敷衍,意见沟通都很顺利,而且还会帮助我解决问题hh,和有热情的人一起做事情是很快乐的,这样的结对编程很愉快.

222200102 to 222200101:我的结对队友是十分优秀的,在完成项目时给了我很多帮助,我们都对web编程不熟悉,有一位这样的伙伴使得长时间的学习和项目的实现都更加顺利,十分好的结对队友。

...全文
29 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
AJAX——新手快车道 前言 AJAX是什么? 首先、AJAX是一种很酷的技术,一旦采用了AJAX,就能让你的Web页面, 你的网站,甚至连同你们公司,都变得很酷。在Web2.0的时代里,不使用一点 AJAX技术的网站,就会显得很老土,很落伍。 但是,这样的理解,其实是很肤浅的。仅仅是从一个外行,从一个使用者的 角度出发,来理解AJAX,就像我在本书的第一章AJAX我也行中那样,开发 出很愚蠢,甚至都没有资格被称之为AJAX应用的纯IE、XMLHTTP应用。 AJAX更酷的一点在于,对于传统的Web开发人员来说,AJAX所运用的, 是更加先进的,更加标准化的,更加和谐高效的,完整的Web开发技术体系。 遵循这样的体系开发Web应用,能让你的开发过程变得更加轻松,也能使你们 的开发团队,显得很酷。在Web2.0 的时代里,还在采用过时的技术来开发 Web,会显得很老土,很落伍。 AJAX的相关组成技术,每一个都已经出现了N年以上了,对这些技术的 组合运用,也远远早于AJAX这个名词出现之前。所以,我真正敬佩的,并非提 出 AJAX这个缩写的Jesse James Garrett。而是那些早在N年以前,就已经在探索、 实践的先行者,他们始终在追求的:是更好的用户体验,以及更好的开发体验。 这样的精神,才是最可宝贵的,也是最值得我们学习的。许多年过去以后,当我 们再回头来看当年的这些热门技术,也许早已经变得老土,变得落伍了。在这样 的历程中,哪些人会成长为高手?会成长为大师呢?就是那些永不满足,永远 在追求更好的用户体验,永远在追求更好的开发体验的人! 新手如何上路 软件开发这个领域,永远都在飞速发展,大家都必须不断的学习新的知识、 技能、框架、IDE、甚至新的语言。传说中的骨灰级高手们,就像传说中的大侠, 任何武器、哪怕是一块木头到了他们手里,也能发挥惊人的威力,人家练了几十 年的看家本领,他们随手使来,也竟然像是打娘胎里就开始练了一样。为什么? 就算不吹那么玄的,平常我们能够碰到的那些老手,在学新东西的时候, 也比那些新手学得更快,理解得更深,运用得更熟练。而新手们呢?往往就会漫 无头绪,焦头烂额,以一副张着茫然的大眼睛的经典表情,出现在各大论坛的 新手求助区里。他们欠缺的,究竟是什么呢?为什么老手学新东西,就没遇到那 么多困难呢? 泛泛地说,自然是经验上的欠缺。仔细地说来,又可以分为三个方面: 一、本质,一种技术与另一种技术之间,往往会有本质上的相通之处,当你 对一种技术的理解与思考越来越深入时,学习一种新技术也会更加容易。触类旁 通,举一反三的能力,就是来自于对于技术本质的追寻。 二、地图,本质上或多或少的相通,也提示着我们技术之间的相互关联,当 你了解的技术越多,了解得越是深入,在你的内心,就能建立起越发清晰的技 术地图。各种知识都有一个自然、合理的位置。那么当一个老手要学习一门新技术 的时候,他其实并非在探索一个全新的、未知的领域,而是有很多脉络可寻,也 很多已知可以帮助他们快速了解未知。 三、技巧,面对同样的未知,面对同样的难题,新手们一筹莫展,而老手们 却掌握着更多的技巧和手段,帮助他们试探可能性、缩小问题的范围、迅速定位 问题、不犯明显愚蠢的错误、甚至能够列举出更具命中力的搜索关键词,而这些 技巧,都帮助老手在前进的道路上,更少跌倒,即使跌倒,也能更快的爬起来。 作为一本写给新手的入门书籍,我们希望展现给读者的,是一个老手如何 学习新技术的过程。我们相信,这样的一个学习过程,对于新手来说,是更具有 价值的。 何谓快车道 必须老老实实的承认,我吹牛了!老手虽然会比新手学习得更快一些,但 是也同样会碰到麻烦,遇到障碍,感觉头痛。如果没有真正的专家的指导,我不 可能如此迅速地将AJAX掌握到目前这样的程度,要真是让我自学三个月,然 后就写出书来的话,那真是在骗钱了。 老手能够快速学习的另一个重要的诀窍是:认识很多牛人朋友 如果没有李锟与赵泽欣的专家级指导与帮助,如果没有与李锟AJAX结对 编程的体验,如果没有三个人在MSN上无数次的长聊,我想要在短期内建立起: 对于AJAX本质的理解; 对于整个AJAX以及相关技术地图的理解; 对于AJAX编程开发所需要的很多技巧、手段的掌握; 几乎是不可能的。 如果没有(N多需要感谢的人)的(N多方面的帮助),我们这本书,也 不可能以现在这样的深度,以(N个月)内完成的速度,送到读者的面前。 希望这本书,能够对大家快速学习AJAX,有所帮助。

110

社区成员

发帖
与我相关
我的任务
社区管理员
  • FZU_SE_teacherW
  • 助教赖晋松
  • D's Honey
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧