Skip to content

移动端适配方案

1、概念

  • 物理像素(dp)

    是显示设备中最小的物理部件,一旦设备出厂后,就不会发生改变。

  • 分辨率

    是指屏幕纵横方向上的像素点,单位 px

  • 设备独立像素(dip)

    比如在 iphone 4 中,物理像素比较大,但是在表示的时候会用 2*2 个像素点去表示 1 个像素点。

    在不对网页进行缩放的时候,一个设备独立像素 = 1 个 css 像素

  • 设备像素比(dpr)

    dpr = dp / dip

2、设计稿

一般情况下 UI 设计师是以 iPhone 6 (iPhone se)的大小为原型进行设计,大小为 750*1334

3、比例缩放

前端应该使用哪些单位?px、%、em、rem、vm / vh

vm / vh

视窗单位,vm 是指将屏幕宽度分为100份,1 vw 就表示 1 % 的宽度;1vh 就表示 1 % 的屏幕高度。

会存在兼容问题,所以很多时候不是最佳方案。

rem

相对于根标签的字体大小,根标签是 html 。

换句话讲,如果根标签的大小发生改变,那么所有使用 rem 单位的大小都会发生改变。

所以有一种方案,大小单位全部使用 rem ,然后根据当前设备动态修改 html 标签字体大小。

4、lib-flexible(手淘网的过渡方案)

实现的大致思路

  • 第一步、动态设置 viewport 的缩放。

  • 第二步、动态计算 html 的大小:默认情况下会把屏幕分为10份。

  • 第三步、布局的时候,根据设计稿的尺寸比例,映射到代码中来。

    例如:设计稿中某个元素的宽度为 300 像素,总宽度是 750 像素

    此时 html.fontSize = ‘75px’; 所以每一份的实际大小就是 75 px。

    在代码中该元素的大小就应该为 = 10rem * 设计稿300像素 / 750像素

每次给元素设置大小都要计算,效率非常低,所以可以引入 postcss-pxtorem 该插件自动帮助我们进行计算。

该方案在 vue 项目中实现步骤:

1)、安装模块

bash
npm i amfe-flexible -S 
npm i postcss-pxtorem -D

2)、根目录下修改 .postcssrc.js 或者 postcss.config.js

js
module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue: 75,  // 根据设计稿除以10
      unitPrecision: 5,  // px 转为 rem后需要保留的小数
      propList: ['*'],  // 允许哪些属性转换
      selectorBlackList: [],  // 不会被转换的 class 选择器
      replace: true,
      mediaQuery: false,  // 是否允许在媒体查询中使用
      minPixelValue: 1,  // 小于1个像素就不会被转换
      exclude: /node_modules/i  // 排除哪些目录
    }
  }
}

// 在 main.js 中引入 amfe-flexible
import 'amfe-flexible'

// 完成环境创建后,在代码中就不需要计算元素打消了,直接设计稿中标注是多大的,代码中就写多少

微信开放文档

小程序开发

1、移动端开发方案

  • Native App(原生 APP)

    IOS、Android

  • H5 App(移动端网页)

  • Hybrid App(混合开发)

    ionic、mui、weex、react-native(rn)、Flutter、小程序

2、小程序的理解

不需要下载安装就可以使用的 app ,几乎拥有与原生 app 同样的能力,而且还能做到体积非常小。

3、如何开发小程序

注册账号:一个账号只能绑定一个小程序

小程序后台

创建小程序开发环境

4、小程序数据绑定语法

基本上与 vue 语法相同,只是名字变了。

1)、语法绑定 - 属性和标签之间

html
{{}}

2)、条件渲染

html
wx:if
wx:elif
wx:else

3)、列表渲染

html
wx:for

<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>

// 对数组中的下标变量和数组元素变量重命名
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
</view>

// key 值
<switch wx:for="{{objectArray}}" wx:key="*this" style="display: block;"> {{item.id}} </switch>

wxss 文件

1、文件后缀

.wxss

2、全局 css

根目录下的 app.wxss

3、与 css 的区别

  • wxss 具有大部分的 css 特性,但是也做一些修改和扩展

  • 支持样式导入,@import ‘xx.wxss’;

  • 仅支持部分 css 选择器(class、id、element、分组选择器、before、after)

  • 在 wxss 中不能使用本地图片(即使用网络图)

  • 新增加一个单位 rpx

    默认情况下屏幕总宽度为 750rpx ,即按照 iphone6 手机大小设计。

app.js

1、理解

小程序的入口文件

2、作用

  • 可以设置全局数据
  • 可以挂载全局方法
  • 应用生命周期

3、应用级生命周期

打开小程序后会自动触发的一系列函数。

js
// 小程序初始化完成,全局触发1次
onLaunch(){}

// 小程序启动或者从后台进入前台就会触发
onShow(){}

// 小程序退到后台
onHide(){}

// 小程序发生脚本错误时会调用
onError(){}

// 打开不存在页面
onPageNotFound(){}

4、APP 函数

该文件必须调用 App(options)

所有的生命周期都是挂载在 options 对象中,除此之外,可以在该对象中挂载任意其他方法或者性能。

一般情况下全局数据挂载到 globalData 属性中。

5、获取 App 对象

其他任意页面调用以下方法,可以获取 app 对象,然后访问 app.js 中的方法和数据。

js
const app = getApp()

app.json

1、理解

小程序的全局设置、包括小程序的应用名字、外观、页面组成、底部导航、分包处理。

2、pages 字段

所有小程序的页面必须在这里注册。

  • 一个个去新建

  • 右击新建文件夹 - 新建 Page

  • app.js 中的 pages 添加 "pages/me/me"

    js
    "pages":[
      "pages/index/index",
      "pages/logs/logs",
      "pages/me/me"
    ]

3、window

小程序窗口表现设置。

js
"window":{
  "backgroundTextStyle": "light",  // 下拉 loading 的样式,仅支持 dark / light
  "navigationBarBackgroundColor": "#e9d7df",  // 导航栏背景颜色
  "navigationBarTitleText": "呆呆小程序",  // 导航栏标题文字内容
  "navigationBarTextStyle":"black",  // 导航栏标题文字内容
  "navigationStyle": "custom",  // 导航栏样式,default:默认样式,custom:自定义导航栏
  "enablePullDownRefresh": true  // 是否开启全局的下拉刷新
}

4、tabBar

底部导航设置。

js
"tabBar": {
  "color": "#000",
  "selectedColor": "#ff0000",
  "list": [
    {
      "pagePath": "pages/index/index",  // 页面路径
      "text": "首页",  // tab 上按钮文字
      "iconPath": "images/tabBar/home.png",  // 图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片
      "selectedIconPath": "images/tabBar/home_checked.png"  // 选中时的图片路径
    },
    {
      "pagePath": "pages/car/car",
      "text": "购物车",
      "iconPath": "images/tabBar/car.png",
      "selectedIconPath": "images/tabBar/car_checked.png"
    }
  ]
}

页面

1、page.js

1)、理解

当前页面的逻辑处理。

2)、Page(options)

每个 page.js 必须调用该方法,接受一个对象作为参数,该对象中设置页面数据,页面生命周期,页面的其他方法。

3)、data

页面数据,只提供给当前页面使用。

在页面生命周期和页面方法中通过 this.data 来进行访问。

4)、页面生命周期

在应用生命周期之后,访问每个页面时会触发的一系列方法。

js
>> 监听页面加载,只执行一次
onLoad() {}

>> 监听页面初次渲染完成
onReady() {}

>> 监听页面显示
onShow() {}

>> 监听页面隐藏
onHide() {}

>> 监听页面卸载
onUnload() {}

5)、页面相关事件处理函数

js
>> 监听用户下拉动作
onPullDownRefresh() {}

>> 页面上拉触底事件的处理函数
onReachBottom() {}

>> 用户点击右上角分享
onShareAppMessage() {}

2、page.wxss

当前页面的css。

3、page.json

当前页面的配置,该配置可以覆盖全局下window相同字段。

4、page.wxml

用于编写标签结构的页面,但是不支持浏览器的标签的,即 div, p, span 等等不支持的。

view 相当于 div,用 text 相当于 span。

html
// 引入图片
<image src="" mode="aspectFill"></image>
注:图片不能用中文命名,否则手机预览不到

事件绑定

1、事件类型

tap:触摸

longpress:长按

touchstart:手指触摸动作开始

touchmove:手指触摸后移动

touchend:手指触摸动作结束

input 等表单事件

2、添加事件的绑定

bind 开头,后面接上事件类型

html
<button bindtap="foo">添加事件</button>

catch 开头,后面跟上事件类型,可以阻止事件冒泡

3、传参

当触发事件处理函数时,如何给该函数传参?

js
// 定义data-
<button bindtap="add" data-idn="123">参数传递</button>

add(e){
  e.target.dataset.idn
}

修改data

1、setData

在小程序中修改数据,必须调用该方法修改。

js
data: {
  username: 'admin',
  num: 0,
  role: {
    name: 'admin',
    pages: ['权限']
  },
}

this.setData({
  num: this.data.num - 1
})

// 修改数组或者对象
this.setData({
  role: {  // 对象名
    ...this.role,
    name: 'superAdmin'
  }
})

// 所以可以直接修改其中一个子字段即可,而不需要重新替换
this.setData({
  'role.name': 'superAdmin'
})

this.setData({
  'role[0].name': 'superAdmin'
})

2、input 的值的绑定

js
<input type="text" value="{{username}}" bindinput="changeUsername" />

changeUsername(e) {
  // e.detail.value 可以获取绑定的表单元素的值
  this.setData({
    username: e.detail.value
  })
}

// 双向绑定
<input type="text" model:value="{{username}}" />

注意:这种写法只能绑定到单一的字段,不能帮到对象下某一个属性的。

小程序路由

1、组件类型

html
<navigator url="" open-type="">跳转到新页面</navigator>

open-type:
  * navigator:普通页面的跳转,跳转时当前页面不会销毁,页面栈只能存在10层
  * redirect:重定向,跳转时,当前页面会被销毁
  * switchTab:用于切换 tabBar,会销毁其他页面
	* navigateBack:返回

2、路由 API

js
wx.navigateTo()
wx.redirectTo()
wx.switchTab()
wx.navigateBack()

button 组件

html
<button bindtap="showloading">加载中</button>
<button open-type="contact">客服</button>
<button open-type="share">转发</button>
<button open-type="feedback">反馈</button>

初始化云开发

第一步、创建云开发的项目

第二步、开通云环境

第三步、代码配置

js
>> 云函数、小程序代码目录设置
  // 在 project.config.json 中配置云函数和小程序代码目录
  {
    "miniprogram/",
    "cloudfunctionRoot": "cloudfunctions/",
  }

>> 小程序的 app.js 进行云环境的初始化
  wx.cloud.init({
    // env: 'cloud1',  // 添加当前云开发环境名称
    traceUser: true,
  });

>> 云函数中也必须进行云初始化
  const cloud = require('wx-server-sdk');

  cloud.init({
    env: cloud.DYNAMIC_CURRENT_ENV  // 使用当前云环境
  });

云函数

1、概念

是指在云端运行的代码,该代码是 nodeJS 的写法。

2、云函数的创建

  • 第一步、确认云函数环境,在云函数目录上点击右键 - 当前环境 - 选择

  • 第二步、在云函数目录上点击右键 - 新建云函数

  • 第三步、将本地的云函数上传至云端 - 右键 - 上传并部署-云端安装依赖

  • 第四步、小程序端就可以调用云函数了。

3、云函数天然鉴权

云函数可以获取每一个用户的识别码。

  • openid:当前小程序中用户唯一识别码。
  • unionid:将公众号、小程序中同一个微信用户进行识别,只有条件符合后的小程序或者公众号才能获取。
js
const wxContext = cloud.getWXContext();

4、小程序调用云函数(类似请求)

js
// 写法1 - 回调:
wx.cloud.callFunction() {
  name: '云函数名字',
  data: {  // 传递给云函数的参数
	  msg: 'Hi'
	},
  success(res) {},  // 成功
  fail(err) {},  // 失败
  complete() {}  // 无论成功与否
}

// 写法2 - promise:
wx.cloud.callFunction() {
  name: '云函数名字',
  data: {  // 传递给云函数的参数
	  msg: 'Hi'
	},
}
.then()
.catch()

5、如何在云函数中处理多个小程序发送的请求

js
wx.cloud.callFunction({
  name: '云函数名字',
  data: {  // 传递给云函数的参数
    type: '',  // 标识
    msg: 'Hi'
  }
})

云数据库

1、概念

在云端的一个非关系型数据库。

2、数据库类型

  • 关系型数据库

    mysql

  • 非关系型数据库

    redis、mongodb 等(云数据库基于mongodb封装,类似 JSON 结构)。

3、云数据库结构

  • 数据库 - database
  • 集合 - collection(可以与 table 作比较)
  • 记录 record / doc
  • 字段 field

4、数据库数据类型

JS 数据类型(string、number、boolean、null、array、object、date)、geopoint

5、数据创建

  • 直接单条数据创建

  • 导入数据(json 文件)

    JSON 数据,每条数据之间不需要逗号隔开

  • 模板插入

  • 由代码生成

6、云数据库环境的初始化

js
const cloud = require('wx-server-sdk');

cloud.init()

const db = cloud.database();

7、数据库的操作

js
>> 云函数端
  db.collection(集合名)

>> 小程序端(允许小程序直接操作数据库)
  const db = wx.cloud.database();
  db.collection(集合名)

*注意:
  小程序端直接新增数据,会自动加上 openid,而云函数没有。

8、云数据库语法

1)、增

js
db.collection(集合名).add({
  data: {},
  success(){},
  fail() {}
})

db.collection(集合名).add({
  data: {}
})
.then()
.catch()

2)、删

js
db.collection(集合名).doc(_id).remove()

3)、改

js
db.collection(集合名).doc(_id).update({
  data: {
    // 要修改的字段
  }
})

4)、查

js
// 小程序端直接查询最多返回20条数据,云函数最多返回100条数据。
// 基本语法
db.collection(集合名).get()

// 根据条件进行查询
db.collection(集合名).where({
  // 字段名
}).get()

// 投影字段
db.collection('w304_users')
  .where({
  //...
})
  .field({
  // 默认返回 _id
  username: true,  // 为true该字段就会返回
  // pass: true,
})
  .get()

// 其他 - 排序、跳过、限制
db.collection('w304_users')
  .where({
  // 字段名
})
  .field({
  name: true,
  price: true,
})
  .orderBy('price', 'desc')
  .skip(1)
  .limit(10)
  .get()

小程序 - this 问题

js
Page({
  saiHi() {
    wx.showToast({
      title: '',
      success() {
        // 回调函数:不可以正常使用 this
        that.setData({})
      }
    })
    
    // 方法1:
    const that = this  // 缓存
    wx.showToast({
      title: '',
      success() {
        that.setData({})
      }
    })
    
    // 方法2 - 箭头函数
    wx.showToast({
      title: '',
      success: () => {
        this.setData({})
      }
    })
    
    // 方法3 - 显示绑定
    wx.showToast({
      title: '',
      success() {
        that.setData({})
      }.bind(this)
    })
  }
})

welcome to zhudaidai's blog!