07 前端框架前置ajax node webpack git

0 说明

代码敲时方恨少,边学边练亏不了
B站黑马视频教程链接
github代码笔记

1 AJAX

Asynchronous JavaScript And XML:异步的JS和XML。

1.1 axios库

基于XMLHttpRequest对象
标准代码段示例:

axios({
            url:'http://hmajax.itheima.net/api/register',
            method:'post',
            data:{
                username:'ithei202308',
                password:'123456'
            }
        }).then((result) => {
            console.log(result);
        }).catch(error => {
                alert(error.response.data.message)
        })
  })          

1.2 响应状态码

1信息
2成功
3重定向
4客户端错误
5服务端错误

1.3 API文档使用

黑马提供的api文档,整洁漂亮,值得借鉴

1.4 form-serialize插件

插件根据元素的name属性来获取

// 3.2 使用form插件的 serialize函数,收集登录表单里用户名和密码
// 3.2.1 获取表单对象
const form = document.querySelector('.login-form')
// 3.2.2 表单对象传入serialize函数,并传入对象参数,获取表单的属性对象
const data = serialize(form, { hash: true, empty: true })
// console.log(data)
// {username: 'itheima007', password: '7654321'}
// 学习阶段为了省略而省略的做法,代码自己都难读懂,着实不建议
// const { username, password } = data:对象的解构&赋值
// 解构&赋值的语法:旧变量名:新变量名
const { username:username, password:password } = data

1.4.1 案例01 登录框案例

p12视频中的alert相关bootstrap链接
案例中涉及到的方法属性:
函数传参,匿名函数(带参)
三元表达式:
let bgc_style = is_success ? 'alert-success' : 'alert-danger'
ajax的axios方法then,catch,
对象获取querySelector与绑定addEventListener,
定时器setTimeout等

1.4.2 案例02 图书管理

1.4.2.1 添加逻辑

坑:点击新增后的清除表单,关闭modal弹窗,获取刷新之后的逻辑应该在回调函数中体现,否则影响事件监听的异步代码的执行顺序

axios({
    url: 'http://hmajax.itheima.net/api/books',
    method: 'post',
    data: {
     // 不用解构,直接展开运算符就行
      ...addBook,
      creator: creator,
    }
  }).then(result => {
    addForm.reset()
    addModal.hide()
    // 点击事件异步,所以需要在里面刷新请求
    getBooksList()
  })
1.4.2.2 删除逻辑
// 活动添加的html标签,用父级的委托来实现点击事件监听
document.querySelector('.list').addEventListener('click',e=>{
  // data-id自定义的id属性保存在dataset属性里
  const theId = e.target.dataset.id
1.4.2.3 修改逻辑
axios({
    url: `http://hmajax.itheima.net/api/books/${editBookInfo.id}`,
    method: 'put',
    data: {
    // 添加图书逻辑中的 addBook不含id,可以直接展开。这里的包括id,不能直接展开运算符,可以做解构,直接点方法也可以更直白
      bookname: editBookInfo.bookname,
      author: editBookInfo.author,
      publisher: editBookInfo.publisher,
      creator
    }
1.4.2.4 案例总结

1、bootstrap插件和form-serialize插件的基本使用:

// bootstrap
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)
// form
const editDom = document.querySelector('.edit-form')
const editBookInfo = serialize(editDom, { hash: true, empty: true })

2、几种ajax下axios的请求methods;修改逻辑结合了添加的逻辑,对象的解构,展开运算符等方法

1.4.3 案例03 图片上传处理

FormData()方法生成图片对象,

const fd = new FormData()
fd.append('img',e.target.files[0])

对应的post方法上传时的data参数直接填对象fd就行,绑定upload上传的change事件

const fd = new FormData()
            fd.append('img',e.target.files[0])
            // 提交
            axios({
                url:'http://hmajax.itheima.net/api/uploadimg',
                method:'post',
                data:fd,
            })

案例里设计本地存储与读取方法的使用:

 // 本地存储地址链接
        localStorage.setItem('imgUrl',result.data.data.url)
    }).catch((err) => {
        pass
    });
})
const imgUrl = localStorage.getItem('imgUrl')
imgUrl && (document.body.style.backgroundImage = `url(${imgUrl})`)

1.4.4 案例04 个人信息管理

1.4.4.1 获取个人信息

同案例02的图书管理里的修改内容的获取逻辑类似,也有返回结果对象的foreach遍历,展示部分代码:

const userObj = result.data.data
const keys = Object.keys(userObj)
keys.forEach(key=>{

此外,针对性别代码的单选框的选定状态,也借由中间变量来过渡确定checked属性,这部分算是目前阶段比较好理解的处理方法,部分代码:

const genderList =document.querySelectorAll('.gender')
const genderNum = userObj[key]
genderList[genderNum].checked = true
1.4.4.2 修改个人信息

修改类似图书管理的修改,不同之处使用了bootstrap的Toast方法弹窗,使用方法类似Modal方法

1.5 XMLHttpRequest(XHR)对象

1.5.1 XHR基础

axios的基础,简单的get请求使用XHR,记得open方法配置请求方法和url后紧接着send调用,然后再写loadend的回调监听,不然容易忘记:

		const myxhr = new XMLHttpRequest()
        // 使用open方法配置请求,send发送请求
        myxhr.open('GET', 'http://hmajax.itheima.net/api/province')
        // loadend事件接收响应
        myxhr.addEventListener('loadend', () => {
            console.log(myxhr.response);
            // 得到的是json字符串,浏览器控制台显示为黑色,需要JSON.parse转换成对象的数据结构
            const prov = JSON.parse(myxhr.response).list
            document.querySelector('.my-p').innerHTML = prov.join('<br>')
        })
        myxhr.send()

1.5.2 XHR带参post

相比基础的xhr请求,参数post需要多设置几处,setRequestHeader,send( JSON.stringify后的json字符串)如代码所示:

		myxhr.setRequestHeader('Content-type','application/json')
            const data = {
                'username':'heima20230831',
                'password':'123456'
            }
            const mydata = JSON.stringify(data)
            myxhr.send(mydata)

1.6 Promise方法-请求状态管理

Promise后边的vue会涉及到
创建对象,携带参数resolve,reject
promise对象的3种状态(promiseState):pendding,resolve(fulfilled),reject(rejected),对象new创建时候立即执行,然后进如pedding,等待执行的状态结果,再进行then和catch回调函数的逻辑运行
XHR和Promise结合的方法实现了404错误页面的展示,部分代码如下:

					if (myxhr.status>=200 && myxhr.status<300) {
                    resolve(JSON.parse( myxhr.response))
                } else{
                    reject(new Error(myxhr.response))
                }
            })
            myxhr.send()
        })
         // 3. p对象针对xhr请求结果进行逻辑处理
         p.then(result=>{
            document.querySelector('.pname').innerHTML=result.list.join('<br>')
         }).catch(error=>{
            console.dir(error);
            document.querySelector('.pname').innerHTML=error.message
         })

1.6.1 案例05 自己封装myAxios方法

主要是XHR对象的4步走:new,open,监听loadend,send;Promise的resolve,reject判断借由then和catch方法控制响应状态
处理参数/响应的JSON.parse与stringify转换,URLSearchParams对象及toString方法等;
这些使用流程逻辑理清,即可简单的实现自己的myAxios方法

1.6.2 案例06 天气预报

涉及的知识点:
1、list的map,join遍历
2、事件绑定动态生成元素时,监听父级,利用(自定义)属性判断点击对象区域
3、搜索栏切换地址,是目前前后端区分的最大感受:前端js只是呈现逻辑的实现,后端处理的数据返回逻辑

1.6.3 promise链式调用

axios中return一个axios对象,返回的axios对象再链式调用then方法处理成功后的逻辑

1.6.4 async函数和await

强制等待,更符合代码阅读习惯

// 1. 定义async修饰函数
async function getData() {  
    // 2. await等待axios请求的Promise对象成功的结果
    const pObj =  await axios({url:'http://hmajax.itheima.net/api/province'})

配合try…catch捕获异常,error一般配合console.dir(非log)打印console.dir(error)

1.7 事件循环

可以认为是假的多线程,es6后promise对象让js引擎也可以发起“异步”任务
微任务:js引擎执行的异步任务
promise对象的then和catch方法
宏任务:浏览器环境执行的异步任务
script里的js脚本,定时器setTimeout、setInterval,ajax请求,用户交互事件等。
执行时,微任务队列里的逻辑代码 优先于宏任务队列

1.7.1 案例07 一二级商品展示

案例精髓在于promise.all方法和map的多层嵌套返回待渲染的字符串

1.7.2 案例08 学习反馈 省市区三级联动

async函数和await就近原则,放在箭头函数和对应的axios请求前就可以。
这里的嵌套map方法,如果单独出去再把结果的str拼接回来会更容易读懂

return `<div class="item">
         <h3>${dataObj.name}</h3>
          <ul>
              ${dataObj.children.map(item2 => {
                  return `<li>
                  <a href="javascript:;">
                      <img src=${item2.picture}>
                      <p>${item2.name}</p>
                  </a>
              </li>`
              }).join('')
              }
          </ul>
      </div>`

1.8 案例09 后台管理

0、项目目录
1、登录token验证
2、axios统一的请求响应拦截器

// 请求拦截器
axios.interceptors.request.use(config => {
    // Do something before request is sent
    const token = localStorage.getItem('token')
    token && (config.headers.Authorization = `Bearer ${token}`)
    return config;}

3、wangeditor富文本编辑器的使用
4、querySelectorAll查询出来的伪数组的foreach遍历,check单选框的change监听事件

// 筛选状态标记数字->change事件->绑定到查询参数对象上
document.querySelectorAll('.form-check-input').forEach(radio => {
    radio.addEventListener('change', e => {
        // console.log(e.target.value);
        queryObj.status = e.target.value
    })
})

5、编辑回显

  • location和URLSearchParams方法获取查询参数字符串
  • 注意对象的forEach遍历参数位置对应的是value和key
  • Object.keys来遍历keys,判断筛选,赋值: Object.keys(dataObj).forEach(key => {...},这里的结果已经是列表了,所以后边是对keys列表的遍历
  • 非id,class的属性选择器用[]
document.querySelector(`[name=${key}]`).value = dataObj[key]

回显有点绕,展示完整代码:

	; (function () {
    // location和URLSearchParams方法获取查询参数字符串
    const paramsStr = location.search
    const params = new URLSearchParams(paramsStr)
    // 注意对象的forEach遍历参数位置对应的是value和key
    params.forEach(async (value, key) => {
        if (key === 'id') {
            document.querySelector('.title span').innerHTML = '修改文章'
            document.querySelector('.send').innerHTML = '修改'

            // 回显
            const res = await axios({
                url: `/v1_0/mp/articles/${value}`
            })
            console.log(res);
            // 根据id返回的文章对象,构建需要返回显示的对象内容
            const dataObj = {
                channel_id: res.data.channel_id,
                title: res.data.title,
                rounded: res.data.cover.images[0],
                content: res.data.content,
                id: res.data.id
            }

            // Object.keys来遍历keys,判断筛选,赋值
            Object.keys(dataObj).forEach(key => {
                if (key === 'rounded') {
                    // 判断封面是否有
                    if (dataObj[key]) {
                        // 类似发布时候的属性设置
                        document.querySelector('.rounded').src = dataObj[key]
                        document.querySelector('.rounded').classList.add('show')
                        document.querySelector('.place').classList.add('hide')
                    } else if (key === 'content') {
                        editor.setHtml(dataObj[key])
                    } else {
                        // 非id,class的属性选择器用[]
                        document.querySelector(`[name=${key}]`).value = dataObj[key]
                    }
                }
            })
        }
    })
})()

6、同一个按钮,两种逻辑发布和修改,用条件判断来实现排他逻辑:

 if (e.target.innerHTML !== '修改') return

2 node&webpack

node和浏览器v8的区别:
浏览器:document,window,XMLHttpRequest
node:fs,path,http
公有:ECMAScript语法:String,Number,setTimeout,console,Promise这些

2.1 fs文件模块

Node.js 代码中,相对路径是根据终端所在路径来查找的.
__dirname 内置变量(获取当前模块目录-绝对路径),path.join() 会使用特定于平台的分隔符使绝对路径和相对路径相结合。

const path = require('path')
// console.log(__dirname);
fs.readFile(path.join(__dirname,'../test.txt'),(err,data)=>{.....}
fs.writeFile(path.join(__dirname,'disk/index.html'),resStr,err=>{....}

需要说明的是,这个命令是__dirname是要写在js文件中,运行时才会执行。直接在终端的node交互式运行环境REPL里,__dirname is not defined.是不行的.
__dirname相关链接:我也是傻傻的在终端执行__dirname,结果报错,查了好久的报错帖子,嘿嘿,蠢的要死哟。链接里重点理解就ok:

他抱怨在node的交互式运行环境REPL里,__dirname is not defined.
原因其实很简单,其他网友也提到了:__dirname意思是当前脚本文件所在的目录,在REPL下,连脚本文件都不存在,自然也不存在__dirname了。

2.2 配置web服务

// 1. 引入http,创建服务应用
const http = require('http')
const server = http.createServer()
// 2.监听request请求,设置响应头和响应体
server.on('request', (req, res) => {
    // 响应头
    res.setHeader('Content-Type', 'text/plain;charset=utf-8')
    // 响应体
    res.end('hello node.js')
})
// 3.配置端口,启动服务
server.listen(3001, () => console.log('node启动web服务'))

2.3 node模块化标准

2.3.1 CommonJS 标准

导出:module.exports = {}
导入:require(‘模块名或路径’)

2.3.2 ECMAScript 标准 - 默认导出和导入

导出:export default {}
导入:import 变量名 from ‘模块名或路径’
注意:Node.js 默认支持 CommonJS 标准语法
如需使用 ECMAScript 标准语法,在运行模块所在文件夹新建 package.json 文件,并设置 { “type” : “module” }

2.3.2 ECMAScript 标准 - 命名导出和导入

命名标准使用:
导出:export 修饰定义语句
导入:import { 同名变量 } from '模块名或路径‘
如需使用 ECMAScript 标准语法,在运行模块所在文件夹新建 package.json 文件,并设置 { “type” : “module” }

2.4 npm包管理器

初始化项目清单文件 package.json 命令
npm init -y
下载软件包的命令
npm i 软件包名字
删除
npm -uni 包name
初始化根据package.json文件里的dependencies包名,用npm i 下载对应的包

2.4.1 全局软件包 nodemon

软件包区别:
本地软件包:当前项目内使用,封装属性和方法,存在于 node_modules
全局软件包:本机所有项目使用,封装命令和工具,存在于系统设置的位置
nodemon 作用:替代 node 命令,检测代码更改,自动重启程序
使用:
安装:npm i nodemon -g(-g 代表安装到全局环境中)

2.5 webpack 前端工程化

npm i webpack webpack-cli --save-dev,package.json文件里需要配置:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"webpack"

  },

npm run 名字(build)运行webpack打包程序

2.5.1 入口与出口

外层目录下的webpack.config.js文件设置

module.exports = {
    // 入口
  entry: path.resolve(__dirname,'./src/login/index.js'),
    // 出口
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: './login/index.js',
    clean:true
  },
};

2.5.2 html自动打包插件

HtmlWebpackPlugin插件
npm i html-webpack-plugin --save-dev
打包html的引用配置:

plugins:[
    new HtmlWebpackPlugin({  // Also generate a test.html
      // 绝对路径
      filename: path.resolve(__dirname,'dist/login/index.html'),
      template: path.resolve(__dirname,'public/login.html')
    })
  ]

2.5.3 css加载器

1、引入css到对应的js文件中,
2、配置,这里的配置遵从output的规则:

module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
2.5.3.1 css抽离打包

交互多为js请求,为了单独抽离css,也可多线程分别下载
MiniCssExtractPlugin,配置不写了,详见官方文档

2.5.3.2 css抽离压缩打包

css-minimizer-webpack-plugin

2.5.3.3 less

npm install --save-dev less-loader
开发文档
小做更改,因为前面用到了mini的css,MiniCssExtractPlugin.loader进行替换style-loader:

{
        test: /\.less$/i,
        use: [
          // compiles Less to CSS
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
        ],
      }
2.5.3.4 资源打包

内置模块,部分配置展示,详见开发文档

{
        test: /\.(png|jpg|jpeg|gif)$/i,
        type: 'asset',
        generator: {
          filename: 'static/[hash][ext][query]'
        }
      },

2.5.4 开发环境

npm install --save-dev webpack-dev-server
package.json文件里自定义script属性的dev值
module.exports 里设置
// 开发模式,默认找public文件夹的资源
mode:‘development’,

2.5.5 两种开发模式

在 package.json 命令行设置 mode 参数

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "cross-env NODE_ENV=production webpack --mode=production",
    "dev": "cross-env NODE_ENV=development webpack serve --open --mode=development"
  },

注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
下载 cross-env 软件包到当前项目
配置自定义命令,传入参数名和值(会绑定到 process.env 对象下)
在 webpack.config.js 区分不同环境使用不同配置

use: [process.env.NODE_ENV = 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, "css-loader"],

2.5.6 前端参数注入

webpack 中配置 DefinePlugin 插件

2.5.7 source-map开发环境调错

问题:error 和 warning 代码的位置和源代码对不上,不方便我们调试!

  • 解决:启动 webpack 的 source-map 资源地图功能
  • 在 webpack.config.js 配置 devtool 选项和值开启功能(注意:只在开发环境下使用)

2.5.8 cdn

在 html 中引入第三方库的 CDN 地址并用模板语法判断

<% if(htmlWebpackPlugin.options.useCdn){ %>
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css">
  <% } %>

配置 webpack.config.js 中 externals 外部扩展选项(防止某些 import 的包被打包)

// 生产环境下使用相关配置
if (process.env.NODE_ENV === 'production') {
  // 外部扩展(让 webpack 防止 import 的包被打包进来)
  config.externals = {
    // key:import from 语句后面的字符串
    // value:留在原地的全局变量(最好和 cdn 在全局暴露的变量一致)
    'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
    'axios': 'axios',
    'form-serialize': 'serialize',
    '@wangeditor/editor': 'wangEditor'
  }
}
new HtmlWebpackPlugin({  // Also generate a test.html
      // 绝对路径
      useCdn: process.env.NODE_ENV === 'production', // 生产模式下使用 cdn 引入的地址

2.5.9 多页面打包发布

目标16 多页面打包
准备源码(html,css,js)放入相应位置,并改用模块化语法导出
下载 form-serialize 包并导入到核心代码中使用(略过)
配置 webpack.config.js 多入口和多页面的设置
重新打包观察效果

2.5.10 分割公共部分打包

// 代码分割公共部分打包
    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太杂了,一塌糊涂,后边碰到了再补吧

3 git

3.1 初始配置

初始配置:用户名和邮箱,应用在每次提交代码版本时表明自己身份
命令:
git config --global user.name “itheima”
git config --global user.email “itheima@itcast.cn”

3.2 Git 仓库(repository)

:记录文件状态内容的地方,存储着修改的历史记录
创建:
1、把本地当前的文件夹转换成 Git 仓库:命令 git init
2、从其他服务器上克隆 Git 仓库

3.3 3个主要区域

git pull—>(工作区)git add—> git ls -files ,git status -s(查看暂存区,文件均为跟踪状态)—>git commit -m “注释” (版本库)—> git push (远端)
git restore 暂存区恢复原来版本,覆盖工作区
git rm --cached 目标文件: 取消暂存,不更改工作区
git log --onelline
git reflog --oneline 查看提交历史的版本号,包括hard回退过的版本号

3.4 回退

git reset --soft 退回版本,工作区和暂存区的文件尽量保留,未被跟踪的状态
git reset --hard 退回版本,工作区和暂存区的文件消失
git reset --mixed 退回版本,工作区的文件尽量保留,未被跟踪的状态,暂存区相应记录消失

3.5 分支

git branch 创建分支名字
git checkout 切换分支名字
git branch -d 要删除的分支

  • 合并分支
    选定现有分支,git merge 要合并进来的分支 ,遇到冲突先解决再提交

3.6 远程仓库

1、添加 :git remote add 远程仓库别名 .git地址
2、推送/拉取:git push/pull -u 远程仓库别名 本地和远程分支名
3、查看远端链接:git remote -v
4、删除远程仓库 : git remote remove 远程仓库别名
5、本地从0开始:git clone 远程仓库地址

3.6.1 git新手容易碰到的问题

本地init代码,网站创办远程仓库(添加readme等基本文件),本地添加远端后,git push不成提示先git pull,结果还是不行,因为两部分的.init不能识别彼此,认为两者是完全不同的项目,不能合并导致的冲突问题。
此时在本地运行如下命令:

// git pull --rebase   远程仓库别名   分支名
git pull --rebase ori master

rebase强制合并并把两部分代码文件合并为新的commit版本

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值