一、css动画
1.动画原理及2D变换
transform: 变换,用于描述物体的位置旋转缩放
①translate: 平移
????????第一个参数 水平平移量 右为正方向
????????第二个参数 竖直平移量 下为正方向
② rotate 旋转?
???????? 参数:可以是角度值 (deg) 也可以是弧度值 (rad) 弧度制的PI = 180°?
????????沿轴进行顺时针旋转为正方向,0°代表竖直向上?
③scale 缩放
????????参数:比率 1 为原本大小
④skew 倾斜?
⑤设置transform的原点
????????原点的位置会影响旋转的圆心,缩放的位置?
/* 谷歌浏览器可以识别该属性 */
-webkit-transform: translate(100px, 120px);
/* 火狐浏览器可以识别该属性 */
-moz-transform: translate(100px, 120px);
/* 市面上现在流行使用postCss来解决css样式兼容性问题 */
2.过渡动画
/* 定义初始状态 */
transform: translateX(0px);
/* transition: all 1s ease-in; */
/* 播放过度动画至少包含 transition-property transition-duration */
/* 指定css属性能够产生过度动画 */
transition-property: left, transform;
/* transition-property 还有两个待选项
none: 无
all: 所有属性都能播放过渡动画
*/
transition-property: all;
/* 动画播放的时长 */
transition-duration: 2s;
/* 动画播放的速度曲线 */
/* 待选项
linear: 匀速直线运动
ease-in: 慢进
ease-out: 慢出
ease-in-out: 慢进慢出
cubic-bezier: 曲线函数
*/
transition-timing-function: linear;
/* 动画播放延迟 */
transition-delay: 3s;
/* 合成属性
语法:
transition: property duration timing-function delay;
*/
transition: all 3s linear 3s;
3.3d变换和animation动画
3d变换:
总结:
要使用3d变换需要依序执行以下步骤:
1. 搭建3d场景,在父元素上设置:transform-style: preserve-3d;
.scene {
height: 100vh;
/* 变换样式
perserve-3d 代表将元素变成一个3D空间
*/
transform-style: preserve-3d;
/* 灭点到屏幕的距离 */
/* 若三维场景中不添加 perspective 则三维场景是一个正交视图 */
perspective: 300px;
/* 透视原点(灭点所在的坐标)
原点为 0 值时,所在位置是scene的左上角
*/
/* perspective-origin: center center; */
perspective-origin: 0 0;
}
2. 在父元素上设置透视距离:perspective: 100px;
3. 给场景添加演员,给场景元素添加子元素
4. 在子元素上使用3d变换
animation动画:
.box {
/* 动画属性如下 */
/* 动画animation必须包含 名称和时长两个属性才会进行播放 */
/* animation一下四个属性可以和 tansition一块儿进行记忆 */
/* 动画名称 */
animation-name: move;
/* 动画播放时长 */
animation-duration: 3s;
/* 动画播放的速度曲线 */
animation-timing-function: linear;
/* 动画延迟 */
/* animation-delay: 3s; */
/* 以下属性为 animation 独有的属性 */
/* 动画的迭代次数
infinite 无限次
*/
animation-iteration-count: 1;
/* 动画播放方向
待选项:
normal: 顺向播放
reverse: 反向播放
alternate: 来回播放
alternate-reverse: 反向来回播放
*/
animation-direction: normal;
/* 动画填充模式(动画播放结束后所保留的状态)
forwards: 保留结束帧的状态
backwards: 保留起始帧的状态
both: 保留初始和结束时的状态
*/
animation-fill-mode: both;
/* 可以定义复合属性,取代上面的所有属性 */
/* 赋值顺序,可以参考如下顺序 */
/* duration | timing-function | delay | iteration-count | direction | fill-mode | play-state | name */
/* duration | timing-function | delay | name */
/* duration | name */
/* animation: 2s move;
animation: 2s linear 3s move; */
animation: move 3s linear 2s forwards;
}
/* 动画帧序列 */
@keyframes move {
/* 起始帧 */
from {
/* 每一帧中描述该元素的状态 */
transform: translateX(0px);
opacity: 0;
}
/* 可以用百分比来代表动画的中间状态 */
50% {
transform: translateX(600px);
opacity: 1;
}
/* 结束帧 */
to {
transform: translateX(300px);
}
}
let btn2 = document.querySelector('.btn2')
let box = document.querySelector('.box')
btn2.addEventListener('click', () => {
// animationPlayState 动画播放状态
// paused 暂停
// running 播放
if (box.style.animationPlayState === 'paused') {
box.style.animationPlayState = 'running'
} else {
box.style.animationPlayState = 'paused'
}
})
4.渐变色分栏布局与响应式
.box {
/* 背景的渐变色实际上是设置的 background-image 而不是 background-color */
/* 线性渐变 */
/* 语法: linear-gradient(direction, color1, color2, color3 ... )
direction: 渐变色的朝向 以 to 开头, 或者可以添加角度值; 默认值为 to top
color1 color2 ...: 渐变的颜色序列
*/
background-image: linear-gradient(30deg, #f00, #0f0, #00f);
/* 颜色值后可以添加像素距离,该像素值代表着该颜色所处的位置,该位置颜色将到下一个位置的颜色之间进行渐变 */
background-image: linear-gradient(to right, #f00, #f00 50px, #0f0 50px, #0f0 100px, #00f 200px);
/* 重复线性渐变 */
background-image: repeating-linear-gradient(to right, #f00, #f00 50px, #00f 50px, #00f 100px);
/* 径向渐变 */
background-image: radial-gradient(#f00, orange, #0f0, #ff0, #f0f);
background-image: radial-gradient(#f00, #f00 50px, #00f 50px, #00f 100px, #0f0 100px, #0f0 200px);
/* 重复径向渐变 */
background-image: repeating-radial-gradient(#f00, #f00 50px, #ff0 50px, #ff0 100px);
}
.p {
width: 800px;
height: 500px;
/* 设置文本列数 */
column-count: 3;
/* 设置列宽度 */
column-width: 150px;
/* 分栏边框,属性值和边框的属性值相同 */
column-rule: 5px double red;
/* 两列文本中间的间距 */
column-gap: 100px;
word-break: keep-all;
}
/* 什么是页面的响应式?
页面的元素样式会根据页面的宽度做出变化
*/
/* 为什么要使用页面响应式
为了让同一个页面能够适配不同的设备
*/
/* 如何实现响应式? */
/* 使用媒体查询,来实现响应式布局 */
/* 媒体查询的作用:当媒体查询条件成立时,将应用花括号中代码块的样式 */
/* 语法:@media media-type and (condition1) and (condition2) ... */
/* 媒体类型 media-type:
备选项
all: 所有设备
print:打印机的预览模式
screen:显示屏
speech:语音合成器
*/
/* min-width: 屏幕最小宽度 */
/* max-width: 屏幕最大宽度 */
二、jQuery
jquery 使用的方法:
1. 查询并存储元素
2. 操作元素,包括修改元素样式,绑定事件等
什么是jquery 对象
// 使用jquery $() 函数查询出来的返回值 就是一个jquery 对象
// $box 就是一个jquery 对象
// let $box = $('.box')
获取jquery对象的方法有两种
// 1. 使用 css 选择器
let $li = $('ul>li')
// 2. 使用 dom 对象
// 先查询一个dom对象
let box = document.querySelector('.box')
// 使用dom对象获取一个jquery对象
let $box = $(box)
创建并插入元素
// 创建一个节点,该节点就是一个jquery对象
let $box = $(`<div class="box">new</div>`)
// 某个元素追加一个子节点
// $(document.body).append($box)
// 追加一个子节点到另一个元素中
// $box.appendTo($(document.body))
// 某个元素追加一个节点到头部
// $(document.body).prepend($box)
// 追加一个子节点到另一个元素的头部
// $box.prependTo($(document.body))
let $box2 = $('.box').eq(1)
// 某个元素的前面追加一个元素
// $box2.before($box)
// 某个元素被添加到另一个元素的前面
// $box.insertBefore($box2)
// 某个元素的后面添加一个元素
// $box2.after($box)
// 某个元素被添加到另一个元素的后面
$box.insertAfter($box2)
jquery对象的一些方法
1、eq 读取对应索引位置的jquery对象
let $li = $lis.eq(1)
// 因为 $li 是jquery对象 所以可以直接使用jquery操作它
$li.css('color', '#0f0')
/2、get 读取对应索引位置的dom对象
// let li = $lis.get(2)
// li.style.color = '#f00'
// 使用 [] 方括号的方式去获取索引对应的 dom 对象
// 其结果等价于 get 函数获取的结果
let li = $lis[2]
li.style.color = '#f00'
3、// 添加类
$box.addClass('active')
4、// 判断是否存在某个类名
$box.hasClass('active')
5、// 删除类
$box.removeClass('active')
6、// 读取属性
let clazz = $box.attr('class')
console.log(clazz);
7、// 赋值属性
$box.attr('my-data', 'hello world')
8、// 删除属性
$box.removeAttr('class')
9、// 每一个元素都使用 div 来进行包裹
// $('li').wrap('<div class="fs"></div>')
10、// 所有的 li 元素用一个 div 进行包裹
$('li').wrapAll('<div class="fs"></div>')
11、// index() 查询某个节点在集合中的索引
let index = $('.box').index($('.box:nth-child(3)'))
console.log(index);
12、// find() 查询某个节点的后代节点
let $span = $('.box-list').find('.box>span')
console.log($span);
13、// js api 的查询方法
let boxList = document.querySelector('.box-list')
// 查询boxList的子节点
console.log(boxList.querySelector('.box>span'));
14、// closest 查询最近的父节点
console.log($span.closest('.box-list'));
jquery对象绑定事件
// 和dom对象绑定事件进行类比
// dom 对象有两种绑定事件的方法
// 1. 使用 事件属性 例如: onclick onmousemove
// 对应 jquery 的写法如下
$btn.click(ev => {
console.log('click');
// ev 是jquery封装的事件对象
console.log(ev);
})
// 再例如
$btn.mousemove(ev => {
console.log('mousemove');
})
// 可以直接使用事件对应的函数去触发事件,例如:
$btn.click()
$btn.mousemove()
// 2. 使用事件监听器
// $btn[0].addEventListener('click', ev=>{})
// 对应的jquery写法:
const handler = ev => {
console.log(ev);
console.log(1);
}
// 绑定事件
$btn.on('click', handler)
$btn.on('click', ev => {
console.log(ev);
console.log(2);
})
// 绑定一次性事件
$btn.one('click', ev => {
console.log(ev);
console.log('one');
})
// 解绑指定事件处理程序
// $btn.off('click', handler)
// 解绑所有事件处理程序
$btn.off('click')
三、canvas画布
使用canvas的步骤
? ? 1. 创建canvas标签
? ? 2. 给canvas标签设置 width height 属性
? ? 3. 通过js 获取canvas标签
? ? 4. 通过canvas标签获取context画布上下文(画布对象)
? ? 5. 通过context绘制画布
1、// 绘制实心矩形(rectangle)
// ctx.fillRect(x, y, w, h)
// x: 水平坐标
// y: 竖直坐标
// 坐标原点在canvas左上角
// w: 宽度
// h: 高度
2、// 镂空矩形
// 参数和实心矩形相同
// ctx.strokeRect(x, y, w, h)
3、// 清空矩形, 用于清空画布
ctx.clearRect(0, 0, 800, 600)
4、// 绘制实心文字
// 语法:ctx.fillText(text, x, y, max-width)
// text: 要渲染的文本
// x,y: 文本渲染的坐标位置
// max-width: 文本最大宽度,当大于该宽度,文本字体将自动缩小以自适应宽度
// ctx.fillText('祖国万岁!!', 200, 100, 100)
5、// 镂空文字
// 参数和实心文本相同
ctx.strokeText('祖国万岁!!', 200, 300)
6、// 设置颜色和线宽
ctx.strokeStyle = '#ff0'
ctx.lineWidth = 15
// 画线分两个步骤:
// 1. 描点(设置路径)
// 2. 画线(将所描的点连接起来)
// 步骤一
// 使用 beginPath 开启路径
ctx.beginPath()
// 移动笔头但不会记录路径上的线条
ctx.moveTo(400, 100)
// 用线绘制到下一个点
ctx.lineTo(200, 200)
ctx.lineTo(600, 200)
ctx.lineTo(400, 100)
// 将路径封闭
ctx.closePath()
// 注意:beginPath在画新的路径的时候必须调用,closePath选择性调用
// 步骤二
// 为了显示图形需要调用以下函数
// 将路径所包围的图形用纯色来填充
// ctx.fill()
// 将路径用镂空线条进行绘制
ctx.stroke()
ctx.strokeStyle = '#f00'
ctx.beginPath()
ctx.moveTo(400, 400)
ctx.lineTo(500, 400)
// 角度转弧度的公式: rad = (PI / 180) * deg
// 弧线
// ctx.arc(x, y, r, start, end)
// x: 圆心横坐标
// y: 圆心纵坐标
// r: 圆半径
// start: 起始弧度 0度时的方向为水平向右 顺时针为正方向
// end: 结束弧度
ctx.arc(400, 400, 100, 0, Math.PI / 180 * 30)
ctx.closePath()
ctx.fill()
// ctx.stroke()
7、//绘制图片
// 语法:
// ctx.drawImage(image, dx, dy);
// ctx.drawImage(image, dx, dy, dWidth, dHeight);
// ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
// image: img 标签的 dom 对象
// dx dy: 图片在canvas中的坐标
// dWidth dHeight: 图片在canvas中的宽高
// sx, sy: 参考图片源,截图的坐标
// sWidth, sHeight: 截图的宽高
四、多媒体标签、swiper和animate.css
1、多媒体标签
属性:
????????width 标签宽度
? ? ? ? height 标签高度
? ? ? ? controls 控制面板
? ? ? ? muted 静音
? ? ? ? autoplay 自动播放
? ? ? ? src 媒体源
? ? ? ? preload 预载模式
? ? ? ? loop 循环
? ? ? ? poster 海报
<body>
<!-- <video height="300" src="./video/oceans.mp4" controls muted loop poster="./img/desktop.png"></video> -->
<!-- 使用自动播放+静音,能实现自动播放的效果 -->
<!-- <video height="300" src="./video/oceans.mp4" controls autoplay muted></video> -->
<!-- https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/audio -->
<!-- 音频播放器 -->
<!-- 由于audio和video都属于HTMLMediaElement的实例
所以audio的所有使用方法和video一样
可以通过 instanceof 来判断一个对象是否是某个类型的实例
video instanceof HTMLMediaElement
-->
<!-- <audio src="./audio/moon.mp3" controls loop></audio> -->
<!-- source 标签若有多个,那么浏览器会从上至下加载直到某一个被加载成功为止 -->
<audio controls>
<!-- 数据源标签 -->
<source src="./audio/a44.mp3">
<source src="./audio/b44.mp3">
<source src="./audio/c4.mp3">
</audio>
<video height="300" src="./video/oceans.mp4"></video>
<!-- 自定义控制器 -->
<div>
<button class="play">播放</button>
<button class="pause">暂停</button>
当前时间:<span class="current-time"></span>
总时间:<span class="total-time"></span>
<input class="inp" /><button class="go-to">跳转到此时间</button>
<button class="v-up">音量+</button>
<button class="v-down">音量-</button>
<button class="muted">静音</button>
</div>
<!-- 可以通过以下网站自定义滑块样式
http://danielstern.ca/range.css/?ref=css-tricks#/
-->
<input type="range" min="0" max="100" step="20" value="0"><span class="range-value">0</span>
<br />
<!-- picture -->
<picture>
<!-- source 标签中有多个待选项时,使用srcset规定资源路径 -->
<!-- media 设置媒体查询 -->
<!-- 媒体查询的顺序由大到小 -->
<source srcset="./img/1.png" media="(min-width: 800px)">
<source srcset="./img/2.png" media="(min-width: 600px)">
<img width="500" src="./img/desktop.png">
</picture>
</body>
<script>
let inputRange = document.querySelector('input[type=range]')
let rangeValue = document.querySelector('.range-value')
inputRange.addEventListener('input', () => {
rangeValue.textContent = inputRange.value
})
// 可以使用 Audio 类名来创建 audio 标签
// let audio = new Audio()
// audio.src = './audio/a4.mp3'
// audio.play()
let video = document.querySelector('video')
let playBtn = document.querySelector('.play')
let pauseBtn = document.querySelector('.pause')
let totalTime = document.querySelector('.total-time')
let currentTime = document.querySelector('.current-time')
let inp = document.querySelector('.inp')
let goToBtn = document.querySelector('.go-to')
let vUpBtn = document.querySelector('.v-up')
let vDownBtn = document.querySelector('.v-down')
let mutedBtn = document.querySelector('.muted')
let timer
// 播放
playBtn.addEventListener('click', () => {
video.play()
// 显示总时长
// textContent 标签体的文本内容
// duration 代表媒体时长,单位: 秒
totalTime.textContent = video.duration
currentTime.textContent = video.currentTime
clearInterval(timer)
timer = setInterval(() => {
// currentTime 代表当前播放的时间
currentTime.textContent = video.currentTime
}, 1000)
})
// 暂停
pauseBtn.addEventListener('click', () => {
video.pause()
})
// 跳转进度
goToBtn.addEventListener('click', () => {
let currentTime = Number(inp.value)
// 直接赋值 video 的 currentTime 就可以跳转进度
video.currentTime = currentTime
})
// 音量+
vUpBtn.addEventListener('click', () => {
// volume 是一个 0~1 的数字 用于控制音量
video.volume = video.volume + 0.1 > 1 ? 1 : video.volume + 0.1
})
// 音量-
vDownBtn.addEventListener('click', () => {
// volume 是一个 0~1 的数字 用于控制音量
video.volume = video.volume - 0.1 < 0 ? 0 : video.volume - 0.1
})
// 静音
mutedBtn.addEventListener('click', () => {
video.muted = !video.muted
})
</script>
2、animate.css
<!-- 动画必须添加 animate__animated
其次添加动画名称所代表的类名
-->
<!-- <h1 class="animate__animated animate__bounceInDown">hello world</h1> -->
<!-- 辅助类 -->
<!-- 延迟 -->
<!-- <h1 class="animate__animated animate__bounceInDown animate__delay-2s">hello world</h1> -->
<!-- 播放速度
animate__slow 2s
animate__slower 3s
animate__fast 800ms
animate__faster 500ms
-->
<!-- <h1 class="animate__animated animate__bounceInDown animate__slower">hello world</h1> -->
<!-- 动画播放次数
animate__repeat-1 1
animate__repeat-2 2
animate__repeat-3 3
animate__infinite infinite
-->
<!-- <h1 class="animate__animated animate__bounceInDown animate__infinite">hello world</h1> -->
<!-- 动态添加动画 -->
<!-- <h1>hello world</h1>
<button class="play">播放</button> -->
<!-- 动画的叠加
只需要添加多级元素来播放不同的动画即可
-->
<!-- <div class="animate__animated animate__fadeInUpBig">
<h1 class="animate__animated animate__bounceInRight">hello world</h1>
</div> -->
<!-- 自定义动画
由于animate.css本质上是使用的 animation 样式播放的动画,所以可以手动强制修改 animation相关样式,来实现自定义
-->
<h1 class="animate__animated animate__bounce">hello world</h1>
3.swiper.js:是个专门用于播放滚动动画的工具
官网地址:<https://swiperjs.com/>
参考地址:<https://www.swiper.com.cn/>
安装方式:
????????1、cdn:从 <https://swiperjs.com/get-started#use-swiper-from-cdn> 找到 `cdn` 地址并引入即可
? ? ? ? 2、npm or yarn:在终端窗口中,通过两句命令 npm init -y?和 npm i swiper
五、微信小程序
1.微信小程序基础
①项目下的文件和文件夹的作用如下:
components: 小程序的自定义组件
images: 图片文件夹
pages: 存放页面文件的文件夹
? ? index: 页面文件夹
? ? ? ? index.js: 页面的js代码
? ? ? ? index.json: 页面的配置
? ? ? ? index.wxml: html模板文件
? ? ? ? index.wxss: 页面的样式文件
app.js: 微信小程序的程序入口(程序入口:开始执行代码的地方)
app.json: 小程序应用程序的全局配置文件
app.wxss: 小程序的全局样式(.wxss文件是小程序的样式文件)
envList.js: 小程序云环境列表
project.config.json: 小程序项目的配置
sitemap.json: 小程序路由配置
②常用标签
<!-- page 标签相当于 html 中的 body -->
<page></page>
<!-- view 标签相当于 html 中的 div -->
<view></view>
<!-- text 相当于 html 中的 span -->
<text></text>
<!-- image 相当于 html 中的 img -->
<image></image>
<!-- block 是一个自身不会显示的标签 -->
<block></block>
③单位rem和rpx
rem 是 html 中的长度单位,代表相对根节点(html)上字体的大小
rpx 是 微信wxml中的长度单位,iphone5 机器上1个像素长度等于1rpx
④模板语法
# 模板语法
参考:https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/
模板语法是微信规定的一套书写wxml的语法
## 插值
作用:用于将变量值插入页面
语法:
```wxml
<!-- name 变量,定义在 js 文件的 data 中 -->
{{name}}
```
> 注意:插值运算的花括号中{{}},填写的内容其实是js表达式
## 循环渲染
作用:可以将数组数据循环显示到页面中
语法:
```wxml
<!-- wx: 开头的写在标签头部的东西 称为指令 -->
<!-- array: 来自js data中的数组 -->
<!-- 使用 wx:for 一定要加上 wx:key,wx:key的值是array对象中的不可重复的属性 -->
<view wx:for="{{array}}" wx:key="id">
<!-- index: 是 wx:for 中隐式声明的变量,代表循环遍历array时的当前索引 -->
<!-- item: 是 wx:for 中隐式声明的变量,代表循环遍历array时的当前数组成员 -->
{{index}}: {{item}}
</view>
```
## 条件渲染
可以根据条件判断,选择性的渲染页面
语法:
```wxml
<view wx:for="{{table}}" wx:key="name">
<text>{{index}}: 姓名 = {{item.name}}; 年龄 = {{item.age}}; 性别 = </text>
<!-- wx:if 指令的值为布尔表达式,为true是渲染该节点,否则不渲染 -->
<text wx:if="{{item.sex==='male'}}">男</text>
<!-- wx:if 可以和 wx:elif、wx:else 连用 -->
<text wx:elif="{{item.sex==='female'}}">女</text>
<text wx:else>其他</text>
</view>
```
2.小程序应用开发
①阿里iconfont的使用
阿里iconfont是阿里的矢量图库,图库提供各式各样的图标。
矢量图描述了绘图时所使用的坐标点,在等比例缩放图片时,图片不会变模糊。
## 图库使用流程
网址:<https://www.iconfont.cn/>
安装流程:
1. 选择图标,加入自己的项目
2. 下载自己项目
3. 解压下载的zip文件
4. 引入解压文件中的 iconfont.css 文件
使用方法:
1. 使用 span 标签,给标签 class 加入 iconfont
2. 在自己的项目中选择一个图标的 class
3. 在 span 标签中加入所选 class 即可
> 注意:iconfont图标被当作字符使用,所以调节大小时,使用 font-size 属性
## 在微信小程序中使用iconfont
1. 在 iconfont 网站的项目中点击 `项目设置` 设置字体类型为 `Base64` 然后下载项目
2. 将 iconfont.css 改名为 iconfont.wxss
3. 将 iconfont.wxss 放入小程序项目目录下
4. 在小程序的 app.wxss 第一行代码加入 @import '...' (此处是iconfont.wxss文件路径)
安装好后其余使用方法和 html 中的方法一样
②页面底部选项卡
在 app.json 中 增加 tabBar 配置就能添加选项卡
```json
{
"tabBar": {
"selectedColor": "#444", // 选中的按钮的文本颜色
"list": [ // 按钮列表
{
"pagePath": "pages/read/read", // 跳转的页面路径
"text": "领读", // 按钮的文字描述
"iconPath": "image/tab_icon1.png", // 未选中时的图标路径
"selectedIconPath": "image/tab_icon1_active.png" // 选中时的图标路径
}
]
},
}
```
注意:要显示选项卡,按钮列表中,必须要有一个配置的 pagePath 属性值,是小程序的入口页面
注意:底部选项卡指定的页面不能是分包里的页面
自定义底部选项卡图标
可以在阿里适量图库下载需要的图标(一般来说是一个镂空图标和一个填充图标)
将下载后的图片复制到小程序项目目录下,然后再tabBar配置选项中配置即可
③导航与页面间传参
导航:引导页面跳转到指定位置
导航方法有两种:1. 页面标签进行导航,类似 html 中的 a 标签;2. 使用js进行导航,类似于 location.href
## 使用 navigator 标签
文档:https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html
语法:
```html
<!-- url:要跳转到的页面路径 -->
<!-- 若要传递参数,可以在url后面增加 ?key=value 的参数 -->
<navigator url="path"></navigator>
```
## 使用 wx.navigateTo 函数
文档:https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html
语法:
```js
function(){
wx.navigateTo({
// path: 要跳转的路径
// key=value: 要传递的参数
url: 'path?key=value'
})
}
// wx.navigateTo 跳转到某页 会新增堆栈
// wx.redirectTo 重定向到某页 不会新增堆栈
// wx.navigateBack 返回
```
> 参数的获取可以在另一个页面的 onLoad 声明周期函数中 options 变量中存放着参数
④获取页面元素
## 方法:
步骤如下:
获取查询器:
let query = wx.createSelectorQuery()
使用查询器 查找节点
query.select(selector) 或者 query.selectAll(selector)
let nodeRef = query.select(selector) // nodeRef 大致可以理解为是页面元素
获取元素属性:
```js
// fields 接收两个参数,
// 第一个参数:查询属性的配置
// 第二个参数:查询结束的回调
nodeRef.fields({
dataset: true, // 自定义属性,也就是标签上 data- 开头的属性
size: true, // 元素的宽高
rect: true, // 元素的位置 top left right bottom
properties: ['url'], // 元素的固有属性,不能查询 id class style 属性和绑定的事件属性
computedStyle: ['backgroundColor', 'fontSize'] // 查询样式
}, (res)=>{
// 该 res 就是查询的结果
console.log(res)
})
```
当调用完 fields 后 ,一定要执行 exec,例如:
```js
query.exec()
```
## 查询组件
小程序组件类似html标签,可以使用css选择器进行查询
```js
// this 是当前页面对象模型
// 通过 this.selectComponent 查询当前页中对应css选择器的组件
const checkbox = this.selectComponent('.checkbox')
```
⑤自定义属性data-
和 html 一样,微信小程序的标签上也能自定属性,但是必须是以 data- 开头的属性,例如:
<!-- 此处的data-id就是一个自定义属性 -->
<text data-id="0">hello world</text>
除了使用 wx.createSelectorQuery 获取页面属性,来获取 data- 开头的自定义属性以外,还可以通过事件获取按钮上的自定义属性,例如:
<button data-id="0" bindtap="remove">删除</button>
⑥将数据保存到小程序的全局对象中
```js
// 获取小程序实例对象
const app = getApp()
app.globalData.x = 1 // 给小程序的全局对象赋值
// 只要不关闭小程序就能通过小程序全局对象保存参数
```
## 持久化数据
什么叫持久化?持久化就是长期存储数据到磁盘中,关闭应用程序后,存储的数据还在
异步是什么?异步就是程序执行的时候不会等待或卡顿
同步是什么?同步的程序在调用的时候会等待或卡顿
异步存储
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorage.html
wx.setStorage(Object object)
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.getStorage.html
wx.getStorage(Object object)
异步删除
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.removeStorage.html
wx.removeStorage(Object object)
下面的是上述方法的同步版本
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.getStorageSync.html
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.removeStorageSync.html
⑦分包:将项目资源切分成多个小块的过程就是分包
项目资源包只允许在2m以内,所以当项目过大时内容超过2m,则需要进行分包
⑧设备的本地功能调用
在不同的设备上可能存在一些设备独有的功能,例如:摄像头,陀螺仪,卫星定位等等
例如:扫描二维码
```js
wx.scanCode({
onlyFromCamera: false,
success: (res) => {
console.log(res);
},
});
```
例如:摄像头拍照
```html
<!-- 添加相机组件到页面 -->
<camera
device-position="7"
flash="off"
binderror="error"
style="width: 100%; height: 300px;"
></camera>
```
⑨事件
bind:普通的绑定事件,并且事件可以冒泡
catch:绑定事件,并不会冒泡
capture-bind:捕获事件并可以冒泡
capture-catch:捕获事件并不冒泡
⑩授权
用户需要使用本地设备上的一些设备功能时,需要向系统获取设备权限,例如:摄像头,定位信息,联系人,陀螺仪等
什么时候使用授权:在用户即将使用一些需要授权才能使用的本地设备功能时(微信小程序已经把这些功能制作成了接口,当需要调用这些接口的时候就可以进行授权)
?流程
- 读取当前权限
- 判断是否存在权限
- 不存在权限就进行授权
?(11)组件开发
组件:高度封装独立运行的模块 组件有自己的数据 自己的标签模板 等等
组件的作用就是为了复用代码
```js
// 在组件的配置中添加 properties 配置
Component({
/**
* 组件的属性列表
*/
properties: {
// 声明属性 value
// 具体声明方式可参考 https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html#properties-%E5%AE%9A%E4%B9%89
value: {
type: String, // 属性类型 可以通过设置 optionalTypes 来接收多种类型的数据
value: 'o,k', // 属性默认值
// 属性变化监听器
observer: function (newVal, oldVal) {
console.log(newVal);
console.log(oldVal);
console.log(this)
}
}
},
})
```
组件内设置属性的方法和 `Page` 设置 `data` 是一样的
```js
// 使用 setData 设置属性
this.setData({value: 'hello'})
```
在 `Page` 中注册组件后就可以将组件作为标签使用了
```json
// 注册组件
{
"useingComponent": {
"my-component": "path/to/component"
}
}
```
```html
<!-- 使用组件 -->
<!-- _value 是当前页面 data 中的值 -->
<my-component value="{{_value}}"></my-component>
```
> 注意: 除了在组件内修改 `value` 值以外,还可以通过修改 `Page` 的 `_value` 来修改组件的 `value` 值
## 组件方法
### 获取组件并调用组件方法
```js
Page({
getComponent() {
// 给组件添加 class="my-component"
// 通过 selectComponent 获取组件
let com = this.selectComponent('.my-component')
// 假设组件 methods 中有个方法叫 myFn
// 调用组件方法
com.myFn()
}
})
```
## 组件事件
```html
<!-- 假设组件的模板如下 -->
<button bindtap="onClick">发送点击事件</button>
```
```js
// 组件声明如下
Component({
methods: {
onClick() {
// triggerEvent 可以发出事件
// 文档: https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html#%E7%9B%91%E5%90%AC%E4%BA%8B%E4%BB%B6
// 第一个参数: 发出的事件名称
// 第二个参数: 事件传递出去的参数
// 第三个参数: 事件选项
this.triggerEvent('my-click', 'my detail')
}
}
})
```
```html
<!-- Page 的 wxml 如下 -->
<!-- 通过 bind:<event-name> 的方式绑定事件 -->
<my-component bind:my-click="myClickHandler"></my-component>
```
```js
Page({
// myClickHandler 将接收组件的 my-click 事件
myClickHandler(event) {
// event.detail 的值就是 triggerEvent 的第二个参数值
console.log(event.detail)
}
})
```
3.云开发
①云环境:云端(远程端)的运行程序的平台
②云函数:云函数就是在云端(远程端)调用的函数
调用函数时,首先发起网络通信,让服务器调用函数,然后通过网络返回结果
定义云函数
1. 在编辑器的 cloudFunctions 文件夹中右键 新建node.js云函数
2. 编辑index.js中的main函数 返回想要的返回值
③云数据库:数据库软件在服务器上运行
?数据库的增删改查
增删改查是数据库的四个操作
1. 增:添加数据
2. 删:删除数据
3. 改:修改数据
4. 查:查询数据
数据库的增删改查是数据库最基础的操作
### 初始化数据库连接
1. 在 app.js 的 onLaunch 中 初始化数据库
```js
//app.js
App({
onLaunch: function () {
......
this.globalData = {}
// 初始化数据库
const db = wx.cloud.database()
// 在全局对象中保存db对象
this.globalData.db = db
}
})
```
2. 在使用数据库的页面中获取db对象
```js
const db = getApp().globalData.db
```
3. 获取要操作的数据库表
```js
// 获取数据库表 参数为表名
const collection = db.collection('collectionName')
```
4. 通过表对象执行数据库操作
### 插入数据
```js
insert() {
// 获取插入数据的表格
// 参数是表格名
const students = db.collection('students')
// 使用add函数插入数据
students.add({
// 要插入到数据库的数据
data: {
name: '法外狂徒张三',
sex: 'other',
age: 30
},
success(res) {
console.log(res);
},
fail(reason) {
console.error(reason);
}
})
}
```
### 查询数据
从形式上来分,可以分为 列表查询和分页查询
列表查询:适用于手机等移动端查询一个数据列表的查询方法
分页查询:用于将数据像书页一样分页码进行查询
此处以列表查询为例
```js
// 获取数据库表
const students = db.collection('students')
// 查询数据并按照数据的更新时间进行排序
// orderBy 函数用于数据排序
// 第一个参数:排序字段
// 第二个参数:排序方法(是升序asc还是降序desc)
// limit 用于规定返回数据量
// get 查询函数 通常放在链式调用的尾部
students.orderBy('updateTime', 'desc').limit(2).get({
success(res) {
console.log(res);
}
})
// 添加查询条件和查询指令
// 查询指令:用于规定如何查询的一些查询方法
// 文档地址:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/query.html
const _ = db.command // 获取指令对象
// where 添加查询约束(where是约束的意思)
students.orderBy('updateTime', 'desc').limit(2).where({
// 参数是个对象
// key 要添加约束的对象
// value 什么样的约束 此处的例子 是查询 updateTime 字段小于指定值的数据
updateTime: _.lt(new Date('Mon Sep 13 2021 09:40:13 GMT+0800'))
}).get({
success(res) {
console.log(res);
}
})
```
### 更新数据
```js
update() {
const students = db.collection('students')
const _ = db.command // 获取指令对象
// 获取对应id的文档对象
const student = students.doc('cd045e75613eabf80d332db93f080137')
student.update({
// data 要修改的字段集合
data: {
// 规范的做法是使用 set 指令经行修改
// name: _.set('修成正果张三'),
name: '修成正果张三',
updateTime: new Date() // 更新时间
},
success(res) {
console.log(res);
}
})
// 多条数据的更新如下
// 调用表格的 where 函数添加查询条件
students.where({
sex: 'male'
}).update({ // 调用 update 函数进行更新
data: {
age: 16
},
success(res){}
})
}
```
### 删除数据
```js
remove() {
const students = db.collection('students')
// 获取对应id的文档对象
// 此处的id就是想要删除的数据的id
const student = students.doc('cd045e75613eabf80d332db93f080137')
// remove 删除对应id的数据
student.remove({
success(res) {
console.log(res);
}
})
// 批量删除
// 调用表格的 where 函数添加查询条件
students.where({
sex: 'male'
}).remove({ // 调用 remove 函数进行删除
success(res){}
})
}
```
总结
这个阶段的内容知识点比较多,需要我们课下多花时间去练习记忆。
|