当前位置:网站首页>How to realize sliding operation component in fast application
How to realize sliding operation component in fast application
2022-07-07 08:48:00 【Huawei Developer Forum】
1. What is a sliding operation component
In the actual way of mobile application interaction , The most common is the sliding operation . Like sliding left and right to switch pages , Open your fingers to enlarge the picture , It is all done by sliding . In this paper, the sliding operation component refers to the hidden operation button through gesture sliding .
As shown in the figure below :
chart 1 QQ app | chart 2 Huawei SMS app |
The above sliding operation components have the following characteristics :
- Both left and right sliding support , Slide to exhale 、 Hide the operation button bar ;
- Operation buttons can be configured with multiple ;
- Operate the button to set the background color 、 typeface 、 Width etc. ;
- Click the operation button , You can hide the operation bar ;
- When calling out the operation bar , Interface all UI Elements move accordingly ;
2 Basic implementation
2.1 Sliding operation component design
Define components that support sliding operations swipe_item, Parent component reference , Pass action buttons when referencing 、 Operation button style . The sliding operation sub component needs to realize gesture sliding processing .
The code structure is as follows :
<import name="swipeitem" src="../Component/swipe_item.ux"></import><template><div class="container"><swipeitem right-options="{{rightBtns}}" left-options="{{leftBtns}}" @swipebtnclick="swipeItemClick"><text> There are mixed scrolls on both sides </text></swipeitem></div></template>
2.2 Child components swipe_item Attribute design
2.3 Supported properties
attribute | type | Whether the choice | The default value is | describe |
identity | Number | no | Component unique identification , When autoClose by true when , You have to set | |
disabled | Boolean | no | false | Whether sliding is prohibited |
autoClose | Boolean | yes | true | Slide to open the current component , Whether to close other components |
threshold | Number | no | 30 | Slide the default distance |
leftOptions | Array[Option] | no | The content and style of the left operation bar | |
rightOptions | Array[Option] | no | The content and style of the right operation bar |
Option The object parameters are as follows :
attribute | type | Whether the choice | describe |
txt | String | no | Button text |
style | Object | yes | Button style |
style The object parameters are as follows :
attribute | type | Whether the choice | describe |
backgroundColor | Color | no | Button background color |
txtColor | Color | no | Button color |
fontsize | Number | no | Text size |
btnwidth | Number | yes | Button width |
Supported events
Event name | Event passing parameters | describe |
swipebtnclick | {clickIndex:1, position:left|right, btnValue:btnText} | The event will be triggered when the button on the operation bar is clicked ; clickIndex: Click the button array index on the left or right operation bar ; position: The position of the operation bar clicked , The parameter values are left and right; btnValue: Click the button text ; |
centerclick | {} | An event is triggered when you click the content displayed in the middle of the screen |
swipestatechange | {isOpened:true|false} | Triggered when the action bar is opened or closed |
2.4 swipe_item Sub component layout
- Layout structure : From the left operation bar + The middle screen displays content + Horizontal composed of the right operation bar div;
- Left operation bar 、 The right operation bar is based on leftOptions、rightOptions Operation option content array , For adoption for Loop to form horizontal layout rendering ;
- The content displayed on the screen in the middle is dynamic , The content to be displayed for each product and UI Is different , So we used slot slot , By use swipe_item Component page to complete the layout of the intermediate content .
- The width of the middle layout needs to set the width of the whole screen , namely 750px;
2.5 swipe_item Child components css
- Width : Although the left and right operation bars of the sliding operation component are hidden in the initial state , But it is actually part of the whole layout , If the width of the root node cannot be calculated correctly , When it will cause sliding , There is nothing on the operation bar .
- Animation : In the initial state , The left and right operation bars need to be hidden , Only the middle content is visible . Under normal layout ( See the picture 3), The left operation bar is displayed , So we used transform Animation style , Translate the root node by the width of the left operation bar , This ensures that the operation bar is hidden in the initial state .
- Button background color 、 Text size 、 Text color : If the parent component is not set , Set the default value of the sub component , See the picture 4;
chart 3 Normal layout effect | chart 4 The default background color effect of operation bar buttons |
2.6 Gesture slide
Monitor gestures touchstart、touchmove、touchend event , Calculate the sliding pixels of fingers , At the same time call X Translation animation of axis animate Method , Realize the moving effect of components .
- touchstart: Record the starting touch point ;
- touchmove: Sliding distance ds>0 Indicates that the finger slides to the right , On the contrary, slide left , During the sliding process animate() Mobile components , Achieve the effect of opening or hiding the operation bar ; If the sliding distance is less than the threshold threshold, Do not trigger the movement effect ; If sliding is prohibited, that is disabled The value is true when , Nor can it trigger the sliding effect ;
- touchend: Triggered at the end of the slide , call animate() Control the final display position of the operation bar , Need to calculate accurately , Prevent components from moving too far or too close , thus UI The effect is abnormal .
2.8 Parent-child component communication
When you click the button on the sub component operation bar , The parent component is required to handle the business logic , adopt $emit() Send notification to parent component . Be careful , Do not deal with business logic in subcomponents , Otherwise, the code cannot be maintained .
1) Click the event notification button on the operation bar
- When a page calls a sub component , monitor swipebtnclick event ;
- Subcomponent call $emit() Send a notification to the page ;
2) Click event notification in the middle part
- When a page calls a sub component , monitor centerclick event ;
- When the operation bar is open , Click the middle part to hide the operation bar . Only when the operation bar is hidden , When clicking on the middle part , Subcomponent call $emit() Send a notification to the page , The page handles the business logic by itself , For example, open a new page .
3) The operation bar opens 、 Turn off event notification
- When a page calls a sub component , monitor swipestatechange event ;
- When the operation bar is open or closed , Subcomponent call $emit() Send a notification to the page .
The relevant code is as follows :
2.9 autoClose Realization
When sliding to open the current component , Whether to close other components , When autoClose Set to true when ,identity Property must be set , And uniquely identify the current sub component .
- When Child components 1 When the operation bar is opened , adopt $emit() Send status event to page swipestatechange;
- Parent listening swipestatechange event , adopt $broadcast() Method to send a shutdown notification event to the sub component closeSwipeItem, Inform others Child components 2,3,4 Wait to close the open operation bar ;
- Child components 1,2,3,4 Wait until the monitoring is turned off closeSwipeItem event , Handle the closing logic in the event handle , Note that the operation bar opens Child components 1 You will also receive a shutdown event , Here we need to judge identity value , Make sure that the newly opened Child components 1 There will be no phenomenon of opening and closing .
3 summary
- Learn and be familiar with the design and attribute definition of quick application sub components ;
- Learn and be familiar with fast application gesture events ;
- Learn and be familiar with fast application animation ;
- Pay attention to the sliding operation sub assembly swipe_item stay list-item China doesn't work .
4 Code appendix
Slide operation sub assembly swipe_item.ux
<template> <!-- Only one root node is allowed in template. --> <div class="container" style="{{containerStyle}}" > <div id="swipe_item" class="swipe" ontouchstart="dealTouchStart" ontouchmove="dealTouchMove" ontouchend="dealTouchEnd" > <div class="left" id="leftbtns"> <block for="(index,item) in leftOptions"> <input type="button" class="btn" style="background-color: {{calBtnBgColor(item.style.backgroundColor)}}; color:{{calBtnTxtColor(item.style.txtColor)}}; font-size:{{calBtnFontSize(item.style.fontsize)}}px;width:{{item.style.btnwidth}}px;" value="{{item.txt}}" onclick="btnsClick(index,'left',item.txt)"> </input> </block> </div> <div class="center" style="width:{{deviceLogicWidth}}px" onclick="dealClickCenter"> <slot ></slot> </div> <div class="right" id="rightbtns"> <block for="(index,item) in rightOptions"> <input type="button" class="btn" style="background-color: {{calBtnBgColor(item.style.backgroundColor)}}; color:{{calBtnTxtColor(item.style.txtColor)}}; font-size:{{calBtnFontSize(item.style.fontsize)}}px;width:{{item.style.btnwidth}}px;" value="{{item.txt}}" onclick="btnsClick(index,'right',item.txt)"> </input> </block> </div> </div> </div></template><style> .container { flex-direction: column; justify-content: center; } .swipe { flex-direction: row; align-items: center; } .txt { font-size: 40px; width: 100%; height: 100%; } .btn { height: 100%; } .left { flex-direction: row; flex-shrink: 0; height: 100%; background-color: #a9a9a9; } .center { flex-direction: row; align-items: center; padding: 16px; flex-shrink: 0; } .right { flex-direction: row; flex-shrink: 0; height: 100%; background-color: #a9a9a9; }</style><script> import device from '@system.device'; const defaultBtnBg="#f01f1f"; const defaultBtnFontSize=32; const defaultBtnTxtColor="#dcdcdc"; module.exports = { props: { // Ban disabled: { type: Boolean, default: false }, identity:{ type: String, default: '0', }, // Whether to turn off automatically autoClose: { type: Boolean, default: true }, // Slide the default distance threshold: { type: Number, default: 30 }, // Left button content leftOptions: { type: Array, default() { return [] } }, // Button content on the right rightOptions: { type: Array, default() { return [] } } }, data: { movestartX: 0, lastMoveX:0, translateEndX: 0, leftbtnsWidth: 0, rightbtnsWidth: 0, deviceLogicWidth:750, isLeftOpened: false, isRightOpened: false }, computed: { containerStyle() { console.info("computed containerStyle begin") var style = ''; let totalwidth=0; let leftwidth=0; this.leftOptions.forEach((item, index, array) => { console.info("computed item="+JSON.stringify(item)); leftwidth+=item.style.btnwidth; }) this.rightOptions.forEach((item, index, array) => { totalwidth+=item.style.btnwidth; }) totalwidth=totalwidth+this.deviceLogicWidth+leftwidth; console.info("computed totawidth="+totalwidth+", left width="+leftwidth); style += 'width:' + totalwidth + 'px;' style += 'transform: translateX(-' + leftwidth + 'px);' return style; } }, calBtnBgColor(color){ if(color!==undefined){ return color; } return defaultBtnBg; }, calBtnFontSize(size){ if(size!==undefined){ return size; } return defaultBtnFontSize; }, calBtnTxtColor(color){ if(color!==undefined){ return color; } return defaultBtnTxtColor; }, onInit() { console.info("oninit()"); this.$on('closeSwipeItem', this.closeFromParent); setTimeout(() => { this.calWidth(); }, 500); }, calWidth() { this.calLeftBtnsWidth(); this.calRightBtnsWidth(); }, calLeftBtnsWidth() { var that = this; this.$element('leftbtns').getBoundingClientRect({ success(res) { let msg = JSON.stringify(res); console.log('calLeftBtnsWidth Current coordinates :' + msg); // that.leftbtnsWidth = res.width; that.convertRealPx(true, res.width); }, fail() { console.log('calBoxWidth Acquisition failure '); }, complete() { console.log('calBoxWidth complete') } }) }, calRightBtnsWidth() { var that = this; this.$element('rightbtns').getBoundingClientRect({ success(res) { let msg = JSON.stringify(res); console.log('calRightBtnsWidth Current coordinates :' + msg); // that.rightbtnsWidth = res.width; that.convertRealPx(false, res.width); }, fail() { console.log('calBoxWidth Acquisition failure '); }, complete() { console.log('calBoxWidth complete') } }) }, convertRealPx(isLeftWidth, data) { var d = device.getInfoSync(); console.info("calBannerPostion1 d= " + JSON.stringify(d)); // Get the height and width of the visible window in the page , This value does not include the title bar and status bar heights let windowWidth = d.windowWidth; //logicWidth Corresponding manifest.json File settings designWidth value , The default is 750 let logicWidth = d.windowLogicWidth; let result = data * 1.0 * windowWidth / logicWidth; if (isLeftWidth) { this.leftbtnsWidth = result; } else { this.rightbtnsWidth = result; } }, dealTouchStart: function (e) { if (this.disabled) { return; } this.movestartX = e.touches[0].clientX; console.info("dealTouchStart movestartX="+this.movestartX); }, dealTouchMove: function (e) { if (this.disabled) { return; } let moveX = e.touches[0].clientX; let dis = moveX - this.movestartX; console.info("dealTouchMove moveX= " + moveX + ", dis=" + dis); if (Math.abs(dis) < this.threshold) { return; } if (dis > 0) { // Slide the button on the left right to call out or hide the button on the right to restore the initial state if (this.isRightOpened) { // Hide the button on the right , Restore to initial state this.animate(dis-this.rightbtnsWidth, dis); } else { // Slide right , Exhale the button on the left if (this.leftbtnsWidth > 0) { if (!this.isLeftOpened) { console.info("begin to show the left buttons"); this.animate(dis, dis); } } } } else if (dis < 0) { console.info("dealTouchMove left this.isLeftOpened=" + this.isLeftOpened); if (this.isLeftOpened) { // Slide slowly to hide the left button this.animate(this.leftbtnsWidth + dis, dis); } else { // Call out the button on the right if (this.rightbtnsWidth > 0) { if (!this.isRightOpened) { console.info("dealTouchMove begin to show the right buttons"); this.animate(dis, dis); } } } } }, dealTouchEnd: function (e) { if (this.disabled) { return; } let endX = e.changedTouches[0].clientX; let dis = endX - this.movestartX; if (Math.abs(dis) < this.threshold) { return; } console.info("dealTouchEnd dis=" + dis + ", endX=" + endX + ", isLeftOpened=" + this.isLeftOpened + ",isRightOpened=" + this.isRightOpened); if (dis > 0) { // Slide to the right if (this.isRightOpened) { // Hide the right button this.animate(dis - this.rightbtnsWidth, 0); this.isRightOpened = false; this.$emit('swipestatechange', {params: {"isOpened":false}}); } else { if (!this.isLeftOpened) { // Exhale the left button , Display the left button completely ; if (this.leftbtnsWidth > 0) { this.animate(dis, this.leftbtnsWidth); this.isLeftOpened = true; this.$emit('swipestatechange', {params: {"isOpened":true}}); } } } } else if (dis < 0) { // Slide left if (this.isLeftOpened) { // Hide the left button this.animate(this.leftbtnsWidth + dis, 0); this.isLeftOpened = false; this.$emit('swipestatechange', {params: {"isOpened":false}}); } else { if (this.rightbtnsWidth > 0 && !this.isRightOpened) { // Call out the right button , Display the right button completely this.animate(dis, -this.rightbtnsWidth); this.isRightOpened = true; this.$emit('swipestatechange', {params: {"isOpened":true}}); } } } }, animate(value1, value2) { console.info("aninate translateX from: " + value1 + ", to:" + value2); let cmp = this.$element('swipe_item'); var options = { duration: 300, easing: 'linear', delay: 0, fill: 'forwards' } console.info("dealTouchMove value2=" + value2); var frames = [ { transform: { translateX: value1, } }, { transform: { translateX: value2, } }]; var animation = cmp.animate(frames, options); animation.play(); animation.onfinish = function () { console.log("animation onfinish"); } animation.oncancel = function () { console.log("animation oncancel"); } }, btnsClick: function(index,direction,btnValue) { console.info("swipe.ux item click direction="+direction); this.$emit('swipebtnclick', {params: {"clickIndex":index,"position":direction,"btnValue":btnValue}}); // Button close if(direction=='left'){ this.animate(this.leftbtnsWidth, 0); this.isLeftOpened = false; }else{ this.animate( - this.rightbtnsWidth, 0); this.isRightOpened = false; } this.$emit('swipestatechange', {params: {"isOpened":false}}); }, close:function() { if(this.isLeftOpened){ // close this.animate(this.leftbtnsWidth, 0); this.isLeftOpened = false; this.$emit('swipestatechange', {params: {"isOpened":false}}); }else if(this.isRightOpened){ // close this.animate( - this.rightbtnsWidth, 0); this.isRightOpened = false; this.$emit('swipestatechange', {params: {"isOpened":false}}); }else{ // The middle part responds to its own click event this.$emit('centerclick', {params: {}}); } }, closeFromParent:function(e) { console.info("closeFromParent e="+JSON.stringify(e)); if(!this.autoClose){ return; } // The newly opened operation bar is not closed , Others are only closed let excludeCloseId=e.detail.exclude; if(excludeCloseId==this.identity){ return; } if(this.isLeftOpened){ // close this.animate(this.leftbtnsWidth, 0); this.isLeftOpened = false; }else if(this.isRightOpened){ // close this.animate( - this.rightbtnsWidth, 0); this.isRightOpened = false; } }, dealClickCenter: function() { console.info("dealClickCenter"); this.close(); }, }</script> page main.ux<import name="swipeitem" src="../Component/swipe_item.ux"></import><template> <!-- Only one root node is allowed in template. --> <div class="container"> <div class="section"> <text class="sec_txt"> Only on the left </text> </div> <swipeitem identity='111' left-options="{{leftBtns}}" @swipebtnclick="swipeItemClick" @swipestatechange="swipeItemChange('111')"> <text> Only the left button </text> </swipeitem> <div class="section"> <text class="sec_txt"> Only the right </text> </div> <swipeitem identity='112' right-options="{{rightBtns}}" @swipebtnclick="swipeItemClick" @swipestatechange="swipeItemChange('112')"> <text> Only the right button </text> </swipeitem> <div class="section"> <text class="sec_txt"> Blend scrolling </text> </div> <swipeitem identity='113' right-options="{{rightBtns}}" left-options="{{leftBtns}}" @swipebtnclick="swipeItemClick" @swipestatechange="swipeItemChange('113')"> <text> There are mixed scrolls on both sides </text> </swipeitem> <div class="section"> <text class="sec_txt"> Do not scroll left or right </text> </div> <swipeitem disabled="{{disabled}}" left-options="{{leftBtns}}" right-options="{{rightBtns}}" @swipebtnclick="swipeItemClick"> <text> Do not scroll left or right </text> </swipeitem> <div class="section"> <text class="sec_txt">div list </text> </div> <div class="swipelist" id="swiplist"> <swipeitem identity="{{item.id}}" auto-close={{isautoclose}} right-options="{{item.options}}" for="(index,item) in swipeList" @swipestatechange="listSwipeItemChange(index)" @swipebtnclick="listSwipeItemClick(index)" @centerclick="listCenterItemClick(index)"> <text onclick="clickText">{{item.content}}</text> </swipeitem> </div> </div></template><style> .container { flex-direction: column; width: 100%; } .section { background-color: #f5f5f5; height: 100px; width: 100%; border: 1px solid #f5f5f5; } .swipelist { flex-direction: column; } .istItemStyle { width: 1300px; } .liststyle { flex-direction: column; } .sec_txt { font-size: 32px; font-weight: 600; margin-left: 25px; margin-top: 10px; }</style><script> import prompt from '@system.prompt'; module.exports = { data: { isautoclose:true, leftBtns: [], disabled: true, rightBtns: [], unstyleleftBtns: [], unstylerightBtns: [], swipeList: [] }, onInit: function () { let btn1 = { "txt": " Roof placement ", "style": { "backgroundColor": "#00bfff", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 150 } }; let btn2 = { "txt": "ok", "style": { "backgroundColor": "#00bfff", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 200 } }; let btn3 = { "txt": " Cancel topping ", "style": { "backgroundColor": "#f01f1f", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 150 } }; let btn4 = { "txt": "cancel", "style": { "backgroundColor": "#00bfff", "txtColor": "#dcdcdc", "fontsize": 30, "btnwidth": 180 } }; let unstylebtn1 = { "txt": " Roof placement ", "style": { "btnwidth": 230 } }; let unstylebtn2 = { "txt": "ok", "style": { "btnwidth": 200 } }; let unstylebtn3 = { "txt": " Cancel topping ", "style": { "btnwidth": 150 } }; let unstylebtn4 = { "txt": "cancel", "style": { "txtColor": "#ff9900", "fontsize": 30, "btnwidth": 150 } }; this.leftBtns.push(btn1); this.leftBtns.push(btn2); this.rightBtns.push(btn3); this.rightBtns.push(btn4); this.unstyleleftBtns.push(unstylebtn1); this.unstyleleftBtns.push(unstylebtn2); this.unstylerightBtns.push(unstylebtn3); this.unstylerightBtns.push(unstylebtn4); }, onReady(options) { this.swipeList = [{ options: [{ txt: ' add to ', style: { backgroundColor: 'rgb(255,58,49)', txtColor: "#dcdcdc", fontsize: 36, btnwidth: 150 } }], id: '10', content: 'item1' }, { id: '11', options: [{ txt: ' add to ', style: { backgroundColor: 'rgb(255,58,49)', txtColor: "#dcdcdc", fontsize: 30, btnwidth: 150 } }, { txt: ' Delete ', style: { backgroundColor: 'rgb(255,58,49)', txtColor: "#dcdcdc", fontsize: 30, btnwidth: 150 } } ], content: 'item2' }, { id: '12', options: [{ txt: ' Roof placement ', style: { backgroundColor: 'rgb(255,58,49)', txtColor: "#dcdcdc", fontsize: 30, btnwidth: 150 } }, { txt: ' Mark as read ', style: { backgroundColor: 'rgb(255,58,49)', txtColor: "#dcdcdc", fontsize: 30, btnwidth: 150 } }, { txt: ' Delete ', style: { backgroundColor: 'rgb(255,58,49)', txtColor: "#dcdcdc", fontsize: 30, btnwidth: 150 } } ], content: 'item3' } ] }, listSwipeItemClick: function (index, e) { console.info("main swipeItemClick e:" + JSON.stringify(e) + ",index=" + index); let position = e.detail.params.position; // // let index = e.detail.params.clickIndex; // let itemListId = e.detail.params.itemListIndex; let btnValue = e.detail.params.btnValue; let msg = ''; if (position == 'left') { // msg=' Click on the left ${e.detail.params.btnValue} Button ' ; msg = ' Click on the left ' + btnValue + ' Button '; } else { msg = ' Click on the right ' + btnValue + ' Button '; } prompt.showToast({ message: msg, duration: 2000, gravity: 'center' }) if (btnValue == " add to ") { console.info("begin to add ") this.addSwipteItem(); } else if (btnValue == " Delete ") { this.delSwipteItem(index); } }, addSwipteItem: function () { this.swipeList.push({ id: new Date().getTime(), content: ' newly added ' + new Date().getTime(), options: [{ txt: ' Roof placement ', style: { fontsize: 30, btnwidth: 150 } }, { txt: ' Mark as read ', style: { backgroundColor: 'rgb(254,156,1)', fontsize: 30, btnwidth: 150 } }, { txt: ' Delete ', style: { backgroundColor: 'rgb(255,58,49)', fontsize: 30, btnwidth: 150 } } ], }); }, delSwipteItem: function (index) { var that = this; prompt.showDialog({ title: ' Tips ', message: ' Whether or not to delete ', buttons: [ { text: ' determine ', color: '#33dd44' }, { text: ' Cancel ', color: '#33dd44' }], success: function (data) { console.log("delSwipteItem showDialog handling callback data:" + JSON.stringify(data)); if (data.index == 0) { //delete that.swipeList.splice(index, 1); } }, fail: function (data, code) { console.log("handling fail, code = " + code); } }) }, swipeItemClick: function (e) { console.info("main swipeItemClick e:" + JSON.stringify(e)); let position = e.detail.params.position; let btnValue = e.detail.params.btnValue; let msg = ''; if (position == 'left') { // msg=' Click on the left ${e.detail.params.btnValue} Button ' ; msg = ' Click on the left ' + btnValue + ' Button '; } else { msg = ' Click on the right ' + btnValue + ' Button '; } prompt.showToast({ message: msg, duration: 2000, gravity: 'center' }) }, clickText: function () { console.info("click text"); prompt.showToast({ message: 'click text', duration: 2000, gravity: 'center' }) }, listCenterItemClick: function (index, e) { console.info("main listCenterItemClick e:" + JSON.stringify(e) + ",index=" + index); prompt.showToast({ message: 'click text', duration: 2000, gravity: 'center' }) }, listSwipeItemChange: function (index, e) { console.info("main listSwipeItemChange e:" + JSON.stringify(e) + ",index=" + index); this.$broadcast('closeSwipeItem', { 'exclude': this.swipeList[index].id }); }, swipeItemChange: function(id,e) { console.info("main swipeItemChange e:" + JSON.stringify(e)+",id="+id); this.$broadcast('closeSwipeItem', { 'exclude': id }); }, }</script>
For more technical articles , Welcome to visit https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh
边栏推荐
- Input of mathematical formula of obsidan
- Explain Huawei's application market in detail, and gradually reduce 32-bit package applications and strategies in 2022
- Rapid integration of authentication services - harmonyos platform
- Greenplum6.x监控软件搭建
- [machine learning] watermelon book data set_ data sharing
- 指针进阶,字符串函数
- Upload an e-office V9 arbitrary file [vulnerability recurrence practice]
- Download and install orcale database11.2.0.4
- ncs成都新电面试经验
- POJ - 3784 running medium
猜你喜欢
let const
Arm GIC (IV) GIC V3 register class analysis notes.
ncs成都新電面試經驗
Are you holding back on the publicity of the salary system for it posts such as testing, development, operation and maintenance?
[MySQL] detailed explanation of trigger content of database advanced
Data type - integer (C language)
Greenplum6.x搭建_环境配置
Greenplum6.x常用语句
[hard core science popularization] working principle of dynamic loop monitoring system
最长上升子序列模型 AcWing 1017. 怪盗基德的滑翔翼
随机推荐
Quick sorting (detailed illustration of single way, double way, three way)
Lenovo hybrid cloud Lenovo xcloud: 4 major product lines +it service portal
Image segmentation in opencv
Database storage - table partition
【踩坑】nacos注册一直连接localhost:8848,no available server
数据分析方法论与前人经验总结2【笔记干货】
如何在快应用中实现滑动操作组件
Greenplum 6.x monitoring software setup
Uniapp wechat applet monitoring network
2 - 3 arbre de recherche
Qt Charts使用(重写QChartView,实现一些自定义功能)
23 Chengdu instrument customization undertaking_ Discussion on automatic wiring method of PCB in Protel DXP
[南京大学]-[软件分析]课程学习笔记(一)-introduction
oracle一次性说清楚,多种分隔符的一个字段拆分多行,再多行多列多种分隔符拆多行,最终处理超亿亿。。亿级别数据量
Greenplum6.x搭建_安装
opencv之图像分割
调用华为游戏多媒体服务的创建引擎接口返回错误码1002,错误信息:the params is error
Mock. JS usage details
[Yugong series] February 2022 U3D full stack class 005 unity engine view
测试踩坑 - 当已有接口(或数据库表中)新增字段时,都需要注意哪些测试点?