前端开发中常用的知识点
思维导图
- xmind
idea快捷键
- 格式化 ctrl+alt+l
- 选中 shift+上、下、左、右
- .log 控制台
.const 局部变量(不可变)
.var 声明是全局作用域或函数作用域,var 变量可以在其范围内更新和重新声明
.let 变量可以被更新但不能重新声明 - 两次shift 搜索
- ctrl+x 剪切
- ctrl + D 复制当前行到下一行
- alt + 回车
- alt + / 代码提示
- ctrl+shift + insert
- 展开/缩起 ctrl+shift + '+/-'
uni常用api
生命周期
- 小程序加载事件
- onLunch 小程序加载完成
- onShow 小程序显示
- onHide 小程序隐藏
- onError 小程序加载错误
- 页面加载事件
- onLoad 页面加载完成了
- onShow 页面显示了
- onReady 页面初次渲染完成
- onHide 页面隐藏了
存储数据
常用api
- 设置数据
- uni.setStorage
- uni.setStorageSync
- 移除数据
- uni.removeStorage
- uni.removeStorageSync
- 跳转路径,应尽量使用绝对路径
- uni.navigateTo 保留当前页面,跳转到应用内的某个页面
- uni.switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
- uni.redirectTo 关闭当前页面,跳转到应用内的某个页面
- uni.reLaunch 关闭所有页面,打开到应用内的某个页面
- uni.navigateBack 关闭当前页面,返回上一页面或多级页面
筛选符合条件,用于搜索 map ()
export default{
data:{
brandList: [],
view:{}
},
methods:{
showBrandList() {
const map = {};//定义一个map
for (let item of this.brandList) {
const {
brandKey = "",
brandName = "",
} = item
if ( !uni.$u.test.isEmpty(this.view.keyword)) {
console.log('isEmpty');
if (brandKey.includes(this.view.keyword) ||brandName.includes(this.view.keyword)) {
}else {
continue;
}
}
//拼音的首字母
const key = brandKey.substring(0, 1);
if (!map[key]) {
map[key] = {
name: key,
list: [],
}
}
map[key].list.push(item)
}
const list = Object.values(map).sort((l, r) => {
return l.name.localeCompare(r.name)})
return list;
}
}
}
写store缓存数据
更新的缓存pinia
import Vuex from "vuex";//首先导入vuex
export const WorkOrderStore = new Vuex.Store({//定义变量导出
state:{
completedProject:[],//完成项目后将历史项目放在这儿,并删workOrderLisL里面对应的数据
workOrderList:[],//保存了automobile+projectList的数据
automobile:undefined,
projectList:[],
},
mutations:{
setAutomobile(state,data){
state.automobile = data;
}
},
})
//在引入页
export default{
import WorkOrderStore from './WorkOrderStore'
data(){
return{
item:undefine
}
},
methods:{
myEvent(){
WorkOrderStore.store.commit('setAutomobile',this.item)
}
}
}
将对象push到数组里面
const array = [];
obj a = {};
obj b = [];
obj c = {a,b},
array.push(c)
封装枚举数据
//封装第一个文件
export function defineEnumObj(key, label) {
return {
k: key,
v: label,
}
}
export default {
getLabel(enums,key){
let item = this.valueOf(enums,key);
return item?.v;
},
valueOf(enums,itemKey){
for (let key in enums) {
let item = enums[key]
if (item.k === itemKey) {
return item;
}
}
return undefined;
},
defineEnumObj
}
//第二个文件导入第一个文件,然后定义想要的枚举
import {defineEnumObj} from "url";
export default {
Coupons:{
Type:{
COMBO:defineEnumObj('COMBO',"套餐券"),
EXCHANGE:defineEnumObj('EXCHANGE',"兑换券"),
DISCOUNT:defineEnumObj('DISCOUNT',"折扣券"),
DEDUCTION:defineEnumObj('DEDUCTION',"满减券"),
}
}
}
封装后台数据请求axios 做成api
//axios---封装http----使用http----基础写好后写不同的api(后台给的地址)
//第一个文件导入
import axios from "axios";
import {getBase} from "./Base";
//1、封装http
export function http(url, data, config) {
if (!url.startsWith("/")) {
url = "/" + url
}
// @ts-ignore
let URL = getBase().host + url;
if (uni) {
return new Promise((success,fail)=>{
uni.request({
method:"POST",
url:URL,
data,
header:getHeader(),
...config,
success,
fail
})
})
// return uni.request({
// method:"POST",
// url:URL,
// data,
// header:getHeader(),
// ...config,
//
// })
}else {
return axios({
method: "POST",
url: URL,
data,
headers: getHeader(),
...config,
})
}
}
//getBase.js
let host;
if (model === 'dev') {
host = "http://192.168.0.109:8082"
} else if (model === 'cart') {
host = "https://yoururl"
} else {
host = 'https://yoururl'
}
//第二个文件 使用http
export function ApiClient({url, data = {}}) {
return new Promise((succ, fail) => {
http(url, data, {}).then((({data}) => {
DataHandle(data, succ, fail)
})).catch(e => {
fail(e)
})
})
}
export function DataHandle(data, succ, fail) {
if (data.code == 200) {
succ(data)
} else {
let message
if (data.code == 503) {
message = data.msg
} else {
message = "系统异常"
}fail(data)
}
}
//第三个文件(一般只需要动这儿)
//3、基础写好后写不同的api
//导入第二个文件的ApiClient(上面是这样命名,名字随意,有意义就行)(如果有多种请求,那个可以继续封装url----)
export default {
content_user_list(data){//获取内容
return ApiClient({
url:"/content/user/list",
data
})
},
content_user_get(data){//获取内容详情
return ApiClient({
url:"/content/user/get",
data
})
},
}
遍历数组中的某一项放到新数组中
contentList.map(o=>o._cover=o.cover[0])
dayjs 可以日期转化
模态框 uview自带是组件,uniapp是api,用api可以监听变化
uni.showModal
强制刷新
this.$forceUpdate
页面通讯,可以实现页面刷新、组件间传值
- uni.$on(a) 监听
- uni.$emit(a,()={}) 触发
- 在全局定义一个枚举或者变量,然后导入,一边定义一边触发,实现不同页面的通信
export const PageEvent = {
//收货地址
Address:{
ITEM_CLICK:"ITEM_CLICK"
},
//订单页
TorderList:{
REFRESH:"REFRESH"
}
}
小知识点
- uview中的时间转化 uni.$u.date('1585926095536', 'yyyy-mm')
- v-for的 :key值后渲染不会随着dom移动
- uniapp 分享 全局配置分享页
- 将原来的数据转化为数组,用,分割
a = b.split(',')
让子元素位于父元素水平垂直居中
<view style="height: 400rpx; display: flex;justify-content: center;align-items: center">
<view style=" height: 300rpx;width: 300rpx;border-radius: 50%;background-color: #007aff"></view>
</view>
父组件传值到子组件
//父亲
<view name='张三' age=10></view>
//子
export default{
prop:{
name: {
type: String, // name传入类型必须为字符串
required: true // name设为必传字段
},
age: {
type: Number,
default: 233 // 默认值
}
}
}
flex布局
//将父元素定为flex布局
<div style="dispaly:flex"></div>
- 常用属性
-
flex-diection
属性
- row: 默认值,表示沿水平方向,由左到右。
- row-reverse :表示沿水平方向,由右到左
- column:表示垂直方向,由上到下
- column-reverse:表示垂直方向,由下到上
-
flex-wrap
属性
- nowrap:表示不换行
- wrap:正常换行,第一个位于第一行的第一个
- wrap-reverse:向上换行,第一行位于下方
-
flew-flow
属性
- flex-flow属性是flex-deriction和flex-wrap属性的简写,默认值为[row nowrap]
- 第一个属性值为flex-direction的属性值
- 第二个属性值为flex-wrap的属性值
-
justify-content
属性
- flex-start:默认值,左对齐
- flex-end:右对齐
- center:居中对齐
- space-between:两端对齐
- space-around:每个项目两侧的间距相等
-
align-items
属性
- flex-start:交叉轴的起点对齐
- flex-end 交叉轴的终点对齐
- center 交叉轴居中对齐
- baseline 项目的第一行文字的基线对齐
- stretch:默认值:如果项目未设置高度或者高度为auto,将占满整个容器的高度
-
align-content
属性
- align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
- flex-start:与交叉轴的起点对齐。
- flex-end:与交叉轴的终点对齐。
- center:与交叉轴的中点对齐。
- space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
- space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
- stretch(默认值):轴线占满整个交叉轴。
- 其他属性
-
order 属性 -order属性设置项目排序的位置,默认值为0,数值越小越靠前
-
flex-grow 属性
- 默认值为0,表示即使容器有剩余空间也不放大显示。
- 如果设置为1,则平均分摊后放大显示。
-
flex-shrink
- flex-shrink属性表示元素的缩小比例。默认值为1.如果空间不够用时所有的项目同比缩小。如果一个项目的该属性设置为0,则空间不足时该项目也不缩小。
-
lex-basis属性
- flex-basis属性表示表示项目占据主轴空间的值。默认为auto,表示项目当前默认的大小。如果设置为一个固定的值,则该项目在容器中占据固定的大小。
-
flex属性(常用) flex属性是 flex-grow属性、flex-shrink属性、flex-basis属性的简写。默认值为:0 1 auto;
-
align-self 属性
- flex-start:顶端对齐
- flex-end:底部对齐
- center:竖直方向上居中对齐
- baseline:item第一行文字的底部对齐
- stretch:当item未设置高度时,item将和容器等高对齐
flex 均匀分布
父元素 display: flex; justify-content: space-around;
加阴影
box-shadow:5px 5px 10px gray;
前两个是 左右 、 垂直 偏移量
第三个是阴影模糊距离
第四个是阴影颜色
盒子颜色渐变
background:linear-gradient(to right,#fff,#000)
放一个全部变量
在pageEvent emit监听 on触发 uni.on(a,add)
触发事件和onshow
A页面传数据到B B返回A没有参数变化 就不用监听 B返回A有参数变化 就需要监听
用 function命名函数后得到一个新的对象
但是用()=> 后 ,能够调用之前的this.data 数据
字符串拼接
<u-cell-group><u-cell v-for="item in pager.records"
:title="item.remarks"
:value="(item.value)/100 +'分'"
:label="`${$u.timeFormat(item.creatTime, 'yyyy-mm-dd')} 订单号:${item.torderId}`">
</u-cell></u-cell-group>
路由守卫
const LoginPath = [
"/pages/login/login/login",
"/pages/login/login/chooseStore",
]
router.beforeEach(to,from,next)=>{
const loginUser = store.getters.getUserInfo;
<!-- 判断路径是否要登录 -->
if(!LoginPath.includes(to.path)){
<!-- 判断用户没有登录 -->
if ( !loginUser.merchantStoreInfo?.merchantStoreId) {
console.log(to);
//跳转至登录页
const loginRouter = PageEnum.login.router({
to: to.fullPath,
toType: toUViewPathType(to),
});
//跳到下一页
next({
path: loginRouter.url,
query: {
...loginRouter.params
}
})
return;
}
}
}
在main.js中
import {initRouter,router,RouterMount} from "./router/router";
Vue.use(router)
// #ifdef H5
RouterMount(app,router,'#app')
// #endif
在系统终端开启模拟器
adb version adb kill-server adb start-server adb connect 127.0.0.1:7555 最后测试Hbuilder能否连接手机模拟器 点击运行到Android App基座
关于uniapp中navigateTo跳转不生效问题
首先检查要跳转的页面是否为tabBar页面 tabBar页面为pages.json中"tabBar"中配置的页面,如果是则应该使用uni.switchTab跳转。 而不应该用uni.navgeteTo