前端框架前置-相关知识学习

发布于:2025-07-02 ⋅ 阅读:(23) ⋅ 点赞:(0)

AJAX有什么用?
浏览器和服务器之间通信,动态数据交互
使用axios:
  1.引入axios库
  2.语法:
  axios({
  url:'目标资源地址'  //服务器的地址
}).then((result)=>{
   //服务器返回的数据做后续处理
})
案例:
        <p class="my-p"></p>
    <script src="http://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">
    </script>
    <script>
        axios({
            url:'http://hmajax.itheima.net/api/province'
        }).then(
            result=>{
                console.log(result.data.list)//返回一个省份的数组
                console.log(result.data.list.join('<br>'))
                document.querySelector('.my-p').innerHTML=result.data.list.join('<br>')
            }
        )
    </script>
认识URL:
   统一资源定位符,简称网址,是因特网上标准的资源的地址,用于访问网络上的资源
有网页资源,图片资源,数据资源等等
eg:http://hmajax.itheima.net/api/province
      协议              域名               资源路径
http协议:规定了浏览器发送及服务器返回内容的格式
域名:标记服务器在互联网中方位
资源路径:标记资源在服务器下的具体位置
http://hmajax.itheima.net/api/news
这个拿到的是对象数组
URL查询参数:
 定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
 语法:http://xxx.com/xxx/xxx?参数1=值1&参数2=值2
   axios({
  url:'目标资源地址'
  params:{
    参数名:值
    pname:' '
}
}).then((result)=>{
   //服务器返回的数据做后续处理
})
注意:axios在运行时把参数名和值,会拼接到url?参数名=值
eg:
           axios({
            url:'http://hmajax.itheima.net/api/city',
            params:{
                pname:'青海省'
            }
        }).then(
            result=>{
                console.log(result.data.list.join('<br>'))//返回一个省份的数组
                document.querySelector('.my-p').innerHTML=result.data.list.join('<br>')
            }
        )
地区查询:后端会告诉你URL网址和参数
   https://hmajax.itheima.net/api/area?pname=河北省&cname=邢台市
document.querySelector('sel-btn').addEventListener('click',()=>{
   let pName=document.querySelector('.provice').value
   let cName=document.querySelector('.city').value
axios({
   url="http://hmajax.itheima.net/api/area',
   params:{
     pname:pNname,
     cname:cNname
   }
}).then(result()=>{
   let list=result.data.list
   console.log(list)
   let theLi=list.map(areaName=>`<li class="list-group-item">${areaName}</li>.join(' ')`
   console.log(theLi)
   document.quSelector('.list-group'.innerHTML=theli
})
)}
常用的请求方法:对服务器资源,要执行的操作
 GET:获取数据
 POST:提交数据
 PUT:修改数据(全部)
 DELETE:删除数据
 PATCH:修改数据(部分)
axios 请求配置
url:请求的URL网址
method:请求的方法,GET可以省略(不区分大小写)
data:请求数据
语法:
   axios:({
   url:'  ',
   method: 方法
   data:{
     参数名:值
  }
}).then((result)=>{
    对服务器返回的数据进行处理
})
数据提交-注册账号
    <button class="btn">点击</button>
    <script src="http://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">
    </script>
    <script>
    document.querySelector('button').addEventListener('click',()=>{
        axios({
            url:'http://hmajax.itheima.net/api/register',
            method:'post',
            data:{
                username:'itheima798',
                password:'jsaouhf'
            }
        }).then(result=>{
            console.log(result)
        })

    })
    </script>
常见就是数据获取和数据提交
数据获取:
  axios({
 url:'  ',
 method:'get', //默认是get所以我们一般是不写的
 params:{
   参数名:值
 }
})
数据提交:
axios({
 url:' ',
 method:'put',
 data:{
   参数:值
 }
})
axios错误处理:
   场景:再次注册相同的账号,会遇到报错信息
   查询方法就是:控制台----response----data
   在这里就能找到axios产生的错误信息
   但是我们如何将这个错误信息反馈给用户来看???
语法:在then方法的后面,通过点语法调用catch方法,传入回调函数并定义形参。
  axios({
  url:
}).then(result=>{
  处理数据
}).catch(error=>{
  处理错误
})
案例:重复注册账号,点击按钮出现账号被占用的弹窗
HTTP协议-请求报文
http协议:规定了浏览器发送及服务器返回内容的格式
请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容
  请求报文的组成部分有:
  1.请求行:请求方法,URL,协议
  2.请求头:以键值对的格式携带的附加信息,比如:Content-Type
  3.空行:分割请求头,空行之后的是发送服务器的资源
  4.请求体:发送的资源
右键检查查看网络,Fetch/XHR,标头(请求标头),在载荷中查看用户提交的内容
请求报文-错误排查
需求:通过请求报文排查错误原因,并修复
HTTP协议-相应报文
响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容
 1.响应行(状态行):协议,HTTP响应状态码,状态信息
 2.响应头:以键值对的格式携带的附件信息,比如:Content-Type(服务器返回的内容类型)
 3.空行:分隔响应头,空行之后的是服务器返回的资源
 4.响应体:返回的资源
HTTP响应状态码:用来表明请求是否成功完成
1xx----信息   2xx---成功  3xx---重定向消息  4xx---客户端(浏览器)错误
5xx---服务端错误
在哪里能查看?响应标头---响应
接口文档:描述接口的文章(后端提前给你的)
接口:使用AJAX和服务器通讯时,使用的URL,请求方法,以及参数
请求体就是请求方法下面的内容,就是data对象,想查看的话就点击网络的载荷,这里面的内容是由浏览器将请求体自动转换成的json字符串
用户登录案例:
    VSCODE里面
form-serialize插件
作用:快速收集单元素的值
参数1:要获取那个表单的数据
   表单元素设置name属性,值会作为新对象的属性名
   建议name属性的值,最好和接口文档参数名一致
参数2:配置对象
  hash 设置获取数据结构
   -true:JS对象(推荐)  一般请求体里提交给服务器
   -false:查询字符串
  empty 设置是否获取空值
    -true:获取空值(推荐)  数据结构和标签结构一致
    -false:不获取空值
它会将这些值收集成一个对象
<script src="./from-serislize.js"></script>
const data=serialize(form,{hash:true,empty:true})
使用该插件批量获取之后可以使用解构的方法进行批量的赋值
const{username:,password:}=data
注:定义class就是为了方便获取
Bootstrap弹框:
  功能:不离开当前页面,显示单独内容,供用户操作
步骤:
     1.引入bootstrap.css和bootstrap.js
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js></script>
     2.准备弹框标签,确认结构
     3.通过自定义属性,控制弹框的显示和隐藏----单纯显示/隐藏
     eg:
     <button data-bs-toggle="modal" data-bs-target="css选择器">
         显示弹框
     </button>
     //为下面HTML标签中的button添加dismiss属性
     <button data-bs-dismiss="modal">Close</button>
弹框标签
    bootstrap的modal弹框:添加modal类名(默认隐藏)
通过JS控制,弹框显示或隐藏-----额外逻辑代码
   方法:1.创建弹框对象
              const modalDom=document.querSelector('.css选择器')
              const modal=new bootstrap.Modal(modalDom)
             2.显示弹框
                写个点击事件,然后调用 modal.show()
             3.隐藏弹框
                modal.hide()
1.axios的库  2.serialize插件,用于收集表单里的值  3.bootstrap的js库控制弹窗的显示和隐藏
案例:做一个从服务器获取数据,然后渲染到表格上面的案例
const certer='xxx'
function getBookList(){
    axios({
    url:'http://hmajax.itheima.net/api/books',
    params:{
      creter
   }
  }).then(result=>{
      console.log(result)
      const bookList=result.data.data
      console.log(bookList)
      //下面教你如何把对象数组渲染到页面上
      const htmlStr=bookList.map((item,index)=>{
      return `<t>
    <td>${index+1}</td>
    <td>${item.bookname}</td>
    <td>${item.author}</td>
    <td>${item.publisher}</td>
    <td>
        <span class="del">
            删除
        </span>
        <span class="edit>
            编辑
        </span>
    </td>
    </tr>`
  }).join(' ')
   console.log(htmlStr)
   document.querSelector('.list').innerHTML=htmlStr
  })
}
///将你写的数据,提交到服务器上面
document.querSelector('click',()=>{
   //收集表单数据,并提交到服务器保存
   const addForm=document.querSelector('.add-form')
   const bookObj=serialize(addForm,{ hash:true, empty: true})
   console.log(bookObj)
   //提交到服务器
  axios({
   url:'http://hmajax.itheima.net/api/books',
   method:'post'
   data:{
       ...bookObj,   //展开属性值
       creator
   }
  }).then(result=>{
    console.log(result)
    //添加成功后,重新请求并渲染图书馆列表
    getBookList()
    //重置表单
   addForm.reset()
    //点击保存后隐藏弹框
    addModal.hide()
})
})
/实现删除图书---在服务器中删除数据,然后在页面中重新渲染一下
//删除元素---由于是动态创建的tr--->点击事(件委托)---从父级里面找
document.querSelector('.list').addEventListener('click',e=>{
    //获取触发事件目标元素
    //console.log(e.target)
    //判断点击的是删除元素
    if(e.target.classList.contains('del')){
    //获取图书id(自定义属性id)
   const theId=e.target.parentNode.dataset.id
   console.log(theId)
   axios({
    url:`http://hmajax.itheima.net/api/books/${theId}`
    method:'DELETE'
 }).then(()=>{
  //重新刷新一下页面
  getBooksList()
})
}
})
修改图书---先从服务器中找到对应的图书详情回填到表单中---修改之后再提交给服务器---刷新一下界面
const editDom=document.querySelector('.edit-modal')
const editModal=new bootstrap.Modal(editDom)
document.querSelector('click',e=>{
  //判断点击的是否为编辑元素
  if(e.target.classList.contains('edit')){
      //数据回填
      const theId=e.target.parentNode.dataset.id--父级节点中的自定义属性id
     axios({
    url:'http://hmajax.itheima.net/api/books/${thrId}'
    }).then(result=>{
     const bookObj=result.data.data
     //获得属性名
      const keys=Object.keys(bookObj)
     keys.forEach(key=>{
       document.querSelector(`.edit-form .${key}`).value=
       bookObj[key]   //对象中的属性值           
    })
})
      editModal.show()
 }
 //再点击一下编辑按钮,就隐藏
 document.querSelector('.edit-btn').addEventListener('click',()=>{
  editModal.hide()
})
})
///将改过的数据提交到服务器上面,然后再刷新一下页面
 document.querSelector('.edit-btn').addEventListener('click',()=>{
     const editForm=document.querSelector('.edit-form')
     const {id,bookname,author,publisher}=serialize(editForm,{hash:true,empty:true}
     //保存正在编辑的图书id,隐藏起来,无需让用户修改
    //<input type="hidden" class="id" name="id" value="84783">
   axios({
    url:'http://hmajax.itheima.net/api/books/${id}'
    method:'put',
    data:{
     bookname,
     author,
     publisher,
     creater
   }
  }).then(result=>{
    getBookList()
   editModal.hide()
})
})
图片上传:
  1.获取图片文件对象
  2.使用FormData携带图片文件
       const fd=new FormData()
       fd.append(参数名,值)
       参数名在接口文档中一般是img,值就是图片文件对象
   3.提交表单数据到服务器,使用图片url网址
   4.接口文档请求参数中的Body参数/form-data类似于json字符串的形式,而form-data就是以表单来上传的
案例实现:<input type="file" class="upload">
<img src="" class="my-img" alt="图没了">
document.querSelector('.upload').addEventListener('change',e=>{
    console.log(e.target.files)  //拿到了文件列表Filelist--伪数组
    //想拿图片对象
   console.log(e.target.failes[0])
   const fd=new FomData()
   fd.append('img',e.target.files[0])
   //交表单数据到服务器,使用图片url网址
   axios({
    url:'http://hmajax.itheima.net/api/uploading',
    method:'POST',
    data:fd
  }).then(result=>{
       console.log(result)
       //获取图片url网址,用img标签加载显示
       const imgUrl=result.data.data.url
       document.querySelector('.my-img').src=imgUrl
  })
})
标签关联:<lable for="bg">更换背景</lable>
           <input class="bg-ipt" type="file" id="bg">
<script>
document.querSelector('.bg-ipt').addEventListener('change',e=>{
    console.log(e.target.files[0])
    const fd=new FormData()
    fd.append('img',e.taregt.files[0])
    axios({
    url:'http://hmajax.itheima.net/api/uploading',
    method:'post',
    data:fd
   }).then(result=>{
   const imgUrl=result.data.data.url
   document.body.style.backgroundImg=`url(${imgUrl})`
   //将图片的URL存储到本地,以便下次打开网页图片还在
   localStorage.setItem('bgImg',imgUrl)
})
})
  //网页运行后将本地存储的URL拿出来
  const bgUrl=localStorage.getItem('bgImg')
  console.log(bgUrl)
  document.body.style.backgroundImage=`url(${bgUrl})`
  bgUrl && (document.body.style.background=`url(${bgUrl})`)
</script>
案例:个人信息设置
步骤:1.信息渲染
          2.头像修改
          3.提交表单
          4.结果提示
1.信息渲染
   自己的用户信息:给自己起个外号,并告诉服务器,获取对应的用户数据
   axios({
     url:'http://hmajax.itheima.net/api/setting',
     params:{
        creator:'播仔'
   }
  }).then(reult=>{
    const userObj=result.data.data
    //数据回填
   Object.keys(userObj).forEach(key=>{   //遍历获取对象的属性值
      if(key==='avator'){
        //赋予默认头像
        document.querSelector('.prew').src=userObj[key]
     }else if(key==='gender'){
       //赋予默认性别
       //获取性别单选框:[男radio元素,女radio元素]
      const gRadioList=document.querSelector('.gender')
      //获取性别数字:0男,1女
      const gNum=userObj[key]
     //通过性别数字,作为下标,找到对应性别单选框,设置选中状态
      gRadioList[gNum].checked=true
   }else{
     //赋予默认内容
     document.querySelector(`.${key}`).value=userObj[key]
  }
 })
 })
//头像修改
注意:label可以提高我们表单的交互范围,使用for关联了input文件选择类型id的值,所以我们点在了这个label就相当点在了<input>上,所以change一般就绑定在<input>的class上面
document.querSeltctor('.upload').addEventListener('change',e=>{
    1.获取本地的头像文件
    console.log(e.target.files[0])
    const fd=new FormData()
    fd.append('avatar',e.target.files[0])
    fd.append('creator',外号)
   //提交服务器并更新头像
    axios({
      url:'http://hmajax.itheima.net/api/avatar',
      method:'PUT'
      data:fd
   }).then(result=>{
    const imgUrl=result.data.data.avatar
    //把新的头像回显到页面上
    document.querSelector('.prew').src=imgUrl
})
})
提交表单
1.收集表单信息
2.提交到服务器保存
document.querSelector('.submit').addEventListener('click',()=>{
   const userForm=document.querSelector('.user-form')
   const userObj=serialize(userForm,{hash:true,empty:true})
   userObj.creator=creator //起一个外号,对特定的数据尽心更新
   //性别数字字符串,转成数字类型
   userObj.gender=+userObj.gender
   console.log(userObj)
   //提交给服务器保存
   axios({
     url:'http://hmajax.itheima.net/api/settings',
     method:'PUT',
     data:userObj
  })
})
eg:字符串转为数字类型
    1.使用一元操作符
    let str="abc" let num=+str  console.log(num)  //NaN
                                              console.log(typeof num) //"number"
    2.使用Number()函数
    let str="123";
    let num=Number(str)
    console.log(num)  //输出:123
    3.使用parseInt()和parseFloat()函数分别解析成整数和小数
    let str="123.45"
    let intNum=parseInt(str) //123
    let floatNum=parseFlaot(str) //123.45
//用户信息提交成功后,会有个提示框
<div class="toast" data-bs-delay="1500">
     提示框内容
</div>
 案例:
      <div class="toast my-toast" data-bs-delay="1500">
          <div class="toast-body>
               <div class="alert alert-success info-box">
                    操作成功
               </div>
          </div>
      </div>
document.querSelector('.submit').addEventListener('click',()=>{
   const userForm=document.querSelector('.user-form')
   const userObj=serialize(userForm,{hash:true,empty:true})
   userObj.creator=creator //起一个外号,对特定的数据尽心更新
   //性别数字字符串,转成数字类型
   userObj.gender=+userObj.gender
   console.log(userObj)
   //提交给服务器保存
   axios({
     url:'http://hmajax.itheima.net/api/settings',
     method:'PUT',
     data:userObj
  }).then(result=>{
     //创建toast对象
     const toastDom=document.querSelector('.my-toast')
     const toast=new bootstrap.Toast(toastDom)
     //调用show方法->显示提示框
     toast.show()
})
})
AJAX原理---XMLHttpRequest
定义:XMLHttpRequest(XHR)对象用于与服务器交互,通过XHR可以在不刷新页面的情况下请求特定URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XHR在AJAX编程中被大量使用
关系:axios内部采用XHR与服务器交互
为啥学习XHR?
1.有更多与服务器数据通信方式
2.了解axios内部的工作原理
步骤:
   1.创建XMLHttpRequest
   2.配置请求方法和请求url地址
   3.监听loadend事件,接收响应结果
   4.发起请求
   const xhr=new XMLHttpRequest()
   xhr.open('请求方法','请求url网址')
   xhr.addEventListener('loadend',()=>{
      //接收响应结果
     console.log(xhr.response)   //返回的是对象结构的json字符串,而axios是自动将字符串转换对象的
})
xhr.send()  //发送-请求
案例:获取并展现所有省份名字
const xhr=new XMLHttpRequest()
xhr.open('get','http://hmajax.itheima.net/api/province'
xhr.addEventListener('loadend',()=>{
    console.log(xhr.response)  //json字符串
    const data=JSON.parse(xhr.response) //将json字符串转换为对象
    console.log(data.list.join('<br>'))  //用join()数组转字符串
    document.querSelector('.my-p').innerHTML=data.list.join('<br>')
})
xhr.send()
XHR---查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
<p class="city-p"></p>
<script>
const xhr=new XMLHttpRequest()
xhr.open('get','http://hmajax.itheima.net/api/city?pname=辽宁省')
xhr.addEventListener('loadend',()={
   console.log(xhr.response)
   const data=JSON.parse(xhr.response)
   console.log(data)
   document.querySelector('.city-p').innerHTML=data.list.join('<br>')
})
    xhr.send()
</script>
地区查询:需求:输入省份和城市名字,查询地区列表
 document.querSelector('.sel-btn').addEventListener('click',()=>{
   //收集省份和城市名字
    const pname=document.querSelector('.province').value
    const cname=document.querSelector('.city').value
   //组织查询参数字符串
   const qObj={
     pname,
     cname
   }
   //查询参数对象->查询参数字符串
   const paramsObj=new URLSearchParams(qObj)
   const queryString=paramsObj.toString()
   console.log(queryString)
  //使用XHR对象,查询地区列表
  const xhr=new XMLHttpRequest()
  xhr.open('GET',`http://hmajax.itheima.net/api/area?${queryString}`)
  xhr.addEventListener('loadend',()=>{
    console.log(xhr.response)
    const data=JSON.parse(xhr.response)
    console.log(data)
    const htmlStr=data.list.map(areaName=>{
       return`<li class="list-group-item">${areaName}</li>`
 }).join(' ')
  console.log(htmlStr)
  document.querySelector('.list-group').innerHTML=htmlStr
 })
    xhr.send()
 })
XHR-数据提交
需求:通过XHR提交用户名和密码,完成注册功能
请求头设置Content-Type:application/json
请求体携带JSON 字符串
<button class="reg-btn">注册用户</button>
<script>
 document.querSelector('.reg-btn').addEventListener('click',()=>{
   const xhr=new XMLHttpRequest()
   xhr.open('POST','http://hmajax.itheima.net/api/register')
   xhr.addEventListener('loadend',()=>{
    console.log(xhr.response)
})
    //设置请求头--告诉服务器内容类型(JSON字符串)
   xhr.setRequestHeader('Content-Type','application/json')
    //准备提交的数据
   const userObj={
     username:'itheima007'     
     password:'7654321'
 }
   const userStr=JSON.stringify(userObj)
  //设置请求体,发起请求
  xhr.send(userStr)
})
</script>
Promise:
    promise对象用于表示一个异步操作的最终完成(或失败)及其结果值
异步代码:耗时的,不会堵塞当前线程的
通过promise对象去管理ajax(异步代码)
1.逻辑更清楚
2.了解axios函数内部运行机制(then和catch)
3.能解决回调函数地狱问题
语法:
   //1.创建promise对象
   const p=new  Promise((resolve,reject)=>{
   //2.执行异步任务--并传递结果
   //成功调用:resolve(值) 触发then()执行
   //失败调用:reject(值)  触发catch()执行
})
//3.接收结果
p.then(result=>{
    //成功
}).catch(error=>{
    //失败
})
案例:
   //1.创建Promise对象
    const p=new Promise((resolve,reject)=>{
   //2.执行异步代码
    setTimeout(()=>{
      //resolve('模拟AJAX请求-成功结果')
      reject(new Error('模拟AJAX请求-失败结果')
  },2000)
})
//3.获取结果
p.then(result=>{
   console.log(result)
}).catch(error=>{
    console.log(error)
})
promise-三种状态
一个Promise对象,必然处于以下几种状态之一
就是你创建的new Promise()
1.待定(pending) :  初始状态,即没有被兑现,也没有被拒绝
2.已兑现(fulfilled) : 意味着,操作成功完成--resolve()--.then(回调函数)
3.已拒绝(rejected) : 意味着,操作失败--rejected--.catch(回调函数)
注意:promise对象一旦被兑现/拒绝
就是已敲定了,状态无法再被改变
const p=new Promise((resolve,reject)=>{
   setTimeout(()=>{
       reject(new Error('模拟AJAX请求-失败结果'))
   },2000)
})
console.log(p)   //对象中包含的[[PromiseState]]会显示状态
p.then(result=>{
   console.log(result)
}).catch(error=>{
   console.log(error)
})
案例:使用promise+XHR获取省份列表
<p class="my-p"></p>
<script>
const p=new promise((resolve,reject)=>{
    const xhr=new XMLHttpRequest()
    xhr.open('GET','http://hmajax.itheima.net/api/province')
    xhr.addEventListener('loadend',()={
    //xhr如何判断响应成功还是失败的?
   //2xx开头的都是成功响应状码
   if(xhr.status>=200&&xhr.status<300){
      resolve(JSON.parse(xhr.response))
    }
   else{
      reject(new Error(xhr.response))
  }
})
   xhr.send()
})
p.then(result=>{
  console.log(result)
  document.querSelector('.my-p').innerHTML=result.list.join('<br>')
}).catch(error=>{
  //错误对象常用console.dir详细打印
  console.dir(error)
  document.querSelector('.my-p').innerHTML=error.message
})
</script>
封装-简易axios-获取省份列表
需求:基于promise+XHR封装myAxios函数,获取省份列表展示
步骤:1.定义一个myAxios函数,接收配置对象,返回Promise对象
         2.发起XHR请求,默认请求方法为GET
         3.调用成功/失败的处理程序
         4.使用myAxios函数,获取省份列表展示
<p class="my-p"></p>
fuction myAxios(config){
      return new Promise((resolve,reject)=>{
      //发起XHR请求,默认请求方法为GET
      const xhr=new XMLHttpRequest()
      xhr.open(config.method||'GET',config.url)
      xhr.addEventListener('loaded',()=>{
      if(xhr.status>=200&&xhr.status<300){
         resolve(JSON.parse(xhr.response))
      }
     else{
        reject(new Error(xhr.response))
    }
})
    xhr.send()
})
}
 myAxios({
     url:'http://hmajax.itheima.net/api/province'
     //将这一部分数据传到形参config的位置
}).then(result=>{
    console.log(result)
    document.querSelector('my-p').innerHTML=result.list.join('<br>')
}).catch(error=>{
    console.log(error)
    document.querSelector('my-p').innerHTML=error.message
})
需求:获取地区列表---修改myAxios函数支持传递查询参数
1.myAxios函数调用后,传入params选项
2.基于URLSearchParams转换查询参数字符串
<p class="my-p"></p>
<script>
fuction myAxios(config){
      return new Promise((resolve,reject)=>{
      //发起XHR请求,默认请求方法为GET
      const xhr=new XMLHttpRequest()
     //1.判断有params选项,携带查询参数
     if(config.params){
          // 2.使用URLSearchParams转换,并携带到url上
          const paramsObj=new URLSearchParams(config.params)
          const queryString=paramsObj.toString()
         //3.把查询参数字符串,拼接到url?后面
          config.url+=`?${queryString}`
     }
      xhr.open(config.method||'GET',config.url)
      xhr.addEventListener('loaded',()=>{
      if(xhr.status>=200&&xhr.status<300){
         resolve(JSON.parse(xhr.response))
      }
     else{
        reject(new Error(xhr.response))
    }
})
    xhr.send()
})
}
myAxios({
     url:'http://hmajax.itheima.net/api/area',
     params:{
       pname:'辽宁省',
       cname:'大连市'
    }
}).then(result=>{
    console.log(result)
    document.querySelector('.my-p').innerHTML=result.list.join('<br>')
})  //join()方法是数组转换成字符串的
</script>
需求:修改myAxios函数支持传递请求体数据,完成注册用户功能
1.myAxios函数调用后,判断data选项
2.转换数据类型,在send方法中发送
<button class="reg-btn">注册用户</button>
fuction myAxios(config){
      return new Promise((resolve,reject)=>{
      //发起XHR请求,默认请求方法为GET
      const xhr=new XMLHttpRequest()
     //1.判断有params选项,携带查询参数
     if(config.params){
          // 2.使用URLSearchParams转换,并携带到url上
          const paramsObj=new URLSearchParams(config.params)
          const queryString=paramsObj.toString()
         //3.把查询参数字符串,拼接到url?后面
          config.url+=`?${queryString}`
     }
      xhr.open(config.method||'GET',config.url)
      xhr.addEventListener('loaded',()=>{
      if(xhr.status>=200&&xhr.status<300){
         resolve(JSON.parse(xhr.response))
      }
     else{
        reject(new Error(xhr.response))
    }
})
    //1.判断有data选项,携带请求体
    if(config.data){
        //2.转换数据类型,在send中发送
        const jsonStr=JSON.stringify(config.data)
        //此处必须加请求头
        xhr.setRequestHeader('Content-Type','application/json')
        xhr.send(jsonStr)
    }else{
       //如果没有请求体数据,正常的发起请求
            xhr.send()
    }
})
}
document.querySelector('.reg-btn').addEventListener('click',()=>{
    //3.使用myAxios函数,完成注册用户
    myAxios({
     url:'http://hmajax.itheima.net/api/register',
     method:'POST',
     data:{
       username:'itheima999',
       password:'66666'
    }
}).then(result=>{
    console.log(result)
}).catch(error=>{
    console.log(error)
})
})
案例:天气预报
1.从服务器获得数据
 function getWeather(cityCode){
   myAxios({
      url:'http://heima.itheima.net/api/weather',
      params:{
        city:cityCode
}
}).then(result=>{
   console.log(result)
   const wObj=result.data
   const dateStr=`<span class="dateShort">${wObj.date}</span>
   <span class="calender">农历&nbsp;
        <span class="dateLunar">${wObj.dateLunar}</span>
  </span>
`
  document.querySelector('.title').innerHTML=dateStr
  document.querySelector('.area').innerHTML=wObj.area
  //七日天气预报数据展示
  const dayForecast=wObj.dayForecast
  dayForecastStr=dayForecast.map(item=>{
  return `<li class="item">
  <div class="date-box">
       <span class="date-box">${item.dateFormat}<span>
       <span class="date">${item.date}</span>
  </div>
        <img src="${item.weatherImg}" alt="" class="weatherImg">
    <span class="weather">${item.weather}</span>
    <div class="temp">
        <span class="temNight"></span>
        <span class="temDay">12</span>
        <span>C</span>
    </div>
    <div class="wind">
        <span class="windDirection">${item.windDirection}</span>
        <span class="windPower">${item.windPower}</span>
    </div>
     </li>`
}).join(' ')
   document.querySelector('.week-wrap').innerHTML=dayForecastStr
})
}
//默认进入网页-就要获取天气数据(北京市城市编码:'110100')
getWeather('110100')
需求:根据关键字,展示匹配城市列表
步骤:1.绑定input事件(只要用户输入字或删除字事件就会触发),获取关键字
          2.从后端获取展示城市列表数据
document.querySelector('.search-city').addEventListener('input',(e)=>{
            console.log(e.target.value)
            //获取城市列表数据
           myAxios({
             url:'http://hmajax.itheima.net/api/wether/city',
             params:{
                 city:e.target.value
          }
          }).then(result=>{
             console.log(result)
             const liStr=result.data.map(item=>{
                 return `<li class="city-item">${item.name}</li>`
         }).join(' ')
         console.log(liStr)
         document.querySelecor('.search-list').innerHTML=liStr
         })
})
//点击城市,然后展示该城市近七天的天气状况
  1.绑定城市点击事件,获取城市code值
  2.调用获取并展示天气的函数
注:给动态的标签绑定一个事件就用事件委托
             const liStr=result.data.map(item=>{
                 return `<li class="city-item" data-code="${item.code}">${item.name}</li>` 
//给每个小li绑一个自定义的属性data-code
         }).join(' ')
document.querySelector('.search-list').addEventListener('click',e=>{
   if(e.target.classList.contains('city-item')){
       const cityCode=e.target.dataset.code
      console.log(cityCode)
     //调用获取并展示天气的函数
     getWeather(cityCode)
}
})
同步代码:逐行执行,需原地等待结果后,才继续向下执行
异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发一个回调函数
JS中有哪些异步代码?
setTimeout/setInterval;事件;AJAX
回调函数地狱:
    概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱
缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身
嵌套时如果里面的axios请求出现错误,那么外面进行catch捕获,是不能正常捕获错误的
Promise-链式调用
概念:
1.then()之后会返回一个新生成的Promise对象
2.在promise对象里面管理一个异步任务
概念:依靠then()方法会返回一个新生成的Promise()对象特性,继续串联下一环任务,直到结束
细节:then()回调函数中的返回值,会影响新生成的Promise对象最终状态和结果
eg:
const p=new Promise((resolve,reject)=>{
    setTimeout(()=>{
       resolve('北京市')
},2000)
})
const p2=p.then(result=>{
  console.log(result)
  return new Promise((resolve,reject)=>{
   setTimeout(()=>{
     resolve(result+'.....北京')
  },2000)
})
})
p2.then(result=>{
   console.log(result)
})
---------------------------------------------------------------------------------------------
解释一下:在你的代码中,then() 的回调函数返回了一个新的 Promise。因此,p2(即这个新的 Promise)的解决值将是这个返回的 Promise 的解决值,也就是 '北京市.....北京'。
如果你去掉 return 语句,then() 的回调函数将不返回任何值,所以 p2 的解决值将是 undefined。这样,p2.then(result => { console.log(result) }) 将打印 undefined 而不是 '北京市.....北京'。
简单来说,return 语句在这里是用来传递 Promise 链中的值,确保 p2 的解决值是正确的。
---------------------------------------------------------------------------------------------
console.log(p2===p)  //false
注意:axios函数的返回值是一个Promise对象
案例:
<script>
     let pname=' '
    //1.得到-获取省份的Promise对象
     axios({url:'http://hmajax.itheima.net/api/province'}).then(result=>{
     pname=result.data.list[0]
     dociment.querySelector('.province').innerHTML=pname
    //2.得到- 获取城市Promise对象
    return axios({url:'http://hmajax.itheima.net/api/city',params:{pname}})
}).then(result=>{
   const cname=result.data,list[0]
   document.querySelector('.city').innerHTML=cname
   //3.得到-获取地区Promise对象
   return axios({url:'http://hmajax.itheima.net/api/area',pname:{pname,cname}})
}).then(result=>{
   console.log(result)
   const areaName=result.data.list[0]
   document.querySelector('.area').innerHTML=areaName
})
</script>
//插一个promise链例子
const p= new Promise(resolve,reject){
   setTimeout(()=>{
     resolve('北京市')
   },2000)
}
p.then(result=>{
   console.log(result)
   return anotherFunction(result)
})
function anotherFunction(input){
   const processedResult=input+'...北京';
   console.log(processedResult);
   return processedResult;
}
p2.then(result=>{
    console.log(result);  //打印的结果是"北京市...北京"
});
async函数和await:
    async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise
概念:在async函数内,使用await关键字取代then函数,等待获取promise对象成功状态的结果值
使用await获取成功的promise对象,取在原地,然后定义一个常量在前面接收就行
await会等待结果暂停往下走,只有上面的成功了,才会继续往下获取
案例:
  1.定义async修饰函数
async function getData(){
   2.await等待Promise对象成功的结果
   const pObj=await axios({url:'http://hmajax.itheima.net/api/province'})
   const pname=pObj.data.list[0]
   const cObj=await axios({url:'http://hmajax.itheima.net./api/city',params:{panme}})
   const cname=cObj.data.list[0]
   const aObj=await axios({url:'http://hmajax.itheima.net/api/area',params:{pname,cname}})
   const areaName=aObj.data.list[0]
   document.querySelector('.province').innerHTML=pname
   document.querySelector('.city').innerHTML=cname
   document.querySelector('.area').innerHTML=areaName
}
async函数和await_捕获错误
使用:try...catch语句标记要尝试的语句块,并指定一个出现异常时抛出的响应
语法:try{
       //要执行的代码
     }catch(error){
       //error接收的是,错误信息
       //try里代码,如果有错误,直接进入这里执行
     }
async function getData(){
  try{
   const pObj=await axios({url:'http://hmajax.itheima.net/api/province'})
   const pname=pObj.data.list[0]
   const cObj=await axios({url:'http://hmajax.itheima.net./api/city',params:{panme}})
   const cname=cObj.data.list[0]
   const aObj=await axios({url:'http://hmajax.itheima.net/api/area',params:{pname,cname}})
   const areaName=aObj.data.list[0]
   document.querySelector('.province').innerHTML=pname
   document.querySelector('.city').innerHTML=cname
   document.querySelector('.area').innerHTML=areaName
   }catch(error){
    //注意:如果try里某行代码报错后,try中剩余的代码就不会执行了
      console.dir(error)
   }
}
事件循环:
   概念:JS有一个基于事件循环的并发模型,事件循环负责执行代码,收集和处理事件以及队列中的子任务。
   定义:执行代码和收集异步任务的模型,在调用栈空闲,反复调用任务队列里回调函数的执行机制,就叫事件循环
   为什么有时间循环?
    JS是单线程的,为了(异步耗时的事件)不阻塞JS引擎,设计执行代码的模型
宏任务和微任务:
 eg:
<script>
    console.log(1)
    setTimeout(()=>{
    console.log(2)
},0)
const p=new Promise((resolve,reject)=>{
    console.log(3)
    resolve(4)
})
console.log(5) 
</script> //打印结果是1 3 5 4 2
注:微任务比宏任务先执行
宏任务:1.浏览器执行的异步代码
             2.例如:JS执行脚本事件,setTimeout/setInterval,AJAX请求完成事件,用户交互事件等
微任务:1.JS引擎执行的异步任务
             2.例如:Promise对象.then()的回调
             注意:promise对象本身是同步的
JS内代码如何执行?
1.先执行JS里面的同步代码
2.遇到宏任务/微任务交给宿主环境(浏览器),有结果回调函数进入对应队列
3.当执行栈空闲时,清空微任务队列,再执行下一个宏任务,从1再来
eg: 前端面试题--事件循环
1.回答代码执行顺序
console.log(1)
setTimeout(()=>{
   console.log(2)
   const p=new Promise(resolve=>resolve(3))
   p.then(result=>console.log(result))
},0)
const p=new Promise(resolve=>{
    setTimeout(()=>{
        console.log(4)
    },0)
    resolve(5)
})
p.then(result=>console.log(result))
const p2=new Promise(resolve=>resolve(6))
p2.then(result=>console.log(result))
console.log(7)
结果是:1,7,5,6,2,3,4
注意:只要调用栈空闲就会先从微任务队列里面找(清空)然后再从宏任务里面找
Promise.all静态方法(函数):
概念:合并多个Promise对象,等待所有同时成功完成(或某一个失败),做后续逻辑
new Promise()--new Promise()--new Promise()
=新的Promise对象
1.所有Promise成功-->.then(回调函数)
2.任意一个Promise失败-->.catch(回调函数)
语法:
      const p=Promise.all([Promise对象,Promise对象....])
      p.then(result=>{
          //result结果:[Promise对象成功结果,Promise对象成功结果....]
      }).catch(error=>{
          //第一个失败的Promise对象,抛出的异常
      })
案例:同时请求多地的天气,然后展示到页面上
返回的是一个对象数组
<ul class="my-ul"></ul>
<script>
//1.请求城市天气,得到Promise对象
const bjPromise=axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'110100'}})
const shPromise=axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'310100'}})
const gzPromise=axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'440100'}})
const szPromise=axios({url:'http://hmajax.itheima.net/api/weather',params:{city:'440300'}})
//2.使用Promise.all,合并多个Promise对象
const p=Promise.all([bjPromise,shPromise,gzPromise,szPromise])
p.then(result=>{
   //注意:结果数组顺序和合并时顺序是一致
   console.log(result) //返回的是一个对象数组
  //map返回新数组
   const htmlStr=result.map(item=>{
       return `<li>${item.data.data.area}-----${item.data.data.weather}</li>`
   }).join(' ')
   document.querySelector('.my-ul').innerHTML=htmlStr
}).catch(error=>{
   console.dir(error)
})
</script>
案例:商品分类
需求:尽可能同时展现所有商品分类到页面上
步骤:
1.获取所有的一级分类数据
2.遍历id,创建获取二级分类请求
3.合并所有二级分类Promise对象
4.等待同时成功,开始渲染页面
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
//1.获取所有一级分类数据
axios({
   url:'http://hmajax.itheima.net/api/category/top'
}).then(result=>{
   console.log(result)
   //2.遍历id,创建获取二级分类请求
   const secPromiseList=result.data.data.map(item=>{
   return axios({
     url:'http://hmajax.itheima.net/api/category/sub',
     params:{
         id:item.id //一级分类id
    }
   })
})
   console.log(secPromiseList) //[二级分类请求Promise对象,二级分类请求Promise对象....]
  //3.合并所有二级分类Promise对象
  const p=Promise.all(secPromiseList)
  p.then(result=>{
      console.log(result)
     //4.等待同时完成后,渲染页面
  const htmlStr= result.map(item=>{
      const dataObj=item.data.data //一级数据的标题
        return ` <div class="item">
        <h3>${dataObj.name}</h3>
    <ul>
         ${dataObj.children.map(item=>{
             return `<li>
         <a href="javascript:;">
             <img src="${item.picture}">
             <p>${item.name}</p>
         <a>
    </li>`
   }).join(' ')
    </ul>
     `
  }).join(' ')
  })
})
</script>
//学习反馈---省市区切换
步骤:1.设置省份数据到下拉菜单
         2.切换省份,设置城市数据到下拉菜单,并清空地区下拉菜单
         3.切换城市,设置地区数据到下拉菜单
//1.设置省份下拉菜单数据
axios({
   url:'http://hmajax.itheima.net/api/province'
}).then(result=>{
   const optionStr=result.data.list.map(pname=>`<option value="${pname}">${pname}</option>`).join(' ')
   document.querySelector('.province').innerHTML=`<option value="">省份</option>`+optionStr
   //2.切换省份,设置城市数据到下拉菜单,并清空地区下拉菜单
     document.querySelector('.province').addEventListener('change',async e=>{
  //获取用户选择省份名字----console.log(e.target.value)
     const result=await axios({url:'http://hmajax.itheima.net/api/city'},params:{pname:e.target.value})})
    const optionStr=result.data.list.map(cname=>`<option value="${cname}">{c$name}</option>`).join(' ')
  //把默认城市选项+下属城市数据插入select中
    document.querySelector('.city').innerHTML=`<option value="">城市</option>`+optionStr
  //清空地区数据
   document.querySelector('.area').innerHTML=`<option value="">地区</option>`
})
3.切换城市,设置地区下拉菜单数据
document.querySelector('.city').addEventlistener('change',async e=>{
   console.log(e.target.value)  //拿到你点击的那个城市名
   const result= await axios({url:'http://hmajax.itheima.net/api/area',params:{
     pname:document.querySelector('.province').value,
     cname:e.target.value
}})
   console.log(result)
   const optionStr=result.data.list.map(aname=>`<option value="${aname}">${aname}</option>`).join(' ')
  console.log(optionStr)
  document.querySelector('.area').innerHTML=`<option value="">地区</option>`+optionStr
})
3.数据提交部分
需求:收集(form)学习反馈数据,提交保存
<button type="button" class="btn btn-secondary submit">确定提交</button>
   //1.监听提交的点击事件
document.querySelector('.submit').addEventListener('click',async ()=>{
   //2.依靠插件收集表单数据
   const form=document.querySelector('.info-form')
   const data=serialize(form,{hash:true,empty:true})  //返回一个对象
   console.log(data)
try{
   const result=await axios({
     url:'http://hmajax.itheima.net/api/feedback',
     method:'POST'
     data
  })
   console.log(result)   //返回一个结果对象
   alert(result.data.message)
}catch(error){
   console.log(error)
   alert(error.response.data.message)
}
})
------------------------------------------------------------------------------------------------
Node.js
Nodejs是一个跨平台JavaScript运行环境,使开发者可以搭建服务器的JavaScript应用程序
作用:使用Node.js编写服务器端程序
1.编写数据接口,提供网页资源浏览功能等等
2.前端工程化:开发项目直到上线,过程中集成的所有工具和技术
例如:压缩工具,格式化工具,转换工具,打包工具,脚手架工具等等
Node.js是前端工程化的基础(因为Node.js可以主动读取前端代码内容)
Node.js为何能执行JS???
首先:浏览器能执行JS代码,依靠的是内核中的V8引擎(C++)
其次:Node.js是基于Chrome V8引擎进行封装(运行环境)
注意:Node.js环境没有DOM和BOM等
fs模块--读写文件
模块:类似插件,封装了方法/属性
fs模块:封装了与本机文件系统进行交互,方法/属性
语法:1.加载fs模块对象
         const fs=require('fs')  //返回一个fs对象
         2.写入文件内容
         fs.writeFile('文件路径','写入内容',err=>{
             //写入后的回调函数
         })
         //其中err传入的是错误信息
         3.读取文件内容
         fs.readFile('文件路径',(err,data)=>{
             //读取后的回调函数
             //data 是文件内容的 Buffer 数据流(对象)
         }) 
eg:
    1.加载fs模块对象
    const fs=require('fs')
    2.写入文件内容
    fs.writeFile('./test.txt','hello,Node.js',(err)=>{
      if(err) console.log(err)
      else console.log('写入成功')
    })
    3.读取文件内容
    fs.readFile('./text.txt',(err,data)=>{
    if(err) console.log(err)
    //data 是buffer 16进制数据流对象
    //.toString() 转换成字符串
    else console.log(data.toString)
})
path模块-路径处理
问题:Node.js代码中,相对路径是根据终端所在路径来查找的,可能无法找到你想要的文件
案例:
03-CODE
03
   index.js
   01.js
   02.js
test.txt
            -以上是各个文件的结构
然后编写index.js里面的代码
index.js:
           const fs=require('fs')
           fs.readFile('../test.txt',(err,data)=>{
           if(err) console.log(err)
           else console.log(data.toString())
})
你想要对test.txt进行操作
但是你在终端输入--node 03/index.js
会出现一个报错。
[Error:ENOENT:no such file directory,open'D:\...\03_Node.js与webpack\test.txt']
终端显示的目录:03-Node.js与Webpack\03-code>
所以解释一下问题:03-code的..是03-code的父级03-Node.js与Webpack
,因此Node.js与webpack\test.txt这个路径就不复存在了
注意:./是当前目录,../是父级目录
------------------------------------------------------------------------------------------------
建议:在Node.js代码中,使用绝对路径
补充:_dirname内置变量(获取当前模块目录-绝对路径)
dirname访问的是当前文件夹的绝对路径!!!!!!!
           window:路径的分隔符是 "\"
           mac:路径的分隔符是"/"
注意:path.join()会使用特定于平台的分隔符,作为定界符,将所有给定的路径片段连接在一起
eg:path.join('03','dist/js','index.js')
//window:'03\dist\js\index.js'
//mac:'03/dist/js/index.js'
语法:
       1.加载path模块                     const path=require('path')
       2.使用path.join方法,拼接路径 path.join('路径1','路径2',...)
案例:
      const fs=require('fs')
     //1.引入path模块对象
      const path=require('path')
     //2.调用 path.join() 配合__dirname 组成目标文件的绝对路径
     console.log(__dirname)----\03-Node.js与Webpack\03-code\03
     fs.readFile(path.join(__dirname,'../test.txt'),(err,data)=>{
     if(err) console.log(err)
     else console.log(data.toString)
})
案例:压缩前端html
需求:把回车符(\r)和换行符(\n)去掉后,写入到新html文件中
步骤:
      1.读取源html文件内容
      2.正则替换字符串
      3.写入到新的html文件中
补充:writeFile会自动创建文件,但是不会自动创建文件夹
04
   -dist
   -public
          -index.html
   -build.js
1.读取源html文件内容
const fs =require('fs')
const path=require('path')
fs.readFile(path.join(__dirname,'public/index.html'),(err,data)=>{
    if(err) console.log(err)
    else{
      const htmlStr=data.toString()
      2.正则替换字符串
      const resultStr=htmlStr.replace(/[\r\n]g,' ') --参数g代表全局替换
      console.log(resultStr)
     3.写入到新的html文件中
     fs.writeFile(path.join(__dirname,'dist/index.html'),resultStr,err=>{
        if(err) console.log(err)
        else console.log('写入成功')
  })
   }
})
URL中的端口号
URL:统一资源定位符,简称网址,用于访问服务器里的资源
eg: http://hmajax.itheima.net:80/api/province
      协议---域名---端口号---资源路径
端口号:标记服务器里不同功能的服务程序
注意:http协议,默认访问80端口
常见的服务程序:
    Web服务程序:用于提供网上信息浏览功能
注意:0-1023和一些特定端口号被占用,我们自己编写服务程序请避开使用
http模块--创建Web服务
需求:基于http模块创建Web服务并响应内容给浏览器
1.加载http模块,创建Web服务对象
2.监听request请求事件,设置响应头和响应体
3.配置端口号并启动Web服务
4.浏览器请求(http://localhost:3000)测试
//加载http模块,创建Web服务对象
const http=require('http')
const server=http.createServer()
//监听request 请求事件,设置响应头和响应体
server.on('request',(req,res)=>{
  //设置响应头-内容类型-普通文本以及中文编码格式
  res.setHeader('Content-Type','text/plain;charset=utf-8')
  //设置响应体内容,结束本次请求与响应
  res.end('欢迎使用 Node.js和http 模块创建的Web服务')
})
server.listen(3000,()=>{
    console.log('Web 服务启动成功了')
})
在node.js上会启动一个计算机进程,来监听有没有人来请求
结束进程:ctrl+c
案例:
const fs=require('fs')
const path=require('http')
//1.基于http模块,创建WEB服务
const http=require('http')
const server=http.createServer()
server.on('request',(req,res)=>{
  //2.使用req.url获取请求资源路径,并读取index.html里字符串内容返回给请求方
  if(req.url==='/index.html'){
    fs.readFile(path.join(__dirname,'dist/index.html'),(err,data)=>{
      if(err) console.log(err)
      else{
       //设置响应内容类型-html超文本字符串,让浏览器解析成标签网页等
       res.setHeader('Content-Type','text/html;charset=utf-8')
       res.end(data.toString())
      }
})
}else{
    //其他路径,暂时返回不存在提示
    res.setHeader('Content-Type','text/html;charset=utf-8')
    res.end('你要访问的资源路径不存在')
}
})
server.listen(8080,()=>{
   console.log('Web 服务启动成功了')
})
模块化:在Node.js中,每个文件都被视为一个单独的模块
例如:js代码模块,fs,path,http,querystring
概念:项目是由很多个模块文件组成的
好处:提高代码复用性,按需加载,独立作用域
CommendJS标准,规定了模块的导入和导出
使用:
1.导出:module.exports={}
2.导出:require('模块名或路径')
模块名或路径 :
内置模块:直接写名字(例如:fs,path,http)
自定义模块:写模块文件路径(例如:./utils.js)
需求:定义utils.js模块,封装基地址和求数组总和的函数(导入到index.js这个文件中)
注意:baseURL就是基地址
utils.js:
const baseURL='http://hmajax.itheima.net'
const getArraySum=arr=>arr.reduce((sum,item)=>sum+=item,0)
//导出
module.exports={
   url:baseURL,
   arraySum:getArraySum
}
index.js
//导入
const obj=require('./utils.js')
console.log(obj)-------obj就是你导出的exports对象
const result=obj.arraySum([5,1,2,3])
console.log(result)
ECMAScript标准--默认导出和导入
需求:封装并导出基地址和求和数组元素和的函数
默认标准使用:
1.导出:export default{}
2.导入:import 变量名 form '模块名或路径'
注意:Node.js默认支持CommonJS标准语法
如需使用ECMAScript标准语法,在运行模块所在文件夹新建package.json文件,并设置{"type":"module"}
eg:
    1.utils.js
const baseURL='http://hmajax.itheima.net'
const getArraySum=arr=>arr.reduce((sum,item)=>sum+=item,0)
//默认导出
export default{
    url:baseURL,
    arraySum:getArraySum
}
   2.index.js
//默认导入
import obj from './utils.js'
console.log(obj)  ---返回的还是utils这个自定义模块的对象
const result=obj.arraySum([10,20,30])
console.log(result)
   3.package.json
{
     "type":"module"
}
------------------------------------------------------------------------------------------------
ECMAScript标准-命名导出和导入
命名标准使用:
1.导出:export修饰定义语句
2.导出:import(同名变量)form'模块名或路径'
如何选择以上两种导入和导出的方法呢???
按需加载,使用命名导出和导入
全部加载,使用默认导出和导入
需求:封装并导出基地址和求数组元素和的函数
      1.utils.js
export const baseURL='http://hmajax.itheima.net'
export const getArraySum=arr=>arr.reduce((sum,item)=>sum+=item,0)
注:想导出那个语句在前面加一个export就行
      2.index.js
//命名导入
import(baseURL,getArraySum) from './utils.js'
const result=getArraySum([10,21,33])
console.log(result)
注:导入的参数名必须和导出的变量名一致,参数还是想导入那个就写哪个
------------------------------------------------------------------------------------------------
包:将模块,代码,其他资料聚合成一个文件夹
包分类:
1.项目包:主要用于编写项目和业务逻辑
2.软件包:封装工具和方法进行使用
要求:根目录中,必须有package.json文件(记录包的清单信息)
注意:导入软件包时,引入的默认是index.js模块文件/main属性指定的模块文件
package.json中主要是以下的内容:
{
   "name":"cz_utils", -----------软件包名称
   "version":"1.0.0",  ----------------  软件包当前版本
   "description":"一个数组和字符串常用工具方法的包"----软件包简短描述
   "main":"index.js",------------软件包入口点
   "author":"itheima",----------软件包作者
   "license":"MIT" ----------软件包许可证(商用后可用作者名字宣传)
}
npm-软件包管理器
npm是Node.js标准的软件包管理器
它起初是作为下载和管理Node.js包依赖的方式,但其现在也已成为前端JavaScript中使用的工具
使用:
1.初始化清单文件:npm init -y(得到package.json文件,有则略过此命令)
2.下载软件包:npm i 软件包名称
3.使用软件包
案例:
     需求:使用dayjs软件包,来格式化日期时间
     注:package.json类似于一种日志,能查东西用
大致的过程就是:在一个项目文件夹中输入npm init -y就创建了一个package.json文件
然后再输入npm i dayjs,它就会从npm的资源库中找到dayjs包,再然后它会自动创建一个
node_modules,将这个dayjs包放到其中(软件包源码),同时npm会记录到package.json中并记录dayjs的版本号,然后还会创建一个package-lock.json文件用于固化软件包的版本(防止软件包更新后影响项目的正常运行)
server.js
const dayjs=require('dayjs')
const nowDateStr=dayjs().format('YYYY-MM-DD')
//调用软件包里的函数,它会自动返回一个对象,然后调用格式化的方法.format
console.log(nowDateStr)
------------------------------------------------------------------------------------------------
npm-安装所有依赖
问题:项目中不包含node_modules,能否在正常运行?
答案:不能,缺少依赖的本地软件包
原因:因为,自己用npm下载依赖比磁盘传递拷贝要快得多
解决:项目终端输入命令:npm i
下载package.json中记录的所有软件包
eg:一般项目给你传的有
06
   package-lock.json  (固化软件包的版本)
   package.json
   server.js
当你在项目终端中输入npm i它npm就会自动从你的package.json文件中的dependencise中下载你所缺失的软件包
npm-全局软件包 nodemon
软件包区别:
   1.本地软件包:当前项目内使用,封装属性和方法,存在于node_modules
   2.全局软件包:本机所有项目使用,封装命令和工具,存在于系统设置的位置
nodemon作用:代替node命令,监测代码更改,自动重启程序
使用:
   1.安装:npm i nodemon -g(-g代表安装到全局环境中)
   2.运行:nodemon待执行的目标js文件
Node.js总结:
Node.js模块化
概念:  每个文件当做一个模块,独立作用域,按需加载
使用:采用特定的标准语法导出和导入进行使用
注: Node.js默认支持CommonJS标准
CommonJS标准:
语法:
导出:module.exports={}  导入:require('模块名或路径')
ECMAScript标准
语法:
默认:导出:export default{}   导入:import 变量名 from '模块名或路径'
命名:导出:export 修饰定义语句 导入:import(同名变量) from '模块名或路径'
建议:
       CommonJS标准:一般应用在Node.js项目环境中
       ECMAScript标准:一般应用在前端工程化项目中
常用命令:
1.执行js文件-----node xxx
2.初始化package.json-----npm init -y
3.下载本地软件包-----npm i 软件包名 
4.下载全局软件包-----npm i 软件包名 -g
5.删除软件包-----npm uni 软件包名
6.删除全局软件包-----npm uni 软件包名 -g
------------------------------------------------------------------------------------------------
Webpack
本质上,webpack是一个用于现代JavaScript应用程序的静态模块打包工具
静态模块:指的是编写代码过程中的,html,css,js,图片等固定内容的文件
打包:把静态模块内容,压缩,整合,转译等(前端工程化)
          1.把less/sass转成CSS代码
          2.把ES6+降级成ES5
          3.支持多种模块标准语法
问题:为何不学vite?
因为:很多项目还是基于Webpack构建,并为Vue,React脚手架使用做铺垫
需求:封装utils包,校验手机号长度和验证码长度,在src/index.js中使用并打包观察
在这个案例中默认的打包入口是src文件夹下的index.js,打包出口是dist下的main.js
------------------------------------------------------------------------------------------------
修改webpack打包入口和出口
入口:
默认值是./src/index.js,但你可以通过在webpack configuration 中配置entry属性,来指定一个(或多个)不同的入口起点。例如:
webpack.config.js
module.exports={
    entry:'./path/to/my/entry/file.js',
};
出口:
    output方法
Webpack配置:影响Webpack打包过程和结果
步骤:
1.项目根目录,新建Webpack.config.js配置文件
2.导出配置对象,配置入口,进口文件的路径
3.重新打包观察
注意:只有和入口产生直接/间接的引入关系,才会被打包
自定义打包命令:
npm run build(过程中出现warning一般是没有问题的,出现err时才会有问题)
------------------------------------------------------------------------------------------------
案例:Webpack打包后的代码,作用在前端网页中使用
步骤:1.准备用户登录页面
         2.编写核心JS逻辑代码
         3.打包并手动复制网页到dist下,引入打包后的js,运行
------------------------------------------------------------------------------------------------ 
自动生成html文件
插件html-webpack-plugin: 在Webpack打包时生成html文件
安装:npm install --save-dev html -webpack-plugin
步骤:1.下载html-webpack-plugin本地软件包
         2.配置webpack.config.js------ 让 Webpack拥有插件功能
         3.重新打包观察效果
找包-->下包-->配置包
引入插件的目的是为了给Webpack提供更多的功能
打包css代码:
注: Webpack默认只识别js代码
加载器 css-loader:解析css代码
加载器 style-loader:把解析后的css代码插入DOM(页面)
步骤:
   1.准备css文件代码引入到入口文件(src/login/index.js中)(压缩转译处理等)
   2.下载 css-loader 和 style-loader 本地软件包
   3.配置webpack.config.js让Webpack拥有该加载器功能
   4.打包后观察效果
怎么安装和使用?
搜webpack中文文档,了解即可
------------------------------------------------------------------------------------------------
优化-提取css代码
插件mini-css-extract-plugin:提取css代码
注:本插件会将CSS提取到单独的文件中,为每个包含CSS的JS文件创建一个CSS文件,并且支持CSS和SourceMaps的按需加载,并且需要webpack5才能正常工作
好处:css文件可以被浏览器缓存,减少js文件体积
注意:不能和style-loader一起使用
!!!!引入插件就用require,还有new插件对象之类的
1.插件(给Webpack 提供更多功能)
2.加载器 (让webpack 识别更多模块文件内容)
------------------------------------------------------------------------------------------------优化-压缩过程
问题:css代码提取后没有压缩
解决:使用css-minimizer-webpack-plugin 插件
打包 less 代码
加载器 less-loader:把less代码编译成css代码
module:{
   rules:[
    {
         新增配置对象   
     }
]
}
步骤:1.新建less代码(设置背景图)并引入到入口文件中
         2.下载less和less-loader本地软件包
         3.配置webpack.config.js让Webpack拥有功能
注意:less-loader需要配合less软件包使用
------------------------------------------------------------------------------------------------
打包图片:
Webpack只能默认识别js,json,按道理来说是不能打包图片的
资源模块:Webpack5 内置资源模块(字体,图片等)打包,无需额外loader
资源模块(asset module)是一种资源模块,它允许使用资源文件(字体,图标等)而无需配置额外loader
步骤:1.配置webpack.config.js 让 Webpack 拥有打包图片功能
          打包出口的路径设置
          generator:{
               filename:'assets/[hash][ext][query]'
          }
          占位符[hash]对模块内容做算法计算,得到映射的数字字母组合的字符串
          占位符[ext]使用当前模块原本的占位符,例如: .png/.jpg 等字符串
          占位符 [query] 保留引入文件时代码中查询参数 (只有URL下生效)
          eg: 设置背景图片
          body {
                background: url(https://10wallpaper.com/wallpaper/2560x1600/1311/falling_star-Night_sky_HD_wallpaper_2560x1600.jpg?pname=12&cname=13)
          }
          问号后面就是[query]
注意:判断临界值默认为 8KB
         大于 8KB 文件:发送一个单独的文件并导出URL地址
         小于8KB文件:导出一个data URL (base64字符串)  //eg: src="data:image/png"
注意:js中引入本地图片资源要用 import 方式 (如果是网络图片http地址,字符串可以直接写)
         好处:小文件打包到js中,浏览器就可以减少一次http请求,让网页加载更快一点
         大文件要单独抽离出来发一次请求,因为将资源模块转换成base64字符串的时候,可能会将文件本身的体积增大20%-30%,对于大文件就不太合适了
本地引入:
             import imgObj from './assets/logo.png'
             const theImg= document.createElement('img')
             theImg.src=imgObj
             document.queySelector('.login-wrap').appendChild(theImg)
error.response.data.message
搭建开发环境:
问题:之前改代码,需要重新打包才能运行查看,效率很低
开发环境:配置webpack-dev-server 快速开发应用程序
作用:启动Web服务,自动检测代码变化,热更新(替换变化的代码,自动更新网页)到网页
注意:dist目录和打包内容是在内存里(跟新快)
步骤:
      1.下载webpack-dev-server 软件包到当前项目
       npm i webpack-dev-server --save-dev
      2.设置模式为开发模式,并配置自定义命令
      module.exports={
        //......
     mode:'development'
     }
     配置自定义命令(用于启动这个软件包)
     "scripts":{
       "build":"webpack",
       "dev": "webpack serve --open" (open自动弹出你本机的默认浏览器)
     }
     3.使用npm run dev 来启动开发服务器,试试热更新效果
     注意1:webpack-dev-server 借助 http 模块创建 8080 默认 Web 服务
     注意2:默认以 public 文件夹作为服务器根目录
     它默认是访问的是public下的index.html文件,如果public文件夹没有index.html这个名,就要自己手动进行访问
     注意3:webpack-dev-server 根据配置,打包相关代码在内存当中,以 output.path 的值作为服务器根目录(所以可以直接自己拼接访问 dist 目录下的内容)
<script>
   //webpack-dev-server 的 Web 服务,自动跳转到我们规定的首页, 就不用手动进行更改
   location.href='/login/index.html'
</script>
打包模式:告知 Webpack 使用相应模式的内置优化
分类:
开发模式----development----调试代码,实时加载,模块热替换等----本地开发
生产模式----production----压缩代码,资源优化,更轻量等----打包上线
设置:
方式1:在webpack.config.js配置文件设置mode选项
module.exports={
   //...
  mode:'production'
};
方式2:在package.json命令行设置 mode 参数
"scripts":{
   "build":"webpack --mode=production",  (打包输出到dist文件夹下) npm run build 极致压缩,体积更小
   "dev":"webpack serve --mode=development" (在内存里打包) npm run dev 模块化压缩(模块热替换更快一点)
},
注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
------------------------------------------------------------------------------------------------
前端-注入环境变量
需求:前端项目中,开发模式下打印语句生效,生产模式下打印语句失效
问题:cross-env 设置的只在Node.js环境生效,前端代码无法访问 process.env.NODE_ENV
解决:使用Webpack 内置的 DefinePlugin 插件
在webpack.config.js中配置:
const webpack=require('webpack')
再在plugins:[ ]数组中new webpack.DefinePlugin({...})
index.js:
   if(process.env.NODE_ENV==='production'){
        console.log=function() { }
}
console.log('开发模式下好用,生产模式下失效')
------------------------------------------------------------------------------------------------开发环境调错 -source map
问题:代码被压缩和混淆,无法正确定位源代码位置(行数和列数)
source map: 可以正确追踪 error 和 warning 在原始代码的位置
设置:webpack.config.js 配置 devtool 选项
eg: module.exports={
   //...
   devtool:'inline-source-map'
}
inline-source-map选:把源码的位置信息一起打包在js文件内
注意:source map 仅适用于开发环境,不要在生产环境使用(防止被轻易查看源码位置)
const config={}
if(process.env.NODE_ENV==='development'){
    config.devtool='inline-source-map'  //给config对象增加devtool属性
}
module.exports=config   //导出
------------------------------------------------------------------------------------------------
解析别名 alias
解析别名:配置模块如何解析,创建import 引入路径的别名,来确保模块引入变得更简单
注:就是改路径别名
例如:原来路径如下,比较长而且相对路径不安全
import {checkPhone,checkCode} from '../src/utils/check.js'
解决:在webpack.config.js 中配置解析别名@来代表src绝对路径
const config={
     //...
     resolve:{  ----这个选项是解析的意思
        alias:{   ----这个选项是别名的意思
           '@':path.resolve(__dirname,'src') ----这个@就是src的意思
           //dirname 拿的是根目录
       }
    }
}
替换后:import {checkPhone,checkCode} from '@/utils/check.js'
import youAxios from '@/utils/request.js'
console.log(youAxios)  ---(返回的是一个wrap的函数)
------------------------------------------------------------------------------------------------优化-CDN使用
CDN定义:内容分发网路,指的是一组分布在各个地区的服务器
作用:把静态资源文件/第三方库放在 CDN 网络中各个服务器,供用户就近请求获取
好处:减轻自己服务器请求压力,就近请求物理延迟低,配套缓存策略
------------------------------------------------------------------------------------------------多页面打包
单页面:单个html文件,切换DOM的方式实现不同业务逻辑展示
多页面:多个html文件,切换页面实现不同页面逻辑展示
步骤:1.准备源码(html,css,js)放入相应位置,并改用模块化语法导出
          2.下载form-serialize 包并导入到核心代码中使用
          3.配置webpack.config.js 多入口和多页面的设置
output:{
   filename:'./[name]/index.js'  //使用[name]动态导出
}
//注意:没有导出和导入,只是为了让目标 js 代码被一起打包进来,参与html 最后的运行
import '@/utils/auth.js' 
------------------------------------------------------------------------------------------------
优化-分割公共代码
需求:把2个以上页面引用的公共代码提取
步骤:
      1.配置webpack.config.js的splitChunks分割功能
//代码分离
splitChunks:{
    chunks:'all',  //所有模块动态非动态移入的都分割分析
    cacheGroups:{  //分隔组
      commons:{   //抽取公共模块
         minSize:0,   //抽取的chunk最小大小字节
         minChunks:2,  //最小引用数
         reuseExistingChunk:true,  //当前chunk 包含已从主bundle 中拆分出的模块,则它将被重用
         name(module,chunks,cacheGroupKey){   //分离出模块文件名
            const allChunksNames=chunks.map((item)=>item.name).join('~') //,模块名1~模块名2
            return `./js/${allChunksNames}`  //输出到 dist 目录下位置
}
}
}
}
注:webpack如何将代码抽象的构建成一个语法树,就需要深入往下了解了
------------------------------------------------------------------------------------------------
GIT 初识---管理代码版本
概念:一个免费开源,分布式的代码版本控制系统,帮助开发团队维护代码
作用:记录代码内容,切换代码版本,多人开发时高效合并代码内容
如何学:
个人本机使用:GIT 基础命令和概念
多人共享使用:团队开发同一个项目的代码版本管理
配置:用户名和邮箱,应用在每次提交代码版本时表明自己身份
命令:
      git config --global user.name "itheima"
      git config --global user.email "itheima@itcast.cn"
设置完成后输入 git config --list 查看一下清单
下载完成后:
              git -v
查看版本号,验证是否下载成功
GIT 仓库:记录文件状态内容的地方,存储着修改的历史记录
创建:
1. 把本地文件夹转换成Git仓库:命令git init
删除本地的Git仓库 rm -rf Git仓库名
2.从其他服务器上克隆Git仓库
------------------------------------------------------------------------------------------------
Git的三个区域:
Git使用时:
工作区:实际开发时操作的文件夹
暂存区:保存之前的准备区域(暂存改动过的文件)
版本库:提交并保存暂存区中的内容,产生一个版本快照
大致流程就是:
在git_study(工作区)中生成一个html文件,使用git add命令提交到.git/index(暂存区),
最后使用 git commit提交到.git/objects(版本库)中进行一次代码版本的迭代,产生一次版本记录
命令:
      git add 文件名-------暂存指定文件
      git add .------暂存所有改动的文件
      git commit -m "注释说明"------提交并保存,产生版本快照
      git ls-files---查看暂存区里有哪些文件
------------------------------------------------------------------------------------------------
Git 文件状态
Git 文件 2 种状态:
未跟踪:新文件,从未被Git管理过
已跟踪:Git已经知道和管理的文件
使用:修改文件,暂存,提交保存记录,如此反复
未跟踪(U)---从未被Git管理过---新文件
新添加(A)---第一次被Git暂存---之前版本记录无此文件
未修改(")---三个区域统一---提交保存后
已修改(M)---工作区内容变化---修改了内容产生
注:使用git status -s 查看文件状态,并最终提交
第一列是暂存区状态
第二列是工作区状态
Git 暂存区使用
暂存区:暂时存储,可以临时恢复代码内容,与版本库解耦
暂存区->覆盖->工作区,命令:git restore 目标文件(注意:完全确认覆盖时使用)
注:就是去拿暂存区临时保存的文件,返还给工作区使用
从暂存区移除文件,命令:git rm --cached 目标文件 (取消暂存,改为未跟踪状态)
查看之前所有的的提交历史(git log --online)
------------------------------------------------------------------------------------------------
Git 回退版本
概念:把版本库某个版本对应的内容快照,恢复到工作区/暂存区
查看提交历史:git log --oneline
回退命令:
git reset --soft 版本号(保留)
将git仓库里面的版本回退到工作区和暂存区的时候,原来工作区和暂存区里的文件会被保存,只是文件状态变为了“A”
注意:git reset --soft只会从git仓库回退到暂存区
git reset --hard 版本号 (覆盖)
覆盖了原来工作区和暂存区的文件,只剩下刚刚回退的文件
git reset --mixed 版本号(与git reset等价)
只覆盖暂存区里的文件,原来工作区的文件被保存,工作区的文件状态改为"未跟踪"
注意1:只有记录在版本库的提交记录才能恢复
注意2:回退后,继续修改->暂存->提交操作即可(产生新的提交记录过程)
查看提交历史:
git reflog --oneline
git reflog --oneline和git log --oneline的区别???
两者的主要区别在于,git reflog更注重于本地仓库的操作记录,包括已经被删除或重置的提交,而git log则更侧重于提交历史的查看。
删除文件
在工作区中直接更新到暂存区就行
忽略文件
概念:.gitignore 文件可以让git彻底忽略跟踪指定文件
目的:让git 仓库更小更快,避免重复无意义的文件管理
例如:1.系统或软件自动生成的文件
         2.编译产生的结果文件
.gitignore中的文件配置就是要忽略文件配置
eg:
     #忽略 npm 下载的第三方包
     node_modules
     #忽略分发文件夹(node编译产生的文件)
     dist
     #忽略 VSCode 配置文件
     .vscode
    #忽略密钥文件
    *.pem
    *.cer
    #忽略日志文件
    *.log   
分支
概念:本质上是指向提交节点的可变指针(容器),默认名字是 master
不断地提交代码版本master就会更新,默认是指向最新一次的代码版本
注意:HEAD指针影响工作区/暂存区的代码状态
由于git仓库可能出现多个分支,使用head指针指向的分支,就是你现在工作区/暂存区的代码状态
场景:开发新需求/修复Bug,保证主线代码随时可用,多人协同开发提高效率
需求:创建内容列表content 分支,并产生3次提交记录
步骤:1.创建分支命令:git branch 分支名
         2.切换分支命令:git checkout 分支名
         3.工作区准备代码并暂存提交,重复三次
在这个分支中进行开发就用head指向这个分支名
git branch----查看当前git仓库的分支名
然后在工作区进行开发相关的模块

1.什么是 Git 分支?
指针,指向提交记录
2.HEAD指针的作用
影响暂存区和工作区的代码
3.如何创建和切换指针
git branch 分支名
git checkout 分支名
------------------------------------------------------------------------------------------------需求:新建login-bug分支,做两次提交记录(对手机号长度,验证码长度做判断)
步骤:
1.切回到主分支:git checkout master  (head指针先指回master)
2.创建新分支:git branch login-bug
3.切换新分支:git checkout login-bug  (head指针再指向login-bug)
4.修改代码,暂存,提交产生新版本记录
分支-合并与删除
需求:把login-bug 合并回到master分支并删除login-bug 分支
步骤:
1.切换到要合入的分支上:git checkout master
2.合并其他分支过来:git merge login-bug
合并之后head和master就会更新到最近的版本之下,
但是login-bug指针还是会指向这个最近代码版本
3.删除合并后的分支指针:git branch -d login-bug
------------------------------------------------------------------------------------------------f分支-合并与提交
发生于原分支产生了新的提交记录后,再合并回去时发生时,会自动生成一次新的提交
步骤:
1.切回到要合入的分支上:git checkout master
2.合并其他分支过来:git merge content
3.删除合并后的分支:git branch -d content
Fast -forward(快进):就是前进了几个版本意思
分支-合并冲突
在不同分支下对同一个文件进行更改,合并时就会出现合并冲突
概念:不同分支中,对同一个文件的同一部分修改,Git无法干净的合并,产生合并冲突
解决:
1.打开VSCode找到冲突文件并手动解决
2.解决后需要提交一次记录
场景:
需求1:基于master新建publish分支,完成发布文章业务,然后修改页面的html文件的title标签,并提交一次
需求2:切换到master,也在修改内容页面的html文件的title标签,并提交一次
冲突:把publish分支合并到master回来,产生合并冲突
------------------------------------------------------------------------------------------------
token鉴权;axios拦截器;富文本编辑器,分页切换
------------------------------------------------------------------------------------------------
Git 常用命令-总结
git -v   查看git版本
git init  初始化git仓库
git add 文件标识 ----暂存某个文件----文件标识以终端为起始的相对路径
git add .   暂存所有文件
git commit -m '说明注释'---提交产生版本记录---每次提交,把暂存区内容快照一份
git status  查看文件状态-详细信息
git status -s 查看文件状态-简略信息 --第一列是暂存区状态,第二列是工作区状态
git ls-files 查看暂存区文件列表
git restore 文件标识  ---从暂存区恢复到工作区---如果文件标识为.则恢复所有文件
git rm --catched 文件标识 ---从暂存区移除文件---不让git跟踪文件变化
git log   查看提交记录-详细信息
git log --oneline  查看提交记录-简略信息     版本号 分支指针 提交时说明注释
git reflog --online 查看完整历史-简略消息     包括提交,切换,回退第等所有记录
git reset 版本号   默认是--mixed模式
git branch 分支名              创建分支
git branch                     查看本地分支
git branch -d 分支名      删除分支   请确保记录已经合并到别的分支下,再删除分支
git checkout 分支名     切换分支
git checkout 分支名     (本质就是切换head指针的指向)
git checkout -b 分支名   创建并立刻切换分支
git merge 分支名   把分支提交历史记录合并到当前所在分支
------------------------------------------------------------------------------------------------
Git 远程仓库
概念:托管在因特网或其他网路中的你的项目的版本库
作用:保存版本库的历史记录,多人协作
创建:公司自己的服务器/第三方托管平台(Gitee,GitLab,GitHub...)
需求:创建远程版本库,并把本地Git仓库推送上去保存
步骤:
1.注册第三方托管平台网站账号
2.新建仓库得到远程仓库Git地址
3.本地Git仓库添加远程仓库原点地址
命令:git remote add 远程仓库别名 远程仓库地址
eg: git remote add origin https://gitee.com/lidongxu/work.git
4.本地Git 仓库推送版本记录到远程仓库
   命令:git push -u 远程仓库别名 本地和远程分支名
   eg: git push -u origin master
   完整写法:git push --set-upstream origin master:master
-set-upstream: 其实是建立了某种通道
删除远程仓库的别名:git remote remove origin
凭据管理器(改账号用的)
------------------------------------------------------------------------------------------------
Git 远程仓库-克隆
克隆:拷贝一个Git 仓库到本地,进行使用
命令:git clone 远程仓库地址,例如:git clone https://gitee.com/lidongxu/work.git
效果:在运行命令所在文件夹,生成work项目文件夹(包含版本库,并映射到暂存区和工作区)
注意1:Git 本地仓库已经建立好和远程仓库的链接
注意2:仓库公开随意克隆,推送需要身为仓库团队成员
多人协同开发
需求:小传新代码共享给小智
步骤:
1.小传开发代码->工作区->暂存区->提交->拉取(可选)->推送
2.小智->拉取(后续也可以开发代码->...->推送)
3.想要看到别人同步上去的最新内容:git pull origin master等价于
  git fetch origin master:master (获取远程分支记录到本地,未合并)
  git merge origin/master  (把远程分支记录合并到所在分支下)
从无到有----git clone
如果本地有git仓库,就用git pull

推送过一次下次就可以直接 git push origin master
git pull origin master:master    远程和本地一样就可以简写成
git pull orgin  master
------------------------------------------------------------------------------------------------
VSCode 中使用 Git 
使用:源代码管理,进行暂存,撤销,对比差异,提交等操作(图形化的操作)
------------------------------------------------------------------------------------------------
需求:把Webpack压缩好的 dist 分发文件夹网页,部署到码云上,开启page服务在互联网中浏览
步骤:
1.初始化本地 Git 仓库(这次是非空文件夹-配套素材 dist 文件夹)
2.初始化远程 Git 仓库(这一次也是非空的)
3.本地配置远程仓库链接
4.本地拉拢合并一下(确认本地要包含远程内容时使用)
5.本地推送到远程 Git 仓库
6.开启 page 网页服务得到地址浏览
强制合并--git pull --rebase 远程仓库 本地分支名字
注:强制合并远程仓库和本地分支的代码
------------------------------------------------------------------------------------------------
续Git常用命令
命令-作用-注意
git remote add 远程仓库别名 远程仓库地址----添加远程仓库地址----别名'唯一',地址是.git结尾的网址
git remote -v   查看远程仓库地址
git remote remove 远程仓库别名    删除远程仓库地址
git pull 远程仓库别名 分支名    --拉取----完整写法:git pull 远程仓库别名 远程分支名:本地分支名
等价于:git fetch 和 git merge
git push 远程仓库别名 分支名 --推送---完整写法:git push 远程仓库别名 本地分支名:远程分支名
-u:建立通道后以后可以简写 git push
git pull --rebase 远程仓库别名 分支名 --拉取合并--合并没有关系的记录
git clone 远程仓库地址     克隆       从0得到一个远程的Git仓库到本地使用

当时写的时候, 是边看视频边记的, 感觉写的挺详细的, 但是有点乱....

感谢大家的点赞和关注,你们的支持是我创作的动力!

 


网站公告

今日签到

点亮在社区的每一天
去签到