> 文章列表 > 前端技巧总结---持续更新

前端技巧总结---持续更新

前端技巧总结---持续更新

易遗漏事件总结

关闭/保存后

  • 重置

    • 一些变量、表单
  • 考虑业务流程

  • 加载数据提示

移动端技巧总结

阿里图库

在原有的基础上加新图标

该代码替换掉原有的 iconfont.css

src 请求头要加https,要不然移动端会不显示阿里图标

onBackPress 返回上一级

onBackPress() {// ...自定义操作---提示(是否确认退出)
if (this.ruleForm.Id) {uni.navigateTo({// 跳转到平常页面url: '/pages/business/B_WayBill/B_WayBill'})} else {// 跳转到 tabbar 页面uni.switchTab({url: '/pages/work/work'})}return true
}

实现这种提示:

前端技巧总结---持续更新

<!--关闭按钮显示与否--><u-modal :closeOnClickOverlay="true" @close="show = false" @cancel="show = false" cancelText="继续编辑"confirmText="下次再编辑" :show="show" @confirm="close" :showCancelButton="true" title="还差一点就添加成功了"></u-modal>
// 点击左上角返回按钮触发
onBackPress() {this.show = truereturn true
}close(){uni.navigateTo(...)
}

❗close事件不要用 navigateBack 会进入死循环

✨路径传参

uni.navigateTo({url: `/pages/business/B_WayBill_Add/components/cargoMessage?rowData=${JSON.stringify(this.rowData)}&cargoData=${JSON.stringify(row)}`
});

❗如果传递的参数是对象,需要用 JSON.stringify 转成字符串,后面接受数据再用 JSON.parse 转成 object

条件编辑

  • // #ifdef H5
    // #endif// #ifdef APP-PLUS<!-- #ifndef MP-WEIXIN --> ✨除了这种之外<!-- #ifdef MP-WEIXIN -->
    

页面下拉刷新事件

async onPullDownRefresh() {this.getData()// 停止刷新uni.stopPullDownRefresh()
}// 同时要在 pages 里面设置

返回顶部

<!-- 返回顶部的按钮组件 -->
<u-back-top class="u-back-top" :iconStyle="{color:'#fff'}" icon="arrow-up" :scroll-top="scrollTop"></u-back-top>// 监听返回顶部按钮的距离
onPageScroll(e) {this.scrollTop = e.scrollTop;
}

页面重置到顶部

uni.pageScrollTo({scrollTop: 0,duration: 0
});

搜索定位

uni.pageScrollTo({scrollTop:dom元素(vue里面的ref).offsetTop,
})

图片预览

uni.previewImage({current: "",urls: [e],
})

页面跳转

// 页面会刷新触发onLoad(有表单组件的话需要存起来
uni.navigateTo()  
❗url要带'/',eg:'/pages/...'// 页面不会刷新(有表单组件
uni.navigateBack()

PC端技巧总结

element 多试试插槽,实现个性化样式

<template #title><el-tag effect="dark" size="large" style="margin-right: 10px;">主单号</el-tag>
</template>

分割组件 splitpanes

import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';<splitpanes style="height: 100%"><pane :size="40" v-if="!rowData"></pane>
</splitpanes>

vuex 的使用

const state = {lang:getLang(),
}const mutations = {SET_LANG(state, lang){state.lang = langsetLang(lang)}
}const actions = {changeLang({commit}, lang){commit('SET_LANG', lang)}
}export default {namespaced: true,state,mutations,actions,
}
import { mapState } from 'vuex'
import store from '@/store/index.js'computed: {...mapState("addOrderCargo", ["sendMessage", "recieveMessage", "productOptions", "inventoryData", "ruleForm"])
}store.getters.inventoryDatastore.commit('addOrderCargo/setproductOptions', res.data)

vue2 引入组件

import yhCascader from '@/components/YhCascader'components:{}// 全局 main.js
import yhUpload from '@/components/yh-upload/yh-upload'

watch

"sendMessage.MailingType": {handler(oldVal, newVal) {this.getSendAddress()},deep: true, // 深度监听immediate: true // 第一次改变就执行}

computed

计算后属性必须渲染后,绑定的方法才会生效这里指就是定义后的变量名在上面html中显示

vue3

引入组件

import yhCascader from '@/components/YhCascader'

判断数据类型

const keyType = data => {let type = Object.prototype.toString.call(data);if (type === '[object String]') {type = 'String';} else if (type === '[object Number]') {type = 'Number';} else if (type === '[object Null]') {type = 'Null';} else if (type === '[object Boolean]') {type = 'Boolean';} else if (type === '[object Array]') {type = 'Array';} else if (type === '[object Object]') {type = 'Object';} else {type = '未进行判断的类型:' + type;}return type;
};

对象包裹对象转换为数组

for in   +   push

filter

赋值数据

const data = res.data || []

总–总结

对象

深拷贝

JSON.parse(JOSN.Stringfy())

有key字段,但还需要value字段

  • 直接使用 . 加一个名称属性给 Object

不同属性类型共享同一个 object

对象赋值

for (let key in ruleForm) {ruleForm[key] = value[key]}

callBack 合理使用

封装组件需要注意的点

  • 显示与否

  • 传递数据另给一个 js 文件存放

    • import propsData from './props'

    • // props.js
      export default {leftColumns: {type: Array,default: () => []},
      }
      
  • 个性化–合理利用插槽

    • <slot name="rightTop"></slot>
  • 组件间传递数据

    • props emits
  • 数据更新问题

    • $nextTick

    • 定时器

      • setTimeout(()=> {emits('changeAfter')},200)
        
  • vue3 在 data 中 使用 compute

    • list:computed(()=>{...})
      
  • 使用三段式

    • let activeData = isAll ? getLeftData() : leftTableRef.value.getSelected():type="isShowLeftList ? 'info' : 'success'" 
      
  • 巧用 v-model

      • props:{value: {type: Array,default: () => [],}
        }
        
      • this.$emits('input',data)
        
    • 使用组件 用 v-model

    • v-model 的值就能关联 父里面的 data值了

❗v-if 会影响到 ref 的获取

请求接口参数

  • 拼接参数

    • ?a=${b}&
  • formData

async返回值都是 promise对象

解决:

  • 分开

    前端技巧总结---持续更新

    • 如果是 promise 的话,用 resolve返回

✨善于利用 uniapp 的 API + Promise

  • 代码式书写,解决先后执行问题

async removeBeforeAsync(id) {this.show = truelet returnBool = falseawait new Promise((resolve, reject) => {uni.showModal({title: '删除文件', //提示标题content: '是否删除该文件', //提示内容showCancel: true, //是否显示取消按钮success: async (res) => {if (res.confirm) { //confirm为ture,代表用户点击确定let res2 = await this.http.post('/api/B_WayBill_Files/DelWayBillFile?Id=' + id, {}, true)if (res2.Status) {this.$toast('删除成功!')} else {this.$toast('删除失败!', 'error')}returnBool = res2.Status} else if (res.cancel) { //cancel为ture,代表用户点击取消returnBool = false}resolve()}})})return returnBool},

请求接口的是否加载可以加在config里面

  • 用 axios 的请求拦截器接收

  • 请求拦截器接收之后可以再响应拦截器中拿到并判断关闭

实现左右滑动

.insure {display: flex;height: 520px;.left {width: 40%;// overflow: auto;.header {}}.right {flex: 1;// overflow: auto;}
}
  • elementUI有个滚动条样式

循环一般用来读取数据,而不要改变响应式数据

根据这个思路,可以把methods或者computed计算完的数据放置于数组中,再在响应式内直接读取数组元素

APP热更新

代码:https://blog.csdn.net/itopit/article/details/124620871

借鉴:https://blog.csdn.net/m_xiaozhilei/article/details/126485684

打包的wgt版本要与后端记录的一样,线下打包的可以搞成第一点版本的去测试

高亮与不高亮基本大小要一样才不会变来边去

请求参数如果没有就不添加:

let params = {}if (this.keyword2) {params["billNo"]=this.keyword2}if (this.startTime2 && this.endTime2) {params["beginTime"]=this.startTime2params["endTime"]=this.endTime2}

uniapp select被table遮挡

.uni-table-scroll{overflow-x: unset;}

this.$set解决新增的对象属性没有响应式(computed无效)

this.$set(this.rowData,'coupon',newVal * num || 0)// 优惠金额

图片

前端技巧总结---持续更新

uniapp展示本地图片使用image>标签都可以展示图片。但是<img>标签在网页端和真机模拟都不可以展示图片。

路径直接为 /static/… 不需要相对,不需要@符号。直接从/static目录往下写就行了

数组

新增元素

  • arr.splice(1,0,xx)
  • arr.push(xx)
  • arr.unshfit(xx)

在使用 <script setup> 的单文件组件中,导入的组件可以直接在模板中使用,无需注册

掉起拨打电话接口

<a :href="'tel:' + item.VehiclenoCarManTel">{{item.VehiclenoCarManTel}}</a>

vue2一个对象中的一个值是一个计算属性

怎么搞?—只有计算属性依赖项变化才回触发

devtools–给你的vue3项目的main.js加上这一句

app.config.devtools = true

vue 循环一定要弄key

  • 要不然顺序变化时会出现错误

js 计算精度问题

自己写公共方法:

/ 加/add(arg1, arg2) {var r1, r2, m, c;try {​      r1 = arg1.toString().split(".")[1].length;} catch (e) {​      r1 = 0;}try {​      r2 = arg2.toString().split(".")[1].length;} catch (e) {​      r2 = 0;}​    c = Math.abs(r1 - r2);​    m = Math.pow(10, Math.max(r1, r2));if (c > 0) {var cm = Math.pow(10, c);if (r1 > r2) {​        arg1 = Number(arg1.toString().replace(".", ""));​        arg2 = Number(arg2.toString().replace(".", "")) * cm;} else {​        arg1 = Number(arg1.toString().replace(".", "")) * cm;​        arg2 = Number(arg2.toString().replace(".", ""));}} else {​      arg1 = Number(arg1.toString().replace(".", ""));​      arg2 = Number(arg2.toString().replace(".", ""));}return (arg1 + arg2) / m;},/ 减/sub(arg1, arg2) {var r1, r2, m, n;try {​      r1 = arg1.toString().split(".")[1].length;} catch (e) {​      r1 = 0;}try {​      r2 = arg2.toString().split(".")[1].length;} catch (e) {​      r2 = 0;}​    m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //动态控制精度长度​    n = r1 >= r2 ? r1 : r2;return Number(((arg1 * m - arg2 * m) / m).toFixed(n));},/ 乘/mul(arg1, arg2) {var m = 0,​      s1 = arg1.toString(),​      s2 = arg2.toString();try {​      m += s1.split(".")[1].length;} catch (e) {}try {​      m += s2.split(".")[1].length;} catch (e) {}return (Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) / Math.pow(10, m);},/ 除/div(arg1, arg2) {var t1 = 0,​      t2 = 0,​      r1,​      r2;try {​      t1 = arg1.toString().split(".")[1].length;} catch (e) {}try {​      t2 = arg2.toString().split(".")[1].length;} catch (e) {}​    r1 = Number(arg1.toString().replace(".", ""));​    r2 = Number(arg2.toString().replace(".", ""));return (r1 / r2) * Math.pow(10, t2 - t1);},

或者xe-utils 解决 js 加减乘除精度问题

善于使用对象处理(存储)多数据

let obj = {}
obj[key] = xx

❗一定一定要记得复杂数据类型的特殊性,需求如果是不改变原数据一定要深拷贝

// 一般使用 JSON.stringify 进行拷贝---在获取的时候用JSON.parse来解构就行了在用store存储、作为参数传递过去、赋值等等操作一定要注意

❗❗❗removeEventListener

addEventListener 之后一定要记得 removeEventListener
  • 取消对一个全局事件的监听。

插件的结束时期

数据传输 传过去=》再传回来(用 uni.navigateTo)

插件使用

❗❗❗回调函数里面如果需要用到 this 记得该回调函数一定得写成箭头函数

存储

要记得 JSON.stringfy 再存储

uni.setStorageSync(app_user_timestamp, JSON.stringify(Date.now())) //设置时间戳

uniapp FormData 形式的参数得更改请求头

if (isFormData) _header['Content-Type'] = 'application/x-www-form-urlencoded'// 传递的参数是对象

对象

对象一整个赋值会改不到数据,要用 . 来更改属性值

搜索定位功能

uni.pageScrollTo({scrollTop: this.$refs[res.Data.BillInfo.BillNo][0].$el.offsetTop-310,duration: 0});
let obj = {}
obj[key] = xx

❗一定一定要记得复杂数据类型的特殊性,需求如果是不改变原数据一定要深拷贝

// 一般使用 JSON.stringify 进行拷贝---在获取的时候用JSON.parse来解构就行了在用store存储、作为参数传递过去、赋值等等操作一定要注意

❗❗❗removeEventListener

addEventListener 之后一定要记得 removeEventListener
  • 取消对一个全局事件的监听。

插件的结束时期

数据传输 传过去=》再传回来(用 uni.navigateTo)

插件使用

❗❗❗回调函数里面如果需要用到 this 记得该回调函数一定得写成箭头函数

存储

要记得 JSON.stringfy 再存储

uni.setStorageSync(app_user_timestamp, JSON.stringify(Date.now())) //设置时间戳

uniapp FormData 形式的参数得更改请求头

if (isFormData) _header['Content-Type'] = 'application/x-www-form-urlencoded'// 传递的参数是对象

对象

对象一整个赋值会改不到数据,要用 . 来更改属性值

搜索定位功能

uni.pageScrollTo({scrollTop: this.$refs[res.Data.BillInfo.BillNo][0].$el.offsetTop-310,duration: 0});

v-for涉及到增删改查时一定好设置一个唯一的id❗