资讯专栏INFORMATION COLUMN

一次完整的react hooks实践

kuangcaibao / 2650人阅读

摘要:本次需求其实就两个逻辑输入筛选项。当发生改变时,重新渲染页面首次进入页面时,无任何筛选项。关于的一些,官方也有很棒的文档写在后面本文通过工作中的一个小需求,完成了一次的实践,不过上述代码依然有很多需要优化的地方。

写在前面

本文首发于公众号:符合预期的CoyPan

React在16.8版本正式发布了Hooks。关注了很久,最近正好有一个小需求,赶紧来试一下。

需求描述

需求很简单,部门内部的一个数据查询小工具。大致长成下面这样:

用户首次访问页面,会拉取数据展示。输入筛选条件,点击查询后,会再次拉取数据在前端展示。

需求实现 使用React Class Component的写法

如果使用以前的class写法,简单写一下,代码可能大概长成下面这样:

import React from "react";
import { Tabs, Input, RangeTime, Button, Table } from "./components";

class App extends React.Component {
    ...
    state = {
        type: [],
        id: "",
        title: "",
        date: [],
        dataList: []
    }
    componentDidMount() {
        this.fetchData();
    }
    render() {
        
        
        
        
        
        
    }
    
    fetchData() {
        ...
        this.setState({
            dataList
        });
    }

    handleTypeChange() {
        ...
        this.setState({
            type,
        });
    }
    
    handleIdChange() {
        ...
        this.setState({
            id,
        });
    }

    handleTitleChange() {
        ...
        this.setState({
            title,
        });
    }

    handleRangeTimeChange() {
        ...
        this.setState({
            date,
        });
    }

    handleQueryBtnClick() {
        ...
    }
    ...
}使用React Hooks的写法

关于React hooks的相关内容,这里就不赘述了。可以直接查看react官方文档,写得非常好。

https://reactjs.org/docs/hook...

本次需求其实就两个逻辑:1、输入筛选项 。2、查询数据

主页面一个hooks,处理筛选项以及数据展示。数据请求逻辑多带带弄一个hooks。

主页面hooks:

import React, { useState, useEffect} from "react";
import { Tabs, Input, RangeTime, Button, Table } from "./components";

const App = () => {
    // 数据类型
    const tabs = [{ key: 1, value: "类型1" }, { key: 0, value: "类型2" }];
    const [tab, setTab] = useState(1);
    // 数据ID
    const [dataId, setDataid] = useState("");
    // 标题
    const [title, setTitle] = useState("");
    // 时间区间, 默认为至今一周时间
    const now = Date.now();
    const [timeRange, setTimeRange] = useState([now - 1000 * 60 * 60 * 24 * 7, now]);
    // 数据列表
    const [dataList, setDataList] = useState([]);

    // 点击搜索按钮
    function handleBtnClick() {
        // 请求数据
        ...
    }

    return 
<Tabs label="类型" tabs={tabs} tab={tab} onChange={setTab} /> <Input value={dataId} placeholder="请输入数据ID" onChange={setDataid}>ID</Input> <Input value={title} placeholder="请输入数据标题" onChange={setTitle}>标题</Input> <TimeRange label="数据时间" value={timeRange} onChange={handleTimeChange}/> <article className="btn-container"> <Button type="primary" onClick={handleBtnClick}> 查询 </Button> </article> <Table dataList={dataList}></Table> </section> };</pre> <p>上面的代码,完成了筛选项的处理逻辑。下面来实现负责数据请求的hooks.</p> <p>数据请求hooks:</p> <pre>import React, { useState, useEffect } from "react"; import jsonp from "../tools/jsonp"; function MyFecth(url) { // 是否正在请求中 const [isLoading, setIsLoanding] = useState(false); // 请求参数 const [queryParams, setQueryParams] = useState(null); // 请求结果 const [data, setData] = useState(null); // 向接口发起请求 const fetchData = async () => { if(queryParams === null) { return; } setIsLoanding(true); const res = await jsonp({ url: url, data: queryParams }); setData(res); setIsLoanding(false); } // 只要queryParams改变,就发起请求 useEffect(()=> { fetchData(); }, [queryParams]); // 供外部调用 const doGet = (params) => { setQueryParams(params); } return { isLoading, data, doGet } } export default MyFecth;</pre> <p>在主页面中,引用数据请求hooks:</p> <pre>import React, { useState, useEffect} from "react"; import { Tabs, Input, RangeTime, Button, Table } from "./components"; import MyFecth from "./MyFetch"; const App = () => { // ①使用数据请求hooks const { isLoading, data, doGet } = MyFecth("http://xxx"); // 数据类型 const tabs = [{ key: 1, value: "类型1" }, { key: 0, value: "类型2" }]; const [tab, setTab] = useState(1); // 数据ID const [dataId, setDataid] = useState(""); // 标题 const [title, setTitle] = useState(""); // 时间区间, 默认为至今一周时间 const now = Date.now(); const [timeRange, setTimeRange] = useState([now - 1000 * 60 * 60 * 24 * 7, now]); // 数据列表 const [dataList, setDataList] = useState([]); // 点击搜索按钮 function handleBtnClick() { // ②点击按钮后请求数据 const params = {}; title && (params.title = title); dataId && (params.dataId = dataId); params.startTime = String(timeRange[0]); params.endTime = String(timeRange[1]); doGet(params); } // ③data改变后,重新渲染列表。 // 这里相当于 componentDidUpdate。当data发生改变时,重新渲染页面 useEffect(() => { setDataList(data); }, [data]); // ④首次进入页面时,无任何筛选项。拉取数据,渲染页面。 // useEffect第二个参数为一个空数组,相当于在 componentDidMount 时执行该「副作用」 useEffect(() => { doGet({}); }, []); return <section className="app"> <Title title="数据查询" /> <Tabs label="类型" tabs={tabs} tab={tab} onChange={setTab} /> <Input value={dataId} placeholder="请输入数据ID" onChange={setDataid}>ID</Input> <Input value={title} placeholder="请输入数据标题" onChange={setTitle}>标题</Input> <TimeRange label="数据时间" value={timeRange} onChange={handleTimeChange}/> <article className="btn-container"> <Button type="primary" isLoading={isLoading} onClick={handleBtnClick}> 查询 </Button> </article> <Table dataList={dataList}></Table> </section> };</pre> <b>关于React Hooks的一些思考</b> <p>使用hooks写完这个需求,最直观的感受就是,代码写起来很爽。不需要像以前那样写很多的setState。其次就是</p> <p>hooks的api设计得很优秀,一个useState的就能将【状态】和【变更状态的逻辑】两两配对。React的基本思想就是【数据到视图的映射】,在hooks中,使用useEffect来表明其中的【副作用】,感觉react官方也倾向于不区分componentDidMount和componentDidUpdate。</p> <p>从api设计就能看出,hooks提倡组件状态细粒度地拆分。在一个hooks组件中,可能包含很多的状态,如果用户的某些操作,需要同时修改两个状态,那么我需要分别调用这两个状态的修改逻辑,这样会导致组件被重新render两次。而在使用class写法的组件中,只需要一次setState就好。这样看来,hooks中render两次的操作,可能会带来些许的性能问题 ? 这就要求我们在设计组件结构和state时,多斟酌,多抽象。</p> <p>关于hooks的一些FAQ,官方也有很棒的文档:</p> <p>https://reactjs.org/docs/hook...</p> <b>写在后面</b> <p>本文通过工作中的一个小需求,完成了一次react hooks的实践,不过上述代码依然有很多需要优化的地方。这次实践让我最直观的接触了react hooks,也帮助自己进一步理解了react团队的一些思想。符合预期。</p> <p><script type="text/javascript">showImg("https://segmentfault.com/img/bVbond5?w=1240&h=620");</script></p> </div> <div class="mt-64 tags-seach" > <div class="tags-info"> <a style="width:120px;" title="GPU云服务器" href="https://www.ucloud.cn/site/product/gpu.html">GPU云服务器</a> <a style="width:120px;" title="云服务器" href="https://www.ucloud.cn/site/active/kuaijiesale.html?ytag=seo">云服务器</a> <a style="width:120px;" title="React hooks" href="https://www.ucloud.cn/yun/tag/React hooks/">React hooks</a> <a style="width:120px;" title="react-hooks" href="https://www.ucloud.cn/yun/tag/react-hooks/">react-hooks</a> <a style="width:120px;" title="React Hooks 文档重大更新!" href="https://www.ucloud.cn/yun/tag/React Hooks wendangzhongdagengxin/">React Hooks 文档重大更新!</a> <a style="width:120px;" title="html的完整格式" href="https://www.ucloud.cn/yun/tag/htmldewanzhenggeshi/">html的完整格式</a> </div> </div> <div class="entry-copyright mb-30"> <p class="mb-15"> 文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。</p> <p>转载请注明本文地址:https://www.ucloud.cn/yun/109101.html</p> </div> <ul class="pre-next-page"> <li class="ellipsis"><a class="hpf" href="https://www.ucloud.cn/yun/109100.html">上一篇:如何学习一门新语言或框架</a></li> <li class="ellipsis"><a class="hpf" href="https://www.ucloud.cn/yun/109102.html">下一篇:JavaScript 的 4 种数组遍历方法: for VS forEach() VS for/in</a></li> </ul> </div> <div class="about_topicone-mid"> <h3 class="top-com-title mb-0"><span data-id="0">相关文章</span></h3> <ul class="com_white-left-mid atricle-list-box"> <li> <div class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="https://www.ucloud.cn/yun/106582.html"><b>Ant Design Pro - <em>实践</em><em>React</em> <em>Hooks</em> - 组件</b></a></h2> <p class="ellipsis2 good">摘要:另外,监听事件,更新宽度状态。文本真实宽度渲染完成后,通过获取元素宽度。是否超长比较文本真实宽度和组件的宽度。设置为其他状态或中的状态时,只在这些状态变化时触发注意,依赖为对象时,不会深比较。得益于的用法灵活,组件写法上确实简洁不少。 需求 后台项目,使用Ant Design Pro, 有这样一个需求:有一个表格,宽度是自适应的,表格中有一列是备注,文本长度不定,我们希望在文本过长的时...</p> <div class="com_white-left-info"> <div class="com_white-left-infol"> <a href="https://www.ucloud.cn/yun/u-1597.html"><img src="https://www.ucloud.cn/yun/data/avatar/000/00/15/small_000001597.jpg" alt=""><span class="layui-hide64">twohappy</span></a> <time datetime="">2019-08-26 10:40</time> <span><i class="fa fa-commenting"></i>评论0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="https://www.ucloud.cn/yun/99617.html"><b><em>React</em> <em>Hooks</em>实现异步请求实例—useReducer、useContext和useEffec</b></a></h2> <p class="ellipsis2 good">摘要:本文是学习了年新鲜出炉的提案之后,针对异步请求数据写的一个案例。注意,本文假设了你已经初步了解的含义了,如果不了解还请移步官方文档。但不要忘记和上下文对象可以看做是写法的以及三个钩子函数的组合。 本文是学习了2018年新鲜出炉的React Hooks提案之后,针对异步请求数据写的一个案例。注意,本文假设了:1.你已经初步了解hooks的含义了,如果不了解还请移步官方文档。(其实有过翻译...</p> <div class="com_white-left-info"> <div class="com_white-left-infol"> <a href="https://www.ucloud.cn/yun/u-1592.html"><img src="https://www.ucloud.cn/yun/data/avatar/000/00/15/small_000001592.jpg" alt=""><span class="layui-hide64">Code4App</span></a> <time datetime="">2019-08-23 13:49</time> <span><i class="fa fa-commenting"></i>评论0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="https://www.ucloud.cn/yun/109204.html"><b>精读《Function VS Class 组件》</b></a></h2> <p class="ellipsis2 good">摘要:未来可能成为官方之一。讨论地址是精读组件如果你想参与讨论,请点击这里,每周都有新的主题,周末或周一发布。前端精读帮你筛选靠谱的内容。 1. 引言 为什么要了解 Function 写法的组件呢?因为它正在变得越来越重要。 那么 React 中 Function Component 与 Class Component 有何不同? how-are-function-components-di...</p> <div class="com_white-left-info"> <div class="com_white-left-infol"> <a href="https://www.ucloud.cn/yun/u-1214.html"><img src="https://www.ucloud.cn/yun/data/avatar/000/00/12/small_000001214.jpg" alt=""><span class="layui-hide64">FWHeart</span></a> <time datetime="">2019-08-26 13:38</time> <span><i class="fa fa-commenting"></i>评论0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="https://www.ucloud.cn/yun/99188.html"><b>精读《<em>React</em> <em>Hooks</em>》</b></a></h2> <p class="ellipsis2 good">摘要:更容易将组件的与状态分离。也就是只提供状态处理方法,不会持久化状态。大体思路是利用共享一份数据,作为的数据源。精读带来的约定函数必须以命名开头,因为这样才方便做检查,防止用判断包裹语句。前端精读帮你筛选靠谱的内容。 1 引言 React Hooks 是 React 16.7.0-alpha 版本推出的新特性,想尝试的同学安装此版本即可。 React Hooks 要解决的问题是状态共享,...</p> <div class="com_white-left-info"> <div class="com_white-left-infol"> <a href="https://www.ucloud.cn/yun/u-1396.html"><img src="https://www.ucloud.cn/yun/data/avatar/000/00/13/small_000001396.jpg" alt=""><span class="layui-hide64">kohoh_</span></a> <time datetime="">2019-08-23 13:03</time> <span><i class="fa fa-commenting"></i>评论0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> </ul> </div> <div class="topicone-box-wangeditor"> <h3 class="top-com-title mb-64"><span>发表评论</span></h3> <div class="xcp-publish-main flex_box_zd"> <div class="unlogin-pinglun-box"> <a href="javascript:login()" class="grad">登陆后可评论</a> </div> </div> </div> <div class="site-box-content"> <div class="site-content-title"> <h3 class="top-com-title mb-64"><span>0条评论</span></h3> </div> <div class="pages"></ul></div> </div> </div> <div class="layui-col-md4 layui-col-lg3 com_white-right site-wrap-right"> <div class=""> <div class="com_layuiright-box user-msgbox"> <a href="https://www.ucloud.cn/yun/u-1381.html"><img src="https://www.ucloud.cn/yun/data/avatar/000/00/13/small_000001381.jpg" alt=""></a> <h3><a href="https://www.ucloud.cn/yun/u-1381.html" rel="nofollow">kuangcaibao</a></h3> <h6>男<span>|</span>高级讲师</h6> <div class="flex_box_zd user-msgbox-atten"> <a href="javascript:attentto_user(1381)" id="attenttouser_1381" class="grad follow-btn notfollow attention">我要关注</a> <a href="javascript:login()" title="发私信" >我要私信</a> </div> <div class="user-msgbox-list flex_box_zd"> <h3 class="hpf">TA的文章</h3> <a href="https://www.ucloud.cn/yun/ut-1381.html" class="box_hxjz">阅读更多</a> </div> <ul class="user-msgbox-ul"> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/130642.html">jupyter安装tensorflow</a></h3> <p>阅读 1783<span>·</span>2023-04-25 15:51</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/122427.html">SpringBoot集成Redis</a></h3> <p>阅读 2497<span>·</span>2021-10-13 09:40</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/120827.html">Facebook宣布“元宇宙”相关部门负责人晋升首席技术官</a></h3> <p>阅读 2133<span>·</span>2021-09-23 11:22</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/115905.html">浮动布局错误</a></h3> <p>阅读 3243<span>·</span>2019-08-30 14:16</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/109101.html">一次完整的react hooks实践</a></h3> <p>阅读 2651<span>·</span>2019-08-26 13:35</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/108983.html">React Router4.0</a></h3> <p>阅读 1847<span>·</span>2019-08-26 13:31</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/107322.html">也来探讨一下Object.assign</a></h3> <p>阅读 873<span>·</span>2019-08-26 11:39</p></li> <li><h3 class="ellipsis"><a href="https://www.ucloud.cn/yun/106359.html">React源码解析之React.children.map()</a></h3> <p>阅读 2732<span>·</span>2019-08-26 10:33</p></li> </ul> </div> <!-- 文章详情右侧广告--> <div class="com_layuiright-box"> <h6 class="top-com-title"><span>最新活动</span></h6> <div class="com_adbox"> <div class="layui-carousel" id="right-item"> <div carousel-item> <div> <a href="https://www.ucloud.cn/site/active/kuaijiesale.html?ytag=seo" rel="nofollow"> <img src="https://www.ucloud.cn/yun/data/attach/240625/2rTjEHmi.png" alt="云服务器"> </a> </div> <div> <a href="https://www.ucloud.cn/site/product/gpu.html" rel="nofollow"> <img src="https://www.ucloud.cn/yun/data/attach/240807/7NjZjdrd.png" alt="GPU云服务器"> </a> </div> </div> </div> </div> <!-- banner结束 --> <div class="adhtml"> </div> <script> $(function(){ $.ajax({ type: "GET", url:"https://www.ucloud.cn/yun/ad/getad/1.html", cache: false, success: function(text){ $(".adhtml").html(text); } }); }) </script> </div> </div> </div> </div> </div> </section> <!-- wap拉出按钮 --> <div class="site-tree-mobile layui-hide"> <i class="layui-icon layui-icon-spread-left"></i> </div> <!-- wap遮罩层 --> <div class="site-mobile-shade"></div> <!--付费阅读 --> <div id="payread"> <div class="layui-form-item">阅读需要支付1元查看</div> <div class="layui-form-item"><button class="btn-right">支付并查看</button></div> </div> <script> var prei=0; $(".site-seo-depict pre").each(function(){ var html=$(this).html().replace("<code>","").replace("</code>","").replace('<code class="javascript hljs" codemark="1">',''); $(this).attr('data-clipboard-text',html).attr("id","pre"+prei); $(this).html("").append("<code>"+html+"</code>"); prei++; }) $(".site-seo-depict img").each(function(){ if($(this).attr("src").indexOf('data:image/svg+xml')!= -1){ $(this).remove(); } }) $("LINK[href*='style-49037e4d27.css']").remove(); $("LINK[href*='markdown_views-d7a94ec6ab.css']").remove(); layui.use(['jquery', 'layer','code'], function(){ $("pre").attr("class","layui-code"); $("pre").attr("lay-title",""); $("pre").attr("lay-skin",""); layui.code(); $(".layui-code-h3 a").attr("class","copycode").html("复制代码 ").attr("onclick","copycode(this)"); }); function copycode(target){ var id=$(target).parent().parent().attr("id"); var clipboard = new ClipboardJS("#"+id); clipboard.on('success', function(e) { e.clearSelection(); alert("复制成功") }); clipboard.on('error', function(e) { alert("复制失败") }); } //$(".site-seo-depict").html($(".site-seo-depict").html().slice(0, -5)); </script> <link rel="stylesheet" type="text/css" href="https://www.ucloud.cn/yun/static/js/neweditor/code/styles/tomorrow-night-eighties.css"> <script src="https://www.ucloud.cn/yun/static/js/neweditor/code/highlight.pack.js" type="text/javascript"></script> <script src="https://www.ucloud.cn/yun/static/js/clipboard.js"></script> <script>hljs.initHighlightingOnLoad();</script> <script> function setcode(){ var _html=''; document.querySelectorAll('pre code').forEach((block) => { var _tmptext=$.trim($(block).text()); if(_tmptext!=''){ _html=_html+_tmptext; console.log(_html); } }); } </script> <script> function payread(){ layer.open({ type: 1, title:"付费阅读", shadeClose: true, content: $('#payread') }); } // 举报 function jupao_tip(){ layer.open({ type: 1, title:false, shadeClose: true, content: $('#jubao') }); } $(".getcommentlist").click(function(){ var _id=$(this).attr("dataid"); var _tid=$(this).attr("datatid"); $("#articlecommentlist"+_id).toggleClass("hide"); var flag=$("#articlecommentlist"+_id).attr("dataflag"); if(flag==1){ flag=0; }else{ flag=1; //加载评论 loadarticlecommentlist(_id,_tid); } $("#articlecommentlist"+_id).attr("dataflag",flag); }) $(".add-comment-btn").click(function(){ var _id=$(this).attr("dataid"); $(".formcomment"+_id).toggleClass("hide"); }) $(".btn-sendartcomment").click(function(){ var _aid=$(this).attr("dataid"); var _tid=$(this).attr("datatid"); var _content=$.trim($(".commenttext"+_aid).val()); if(_content==''){ alert("评论内容不能为空"); return false; } var touid=$("#btnsendcomment"+_aid).attr("touid"); if(touid==null){ touid=0; } addarticlecomment(_tid,_aid,_content,touid); }) $(".button_agree").click(function(){ var supportobj = $(this); var tid = $(this).attr("id"); $.ajax({ type: "GET", url:"https://www.ucloud.cn/yun/index.php?topic/ajaxhassupport/" + tid, cache: false, success: function(hassupport){ if (hassupport != '1'){ $.ajax({ type: "GET", cache:false, url: "https://www.ucloud.cn/yun/index.php?topic/ajaxaddsupport/" + tid, success: function(comments) { supportobj.find("span").html(comments+"人赞"); } }); }else{ alert("您已经赞过"); } } }); }); function attenquestion(_tid,_rs){ $.ajax({ //提交数据的类型 POST GET type:"POST", //提交的网址 url:"https://www.ucloud.cn/yun/favorite/topicadd.html", //提交的数据 data:{tid:_tid,rs:_rs}, //返回数据的格式 datatype: "json",//"xml", "html", "script", "json", "jsonp", "text". //在请求之前调用的函数 beforeSend:function(){}, //成功返回之后调用的函数 success:function(data){ var data=eval("("+data+")"); console.log(data) if(data.code==2000){ layer.msg(data.msg,function(){ if(data.rs==1){ //取消收藏 $(".layui-layer-tips").attr("data-tips","收藏文章"); $(".layui-layer-tips").html('<i class="fa fa-heart-o"></i>'); } if(data.rs==0){ //收藏成功 $(".layui-layer-tips").attr("data-tips","已收藏文章"); $(".layui-layer-tips").html('<i class="fa fa-heart"></i>') } }) }else{ layer.msg(data.msg) } } , //调用执行后调用的函数 complete: function(XMLHttpRequest, textStatus){ postadopt=true; }, //调用出错执行的函数 error: function(){ //请求出错处理 postadopt=false; } }); } </script> <footer> <div class="layui-container"> <div class="flex_box_zd"> <div class="left-footer"> <h6><a href="https://www.ucloud.cn/"><img src="https://www.ucloud.cn/yun/static/theme/ukd//images/logo.png" alt="UCloud (优刻得科技股份有限公司)"></a></h6> <p>UCloud (优刻得科技股份有限公司)是中立、安全的云计算服务平台,坚持中立,不涉足客户业务领域。公司自主研发IaaS、PaaS、大数据流通平台、AI服务平台等一系列云计算产品,并深入了解互联网、传统企业在不同场景下的业务需求,提供公有云、混合云、私有云、专有云在内的综合性行业解决方案。</p> </div> <div class="right-footer layui-hidemd"> <ul class="flex_box_zd"> <li> <h6>UCloud与云服务</h6> <p><a href="https://www.ucloud.cn/site/about/intro/">公司介绍</a></p> <p><a href="https://zhaopin.ucloud.cn/" >加入我们</a></p> <p><a href="https://www.ucloud.cn/site/ucan/onlineclass/">UCan线上公开课</a></p> <p><a href="https://www.ucloud.cn/site/solutions.html" >行业解决方案</a></p> <p><a href="https://www.ucloud.cn/site/pro-notice/">产品动态</a></p> </li> <li> <h6>友情链接</h6> <p><a href="https://www.compshare.cn/?ytag=seo">GPU算力平台</a></p> <p><a href="https://www.ucloudstack.com/?ytag=seo">UCloud私有云</a></p> <p><a href="https://www.surfercloud.com/">SurferCloud</a></p> <p><a href="https://www.uwin-link.com/">工厂仿真软件</a></p> <p><a href="https://pinex.it/">Pinex</a></p> <p><a href="https://www.picpik.ai/zh">AI绘画</a></p> </li> <li> <h6>社区栏目</h6> <p><a href="https://www.ucloud.cn/yun/column/index.html">专栏文章</a></p> <p><a href="https://www.ucloud.cn/yun/udata/">专题地图</a></p> </li> <li> <h6>常见问题</h6> <p><a href="https://www.ucloud.cn/site/ucsafe/notice.html" >安全中心</a></p> <p><a href="https://www.ucloud.cn/site/about/news/recent/" >新闻动态</a></p> <p><a href="https://www.ucloud.cn/site/about/news/report/">媒体动态</a></p> <p><a href="https://www.ucloud.cn/site/cases.html">客户案例</a></p> <p><a href="https://www.ucloud.cn/site/notice/">公告</a></p> </li> <li> <span><img src="https://static.ucloud.cn/7a4b6983f4b94bcb97380adc5d073865.png" alt="优刻得"></span> <p>扫扫了解更多</p></div> </div> <div class="copyright">Copyright © 2012-2023 UCloud 优刻得科技股份有限公司<i>|</i><a rel="nofollow" href="http://beian.miit.gov.cn/">沪公网安备 31011002000058号</a><i>|</i><a rel="nofollow" href="http://beian.miit.gov.cn/"></a> 沪ICP备12020087号-3</a><i>|</i> <script type="text/javascript" src="https://gyfk12.kuaishang.cn/bs/ks.j?cI=197688&fI=125915" charset="utf-8"></script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?290c2650b305fc9fff0dbdcafe48b59d"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-DZSMXQ3P9N"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-DZSMXQ3P9N'); </script> <script> (function(){ var el = document.createElement("script"); el.src = "https://lf1-cdn-tos.bytegoofy.com/goofy/ttzz/push.js?99f50ea166557aed914eb4a66a7a70a4709cbb98a54ecb576877d99556fb4bfc3d72cd14f8a76432df3935ab77ec54f830517b3cb210f7fd334f50ccb772134a"; el.id = "ttzz"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(el, s); })(window) </script></div> </div> </footer> </body> <script src="https://www.ucloud.cn/yun/static/theme/ukd/js/common.js"></script> <<script type="text/javascript"> $(".site-seo-depict *,.site-content-answer-body *,.site-body-depict *").css("max-width","100%"); </script> </html>