fetchApi === 入门篇

news2024/12/23 17:54:54

目录

fetch 基本认知

fetch 如何使用

Response对象(了解)

常见属性

常见方法

fetch 配置参数

fetch发送post请求

fetch 函数封装

fetch 实战 - 图书管理案例

渲染功能

添加功能

删除数据

完整代码


fetch 基本认知

思考: 以前开发中如何向服务器请求数据的?

  • 方法一:通过 Ajax 向服务器请求数据,而 Ajax 本质就是使用 XMLHttpRequest 对象实现的

    可以实现,但是代码写起来很麻烦
// 1、创建一个xhr对象
let xhr = new XMLHttpRequest()
// 2、设置请求方式和请求地址
xhr.open('get', 'http://ajax-base-api-t.itheima.net/api/getbooks?name=zs&age=18')
// 3、发送请求
xhr.send()
// 4.监听load事件获取响应结果
xhr.addEventListener('load', function () {
    console.log(JSON.parse(xhr.response))
})

  • 方法二:通过 axios 实现的代码精简不少,但是axios底层仍然是基于 XMLHttpRequest 对象实现的,本质不变,只是进行了 promise 封装

那么目前除了使用 XMLHttpRequest 发送请求之外,还有没有其他方式呢?

  • 有,就是fetch

什么是fetch?

  • Fetch 被称之为下一代 Ajax 技术,内部采用 Promise 方式来处理数据

    可以直接.then即可

  • API语法简洁明了,比 XMLHttpRequest 更加简单易用

  • 采用了模块化设计,API分散于多个对象中(如:Response对象、Request对象、Header对象)

  • 通过数据流(Stream对象)处理数据,可以分块读取,有利于提高网站性能,对于大文件或者网速慢的场景极为有用

兼容性:浏览器支持程度如何?

  • 最新统计(下图所示):fetch 可以支持到 96.83% 的用户端,除了IE,主流浏览器 都已兼容
  • 注意点:不兼容IE

fetch 如何使用

【博客文档推荐】

  • https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
  • https://www.ruanyifeng.com/blog/2020/12/fetch-tutorial.html

使用fetch发送基本get请求

介绍:

  • 如果fetch() 只接收了一个 url字符串 参数,表示默认向该网址发送 get 请求,会返回一个Promise对象
  • 如果需要设置get的参数,直接拼接到 url 地址上即可

语法:

fetch(url)
  .then(...)
  .catch(...)

ヾ(๑╹◡╹)ノ" 01-fetch发送基本的get请求

// 接口地址:http://ajax-base-api-t.itheima.net/api/getbooks
// 请求方式:get
// 查询参数(可选):
//   1、id:需要查询的图书id

fetch('http://ajax-base-api-t.itheima.net/api/getbooks').then(res => {
    // 得到的res,是一个Response对象,需要通过特定方法获取其中内容
    // console.log(res)

    // res.json() 是一个异步操作,表示取出所有的内容,将其转换成JSON对象
    console.log(res.json())
    return res.json()
}).then(json => {
    // 获取经过res.json() 处理过之后的数据——》正常通过ajax获取的数据
    console.log(json)
}).catch(err => {
    console.log(err)
})

 ヾ(๑╹◡╹)ノ" 02-fetch发送get请求-使用async-await改写

// 接口地址:http://ajax-base-api-t.itheima.net/api/getbooks
// 请求方式:get
// 查询参数(可选):
//   1、id:需要查询的图书id

// 1、把代码封装成async异步函数
async function getData() {
    // 通过try...catch语法处理async-await成功和失败的情况
    try {
        // 先获取Response对象
        let res = await fetch('http://ajax-base-api-t.itheima.net/api/getbooks')
        console.log(res)
        // 通过res.json() 取出response对象中的数据
        let json = await res.json()
        console.log(json)
    } catch (err) {
        // 捕获错误信息
        console.log(err)
    }
}
getData()

ヾ(๑╹◡╹)ノ" 03-fetch发送get请求-使用async-await改写-添加查询参数

// 2、如果需要通过get请求设置查询参数如何实现?
//    可以通过地址栏拼接查询参数完成
async function getData1() {
    // 通过try...catch语法处理async-await成功和失败的情况
    try {
        // 先获取Response对象
        let res = await fetch('http://ajax-base-api-t.itheima.net/api/getbooks?id=1')
        console.log(res)
        // 通过res.json() 取出response对象中的数据
        let json = await res.json()
        console.log(json)
    } catch (err) {
        // 捕获错误信息
        console.log(err)
    }
}
getData1()

Response对象(了解)

fetch 请求成功以后,得到的是一个 Response 对象。它是对应服务器的 HTTP 响应。

const res = await fetch(url)
console.log(res)

常见属性

属性含义
res.ok返回一个布尔类型,表示请求是否成功
res.status返回一个数字,表示HTTP回应的状态码(例如:200,表示以请求成功)
res.statusText返回状态的文本信息(例如:请求成功之后,服务器返回ok)
res.url返回请求的url地址

 

常见方法

Response 对象根据服务器返回的不同类型的数据,提供了不同的读取方法。

其中最常用的就是 res.json()

方法含义
res.json()得到 JSON 对象
res.text()得到文本字符串
res.blob()得到二进制 Blob 对象
res.formData()得到 FormData 表单对象
res.arrayBuffer()得到二进制 ArrayBuffer 对象

fetch 配置参数

fetch的第一个参数是 url ,此外还可以接收第二个参数,作为配置对象,可以自定义发出的HTTP请求

比如:fetch(url,options)

其中:post、put、patch 用法类似,咱们这边以post为例演示

配置参数介绍:

fetch(url,{
    method:'请求方式,比如:post、delete、put',
    headers:{
        'Content-Type':'数据格式'
    },
    body:'post请求体数据'
})

fetch发送post请求

咱们这边以开发中用的较多的JSON格式的情况为例

**基本语法1:**json格式(常用)

// 测试接口(新增操作):
// 接口地址:http://ajax-base-api-t.itheima.net/api/addbook
// 请求方式:post
// 请求体参数:
//  1、书名:bookname
//  2、作者:author
//  3、出版社:publisher

// post发送:json格式
async function add() {
    let obj = {
        bookname: '魔法书之如何快速学好前端',
        author: '茵蒂克丝',
        publisher: '格兰芬多'
    }

    let res = await fetch('http://ajax-base-api-t.itheima.net/api/addbook', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(obj)
    })

    let json = await res.json()
    console.log(json)
}
add()

 基本语法2: x-www-form-urlencoded格式(了解)

async function add1() {
    let res = await fetch(url, {
      method: 'post',
      headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
      },
      body: 'foo=bar&lorem=ipsum',
    });

    let json = await res.json();
    console.log(json)
}
add1()

**基本语法3:**formData格式(了解)

let form = document.querySelector('form');

async function add2() {
    let res = await fetch(url, {
        method: 'POST',
        body: new FormData(form)
    })
    
    let json = await res.json()
    console.log(json)
}
add2()

fetch 函数封装

原生fetch虽然已经支持 promise 了,相比 XMLHttpRequest 已然好用了很多,但是参数还是需要自己处理,比较麻烦

比如:

  • get delete 的请求参数,要在地址栏拼接
  • put patch post 的请求参数,要转 json 设置请求头

所以实际工作,我们还是会对 fetch 二次封装

目标效果:

// 发送get请求、delete请求
http({
    method:'xxx'
    url:'xxx',
    params:{......}
     })

// 发送post请求、put请求、patch请求
http({
    method:'xxx'
    url:'xxx',
    data:{......}
     })

封装之后代码如下:

async function http(obj) {
    // 解构赋值
    let { method, url, params, data } = obj

    // 判断是否有params参数
    // 1、如果有params参数,则把params对象转换成 key=value&key=value的形式,并且拼接到url之后
    // 2、如果没有params参数,则不管
    if (params) {
        // 把对象转换成 key=value&key=value 的方法
        // 固定写法:new URLSearchParams(obj).toString()
        let str = new URLSearchParams(params).toString()
        // console.log(str)
        // 拼接到url上
        url += '?' + str
    }

    // 最终的结果
    let res
    // 判断是否有data参数,如果有,则需要设置给body,否则不需要设置
    console.log(data)
    if (data) {
        // 如果有data参数,此时直接设置
        res = await fetch(url, {
            method: method,
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
        })
    } else {
        res = await fetch(url)
    }

    return res.json()
}


// 测试代码1:
// 请求方式:get
// 接口地址:http://ajax-base-api-t.itheima.net/api/getbooks
// 查询参数(可选):
//   1、id:需要查询的图书id

async function fn1() {
    let result1 = await http({
        method: 'get',
        url: 'http://ajax-base-api-t.itheima.net/api/getbooks',
        params: {
            id: 1
        }
    })
    console.log(result1)
}
fn1()

// 测试代码2:
// 请求方式:post
// 接口地址:http://ajax-base-api-t.itheima.net/api/addbook
// 请求体参数:
//  1、书名:bookname
//  2、作者:author
//  3、出版社:publisher
async function fn2() {
    let result2 = await http({
        method: 'post',
        url: 'http://ajax-base-api-t.itheima.net/api/addbook',
        data: {
            bookname: '魔法书111',
            author: '嘻嘻',
            publisher: '哈哈哈'
        }
    })
    console.log(result2)
}
fn2()

fetch 实战 - 图书管理案例

获取所有图书:
    1、接口地址:http://ajax-base-api-t.itheima.net/api/getbooks
    2、请求方式:get

添加图书:
    1、接口地址:http://ajax-base-api-t.itheima.net/api/addbook
    2、请求方式:post
    3、请求体参数:
        1、bookname:图书的名称
        2、author:作者
        3、publisher:出版社

删除图书:
    1、接口地址:http://ajax-base-api-t.itheima.net/api/delbook
    2、请求方式:delete
    3、查询参数:
        1、id:需要删除图片的id

 

渲染功能

步骤:

  1. 把渲染的代码封装成函数
  2. 通过封装好的http函数,获取所有图书数据
  3. 遍历返回的图书数组,每遍历一项,就创建一个tr出来,拼接成完整字符串再一起添加到tbody中去
// 把渲染的代码封装成函数
    async function render() {
      // 获取数据
      let res = await http({
        method: 'get',
        url: 'http://ajax-base-api-t.itheima.net/api/getbooks',
      })
      console.log(res.data)

      let htmlStr = ''
      // 遍历数组,每遍历一项,就创建一个tr出来,拼接成完整字符串再一起添加到tbody中去
      res.data.forEach(item => {
        // console.log(item)
        htmlStr += `
          <tr>
            <th scope="row">${item.id}</th>
            <td>${item.bookname}</td>
            <td>${item.author}</td>
            <td>${item.publisher}</td>
            <td>
              <button type="button" class="btn btn-link btn-sm">
                删除
              </button>
            </td>
          </tr>
        `
      })
      // console.log(htmlStr)
      // 把拼接好的数据,设置到tbody中去
      tbody.innerHTML = htmlStr
    }
添加功能

步骤:

  1. 给form注册submit事件
  2. 阻止浏览器默认行为(提交的默认跳转功能)
  3. 通过serialize插件获取表单数据
  4. 通过封装好的http函数发送数据给服务器
  5. 判断res的status是否成功
    1. 如果成功,此时重新渲染,并且重置表单
    2. 如果不成功,弹框提示错误信息即可
// 表单提交功能
form.addEventListener('submit', async function (e) {
    //  阻止浏览器默认行为
    e.preventDefault()

    // 获取表单数据——》通过serialize插件获取
    let result = serialize(form, { hash: true })
    console.log(result)

    // 把获取的表单数据,发送给服务器
    let res = await http({
        method: 'post',
        url: 'http://ajax-base-api-t.itheima.net/api/addbook',
        data: result
    })
    console.log(res)

    // 通过res的status判断是否添加成功
    if (res.status === 201) {
        // 重新渲染
        render()
        // 重置表单
        form.reset()
    } else {
        // 如果不成功,弹框提示错误信息即可
        alert(res.msg)
    }

})
删除数据

步骤:

  1. 利用事件委托,给tbody注册点击事件
  2. 判断e.target.tagName是不是按钮
  3. 如果是按钮,则通过封装好的http函数发送请求删除数据
  4. 此时需要知道删除的这一项的id,则再渲染button时就可以把id添加到dom结构上
  5. 判断是否删除成功,如果删除成功,则需要重新加载
// 删除功能——》利用事件委托
tbody.addEventListener('click', async function (e) {
    //  console.log(e.target.tagName)

    // 判断如果点击的是按钮,才进行删除
    if (e.target.tagName === 'BUTTON') {
        let res = await http({
            method: 'delete',
            url: 'http://ajax-base-api-t.itheima.net/api/delbook',
            params: {
                id: e.target.dataset.id
            }
        })
        // console.log(res)
        // 判断如果删除成功,此时需要重新加载
        if (res.status === 200) {
            render()
        }
    }
})
完整代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    /* 基本的页面样式 */
    body {
        font-family: 'Arial', sans-serif;
        padding: 20px;
        background-color: #f4f4f4;
    }

    /* 表格的样式 */
    #tbody {
        width: 100%;
        border-collapse: collapse;
        margin-top: 20px;
    }

    #tbody th,
    #tbody td {
        border: 1px solid #ddd;
        padding: 8px;
        text-align: left;
    }

    #tbody th {
        background-color: #4CAF50;
        color: white;
    }

    /* 鼠标悬停效果 */
    #tbody tr:hover {
        background-color: #f5f5f5;
    }

    /* 按钮样式 */
    .btn-link {
        color: #337ab7;
        text-decoration: none;
        padding: 5px 10px;
        border: none;
        background: none;
        outline: none;
    }

    .btn-link:hover {
        text-decoration: underline;
    }

    /* 小型按钮 */
    .btn-sm {
        font-size: 12px;
    }

    /* 删除按钮样式 */
    .delete-btn {
        color: #a94442;
    }

    .delete-btn:hover {
        color: #843534;
    }

    /* 响应式设计 */
    @media (max-width: 768px) {
        body {
            padding: 10px;
        }

        #tbody th,
        #tbody td {
            padding: 5px;
        }
    }

    /* 优化表格结构 */
    #thead,
    #tfoot {
        display: table-header-group;
    }

    #tfoot {
        font-weight: bold;
    }

    /* 动画效果 */
    .btn-link:hover {
        transition: color 0.3s ease;
        text-decoration: underline;
    }

    /* 按钮交互性 */
    .btn-link:focus,
    .btn-link:active {
        outline: none;
        box-shadow: 0 0 0 2px rgba(51, 122, 183, 0.5);
    }

    /* 辅助类 */
    .text-center {
        text-align: center;
    }

    .mt {
        margin-top: 20px;
    }

    /* 表格内边距调整 */
    #tbody th,
    #tbody td {
        padding: 15px;
    }

    /* 删除按钮样式增强 */
    .delete-btn {
        cursor: pointer;
    }

    .delete-btn:hover {
        transition: color 0.3s ease;
    }

    .book-form {
        max-width: 400px;
        margin: 20px auto;
        padding: 20px;
        background: #fff;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }

    .book-form h2 {
        text-align: center;
        margin-bottom: 20px;
    }

    .form-group {
        margin-bottom: 15px;
    }

    .form-group label {
        display: block;
        margin-bottom: 5px;
    }

    .form-group input {
        width: 100%;
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 4px;
        box-sizing: border-box;
        /* 确保padding不会增加宽度 */
    }

    .btn-primary {
        background-color: #4CAF50;
        color: white;
        border: none;
        padding: 10px 20px;
        cursor: pointer;
        border-radius: 4px;
        transition: background-color 0.3s ease;
    }

    .btn-primary:hover {
        background-color: #45a049;
    }

    /* 响应式设计 */
    @media (max-width: 600px) {
        .book-form {
            width: 90%;
            padding: 10px;
        }
    }
</style>

<body>
    <div class="Z">
        <table id="table" class="table">
            <thead id="thead">
                <tr>
                    <th>ID</th>
                    <th>书名</th>
                    <th>作者</th>
                    <th>出版社</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="tbody">
                <!-- 动态生成的表格行将放在这里 -->
            </tbody>
            <tfoot id="tfoot">
                <tr>
                    <td colspan="5">版权所有 © 2024 月之暗面科技有限公司</td>
                </tr>
            </tfoot>
        </table>
        <form id="form" class="book-form">
            <h2>新增书籍</h2>

            <div class="form-group">
                <label for="bookName">书名:</label>
                <input type="text" id="bookName" name="bookname" required>
            </div>

            <div class="form-group">
                <label for="author">作者:</label>
                <input type="text" id="author" name="author" required>
            </div>

            <div class="form-group">
                <label for="publisher">出版社:</label>
                <input type="text" id="publisher" name="publisher" required>
            </div>

            <button type="submit" class="btn btn-primary">提交</button>
        </form>
    </div>
</body>

</html>
<script src="./index.js"></script>
<script>
    async function http(obj) {
        // 解构赋值
        let { method, url, params, data } = obj

        // 判断是否有params参数
        // 1、如果有params参数,则把params对象转换成 key=value&key=value的形式,并且拼接到url之后
        // 2、如果没有params参数,则不管
        if (params) {
            // 把对象转换成 key=value&key=value 的方法
            // 固定写法:new URLSearchParams(obj).toString()
            let str = new URLSearchParams(params).toString()
            // console.log(str)
            // 拼接到url上
            url += '?' + str
        }

        // 最终的结果
        let res
        // 判断是否有data参数,如果有,则需要设置给body,否则不需要设置
        console.log(data)
        if (data) {
            // 如果有data参数,此时直接设置
            res = await fetch(url, {
                method: method,
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data)
            })
        } else {
            res = await fetch(url)
        }

        return res.json()
    }


    // 把渲染的代码封装成函数
    async function render() {
        // 获取数据
        let res = await http({
            method: 'get',
            url: 'http://ajax-base-api-t.itheima.net/api/getbooks',
        })
        console.log(res.data)

        let htmlStr = ''
        // 遍历数组,每遍历一项,就创建一个tr出来,拼接成完整字符串再一起添加到tbody中去
        res.data.forEach(item => {
            // console.log(item)
            htmlStr += `
          <tr>
            <th scope="row">${item.id}</th>
            <td>${item.bookname}</td>
            <td>${item.author}</td>
            <td>${item.publisher}</td>
            <td>
              <button type="button" class="btn btn-link btn-sm" data-id=${item.id}>
                删除
              </button>
            </td>
          </tr>
        `
        })
        // console.log(htmlStr)
        // 把拼接好的数据,设置到tbody中去
        tbody.innerHTML = htmlStr
    }
    render()
    // 表单提交功能
    form.addEventListener('submit', async function (e) {
        //  阻止浏览器默认行为
        e.preventDefault()

        // 获取表单数据——》通过serialize插件获取
        let result = serialize(form, { hash: true })
        console.log(result)

        // 把获取的表单数据,发送给服务器
        let res = await http({
            method: 'post',
            url: 'http://ajax-base-api-t.itheima.net/api/addbook',
            data: result
        })
        console.log(res)

        // 通过res的status判断是否添加成功
        if (res.status === 201) {
            // 重新渲染
            render()
            // 重置表单
            form.reset()
        } else {
            // 如果不成功,弹框提示错误信息即可
            alert(res.msg)
        }

    })
    // 删除功能——》利用事件委托
    tbody.addEventListener('click', async function (e) {
        //  console.log(e.target.tagName)

        // 判断如果点击的是按钮,才进行删除
        if (e.target.tagName === 'BUTTON') {
            try {
                let res = await http({
                    method: 'delete',
                    url: 'http://ajax-base-api-t.itheima.net/api/delbook',
                    params: {
                        id: e.target.dataset.id
                    }
                })
                // console.log(res)
                // 判断如果删除成功,此时需要重新加载
                if (res.status === 200) {
                    render()
                }
            } catch (error) {
                console.log(error);
            }
        }
    })

</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1953590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCIe总线-Linux内核PCIe软件框架分析(十一)

1.简介 Linux内核PCIe软件框架如下图所示&#xff0c;按照PCIe的模式&#xff0c;可分为RC和EP软件框架。RC的软件框架分为五层&#xff0c;第一层为RC Controller Driver&#xff0c;和RC Controller硬件直接交互&#xff0c;不同的RC Controller&#xff0c;其驱动实现也不相…

永结无间Ⅰ--基于 LLM 的 AGI

在过去几周&#xff0c;传奇人物 Francois Chollet 发起的ARC 挑战引起了不小的轰动。这项挑战让很多 AI 研究人员感到困惑&#xff0c;它表明了所有 AI 系统都存在泛化能力不足的问题。ARC 上上一次 SOTA AI 的准确率约为 34%&#xff0c;而在同一挑战中&#xff0c;Mechanica…

【React】Context机制跨层传递数据详解

文章目录 一、React Context的概念二、创建和使用Context1. 创建Context2. 使用Provider提供数据3. 使用Consumer获取数据 三、使用useContext Hook四、动态更新Context值五、Context的实际应用场景1. 主题切换2. 用户认证状态 六、注意事项 在开发React应用时&#xff0c;我们…

【C语言】深入探讨数组传参

一、数组传参简介 在C语言中&#xff0c;数组传参是一个常见的操作&#xff0c;尤其是在处理大量数据或需要多次访问相同数据集时。理解如何传递数组以及这些方法之间的差异是编写高效和安全代码的关键。在这篇博客中&#xff0c;我们将详细讨论C语言中数组传参的几种常见方法&…

【网络】应用层协议(自定义协议)(序列和反序列化)

应用层协议&#xff08;自定义协议&#xff09;&#xff08;序列和反序列化&#xff09; 一、引言--应用层的使用二、应用层1、网络版本计算器&#xff08;1&#xff09;协议定制和序列反序列化&#xff08;2&#xff09;网络版计算器协议定制i、封装有效载荷&#xff08;默认上…

数据结构——单链表OJ题(上)

目录 一、移除链表元素 1.思路 2.注意 3.解题 二、反转链表 思路1&#xff1a;三指针翻转法 &#xff08;1&#xff09;注意 &#xff08;2&#xff09;解题 思路2&#xff1a;头插法 &#xff08;1&#xff09;注意 &#xff08;2&#xff09;解题 三、链表的中间结…

depcheck 前端依赖检查

介绍 depcheck 是一款用于检测项目中 未使用依赖项 的工具。 depcheck 通过扫描项目文件&#xff0c;帮助你找出未被引用的依赖&#xff0c;从而优化项目。 优势&#xff1a; 简单易用: 仅需几个简单的命令&#xff0c;就能够扫描并列出未使用的依赖项&#xff0c;让你快速了…

The Schematic workflow failed. See above.

在使用 ng new 新建Angular项目的时候会报一个错误&#xff1a;The Schematic workflow failed. See above. 解决办法&#xff1a; 只需要在后面加上 --skip-install 参数&#xff0c;就不会报错了。 ng new myapp --skip-install

打工人电脑里都需要的远程控制软件有哪些?这4款不能错过

不巧前几天台风&#xff0c;实在没办法到公司&#xff0c;但是项目还得继续&#xff0c;这时候远程控制电脑的技巧可谓是帮了我大忙了。不知道平常的你偶尔会不会也需要远程控制电脑的操作&#xff0c;如果有就继续看下去吧。 1.向日魁远程控制 直通车>>https://down.o…

AJAX-Promise 详解

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 前言 一、Promise基本概念 1.1 定义 1.2 状态 1.3 构造函数 二、Promise基本用法 2.1 then() 2.2 ca…

ThinkPHP一对一关联模型的运用(ORM)

一、序言 最近在写ThinkPHP关联模型的时候一些用法总忘&#xff0c;我就想通过写博客的方式复习和整理下一些用法。 具体版本&#xff1a; topthink/framework&#xff1a;6.1.4topthink/think-orm&#xff1a;2.0.61 二、实例应用 1、一对一关联 1.1、我先设计了两张表&#x…

根据题意写出完整的css,html和js代码【购物车模块页面及功能实现】

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 问题描述 根据题意写出完…

基于微信小程序+SpringBoot+Vue的社区超市管理系统(带1w+文档)

基于微信小程序SpringBootVue的社区超市管理系统(带1w文档) 基于微信小程序SpringBootVue的社区超市管理系统(带1w文档) 为了让商品信息的管理模式进行升级&#xff0c;也为了更好的维护商品信息&#xff0c;社区超市管理系统的开发运用就显得很有必要&#xff0c;因为它不仅可…

C# 植物大战僵尸

Winform 版本开发 高效率、流畅植物大战僵尸 git地址&#xff1a;冯腾飞/植物大战僵尸

go语言day19 使用git上传包文件到github Gin框架入门

git分布式版本控制系统_git切换head指针-CSDN博客 获取请求参数并和struct结构体绑定_哔哩哔哩_bilibili &#xff08;gin框架&#xff09; GO: 引入GIn框架_go 引入 gin-CSDN博客 使用git上传包文件 1&#xff09;创建一个github账户&#xff0c;进入Repositories个人仓…

我在百科荣创企业实践——简易函数信号发生器(6)

对于高职教师来说,必不可少的一个任务就是参加企业实践。这个暑假,本人也没闲着,报名参加了上海市电子信息类教师企业实践。7月8日到13日,有幸来到美丽的泉城济南,远离了上海的酷暑,走进了百科荣创科技发展有限公司。在这短短的一周时间里,我结合自己的教学经验和企业的…

buu做题(8)

[安洵杯 2019]easy_web 查看源代码可以发现一长串的base64编码 就是页面上的一张图片 回到原页面,url上面也有一些奇怪的参数 经过两次base64和一次hex 解密后得到 555.png 应该就是包含着页面上的这张图片 然后尝试将index.php 按照这样的方式编码, 看看能不能包含到 TmprMl…

后端解决跨域(Cross-Origin Resource Sharing)(三种方式)

注解CrossOrigin 控制层的类上或者方法上加注解CrossOrigin 实现接口并重写方法 Configuration public class CorsConfig implements WebMvcConfigurer {Overridepublic void addCorsMappings(CorsRegistry registry) {// 设置允许跨域的路径registry.addMapping("/**&qu…

算法通关:006_4二分查找:寻找数组中的峰值

文章目录 描述主要代码全部代码运行结果总结 二分法不一定只能用在有序数组中。 描述 leetcode&#xff1a;162 主要代码 //二分法查找峰值public static int findPeakElement(int[] arr){if (arr.length 1){//randomArray()不会出现arr null的情况return 0;}//先检查 0…

LabVIEW操作系列1

系列文章目录 我的记录&#xff1a; LabVIEW操作系列 文章目录 系列文章目录前言五、特殊用法5.1 取值范围表示5.2 对输入值取值范围进行限定5.3 控制多个While循环停止运行。5.4 获取按钮上的文本5.5 获取按钮上的文本【进阶】 六、使用步骤1.引入库2.读入数据 七、其余功能7.…