移动互联应用知识总结

一、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){}
    })
}
```

总结

这个阶段的内容知识点比较多,需要我们课下多花时间去练习记忆。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值