微信小程序相关知识点和云音乐项目制作遇到的问题及解决
小程序項目想下載項目的可以下載看看~
下載地址
- github地址: https://github.com/superBiuBiuMan/Wechat_NetEase_CloudMusic
- gitee地址: https://gitee.com/superBiuBiu/Wechat_NetEase_CloudMusic
彈性盒布局和移動端適配的一些知識
- 具體看下面這兩篇博客,這里就不再繼續說了
- 盒子模型及塊元素水平垂直定位和絕對元素的定位布局和彈性盒
- 移動端前端的適配和rem,vm其他的一些的復習
微信小程序的適配方案
- 小程序適配單位:rpx
- 小程序規定任何屏幕小的寬度為750rpx
- 所以小程序會根據屏幕的寬度不同自動計算rpx值的大小
- 在iPhone6情況下(其實也就是DPR為2的情況下) 1px = 2rpx
- 舉個例子,比如設計師在iPhone6尺寸(375*667)下設計UI圖,那么有一張圖片的大小為100px * 50px ,那么在微信小程序當中對應的rpx是多少呢? 相當于計算下方關系,當然,不需要我們自己去計算,微信小程序會自動轉換
- 計算得結果等于200,所以是200rpx
什么是響應式和自適應
- 一句話:響應式對不同頁面做出代碼變更,自適應不做代碼變更
響應式
-
像素達到臨界點就使用另外一套樣式,通過媒體查詢的方式,也就是據屏幕的大小自動的調整頁面的展現方式
-
響應式的概念應該是覆蓋了自適應,但是包括的東西更多了
自適應
- 百分比布局,寬度使用百分比,文字使用em,rem等
- 自適應是為了解決如何才能在不同大小的設備上呈現相同的網頁
小程序配置
全局配置
- @官網全局配置API地址
- 小程序根目錄下的 app.json 文件用來對微信小程序進行全局配置。文件內容為一個 JSON 對象,有以下屬性:
- 比如說配置頁面底部的導航
- 比如說配置頁面路由項目
- 比如說小程序標題名
頁面配置
- @官網頁面配置API
- app.json當中的部分配置項和對單個頁面的配置項(二者通用)
- 在全局配置當中需要有window字段,而單個頁面的配置項.json文件當中是不需要添加window字段的
全局配置(app.json),需要添加window字段
為某一個頁面配置(比如說video頁面video.json),就不需要添加window字段了
sitemap
- @官網sitemapAPI地址
- 用于被微信搜索爬取頁面
小程序框架接口
App.js
-
@官網API接口
-
App.js 只有一個,所以執行App({...})在里面,而在每一個頁面執行的是Page({...})函數
-
可以配置一些生命周期,并且可以用來全局數據globalData
-
App.js當中內容代碼如下
- 如果需要獲取App.js所生成的實例化對象,其他js文件需要調用getApp()函數,經常用來讀取設置的全局數據
xxx.js(不同頁面不同的xxx.js)
-
@官網API
-
每一個頁面js當中執行的是Page({...})函數,App.js 只有一個,執行App({...})在里面
-
不管有多少頁碼,每一個頁面的xxx.js基本內容差不多都是這樣子
WXML語法
- @官方API
- 和vue不同的是,vue一般對于變量是要在屬性前添加v-bind 或者簡寫為:的,微信小程序則需要通過{{ js代碼 }}來操作變量
數據綁定
-
@官方API
-
使用數據的一方
- 提供數據的一方
列表渲染
-
@官方API
-
微信小程序如果需要操作的話,也需要綁定key值
- 綁定key的時候,不需要書寫{{ }}符號,直接傳入key值,比如循環的每一項為item,里面有一個字段為id,那么傳入wx:key的時候只需要wx:key="id" ,而不是wx:key="{{id}}"
-
wx:for語句有別與vue,在vue當中需要手動指明循環的變量,而微信小程序如果在不指定的情況下,循環項目自動命名為item,當前循環的索引自動命名為index,也可以使用如下代碼去重命名,不過,一般都是二三層循環的時候才去,一般都是默認情況
使用 wx:for-item 可以指定數組當前元素的變量名,使用 wx:for-index 可以指定數組當前下標的變量名:
條件渲染
-
@官方API
-
在框架中,使用 wx:if="" 來判斷是否需要渲染該代碼塊:
block wx:if
- 可以用于包括要判斷的元素,并且不做渲染,這樣子就不用在外面套一層view再去判斷是否渲染了
- <block/> 并不是一個組件,它僅僅是一個包裝元素,不會在頁面中做任何渲染,只接受控制屬性。
WXS文件
- @官方API - wxs
- 這里就不說啦,看這位博主寫的就可以~
- @博客地址
事件系統/事件
- @官方API-介紹
- @官方API - 事件分類
- 在學事件之前,我們先回顧理解下標準事件流和非標準事件流
- 除上官網公布的事件之外的其他組件自定義事件如無特殊聲明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(詳見各個組件)
標準事件流
- 捕獲: 從最外層祖先開始捕獲
- 執行: 從最內層開始執行事件(執行相同的事件)
- 冒泡:從最內層開始執行,從內向外執行的過程交冒泡
非標準事件流
- IE瀏覽器專屬
- 特點:沒有捕獲階段
事件格式及示例
- bind + 事件名 (不會阻止事件冒泡)
- catch + 事件名 (會阻止事件冒泡)
- 常見的事件tap,就相當于PC端的click
示例
- 當用戶點擊該組件的時候會在該頁面對應的 Page 中找到相應的事件處理函數。
- 在相應的 Page 定義中寫上相應的事件處理函數,參數是event。
打印輸出event
{"type":"tap","timeStamp":895,"target": {"id": "tapTest","dataset": {"hi":"Weixin"}},"currentTarget": {"id": "tapTest","dataset": {"hi":"Weixin"}},"detail": {"x":53,"y":14},"touches":[{"identifier":0,"pageX":53,"pageY":14,"clientX":53,"clientY":14}],"changedTouches":[{"identifier":0,"pageX":53,"pageY":14,"clientX":53,"clientY":14}] }數據綁定
- 小程序沒有自帶的雙向綁定,但是可以通過this.setData來實現修改數據后視圖也變化
- this.data.key = value修改data當中的數據,注意和vue進行區分**,vue為什么不用加一層data,那是因為vue做了數據劫持**
- 這樣子是不會引起視圖的改變的! 小程序沒有自帶的雙向綁定
- 如果想要觸發視圖中數據的更新,那么就需要借助setData這個方法用了,setData的機制去把視圖層和邏輯層做一個“中轉站”兩邊連接起來。 注意這里的回調函數必須要用箭頭函數,否者this指向不正確
如圖
小程序獲取,查詢,元素/組件的信息
-
@官方API - boundingClientRect
-
@官方API -createSelectorQuery
-
其功能類似于 DOM 的 getBoundingClientRect
-
獲取元素節點信息語法格式
NodesRef.boundingClientRect(function callback)//返回對象的信息均為px格式function callback 回調函數,在執行 SelectorQuery.exec 方法后,節點信息會在 callback 中返回。返回對象屬性 類型 說明id string 節點的 IDdataset Object 節點的 datasetleft number 節點的左邊界坐標right number 節點的右邊界坐標top number 節點的上邊界坐標bottom number 節點的下邊界坐標width number 節點的寬度(包括padding,包括border)height number 節點的高度(包括padding,包括border) -
wx.createSelectorQuery()
- 返回一個 SelectorQuery 對象實例。在自定義組件或包含自定義組件的頁面中,應使用 this.createSelectorQuery() 來代替。
-
獲取元素節點信息和查詢節點案例
wxml
<!--pages/boundingClientRect/boundingClientRect.wxml--> <view class="list-container">查看我多大吧</view>wxss
/* pages/boundingClientRect/boundingClientRect.wxss */ .list-container{width: 300rpx;height: 300rpx;padding: 10rpx;background-color: red;border: 6rpx solid blue; }js
onLoad(options) {//select查詢單個結果// 也有selectAll查詢全部結果wx.createSelectorQuery().select(".list-container").boundingClientRect((res)=>{console.log(res);}).exec(); },輸出結果
bottom: 166, dataset:{}, height: 166, id: "", left: 0, right: 166, top: 0, width: 166vue和小程序都是單向數據流
什么是單向數據流
- 在父傳子的前提下,父組件的數據發生會通知子組件自動更新
- 子組件內部,不能直接修改父組件傳遞過來的props => props是只讀的
vue
-
單向數據流
-
但是實現了雙向數據綁定 v-model 和 input事件結合使用
-
修改狀態數據
- this.key = value
-
同步修改 model數據結構 和 視圖同時修改
小程序
- 單向數據流
- 同步修改 model數據結構 和 視圖 同時修改,通過this.setData
App.json當中配置路由,路由跳轉及需要注意的點
- @官方API-pages
- @官方API-路由跳轉
- 微信小程序的路由和vue路由不同,小程序的默認路由會自動設置,即為配置項目pages數組的第一個
注意點
- App.json當中的配置項pages在配置路由頁面的時候不可以再加上 /
錯誤示范如下
// 不要在前面添加 / {"pages": ["/pages/index/index","/pages/logs/logs","/pages/test/test"],"sitemapLocation": "sitemap.json" }正確示范如下
{"pages": ["pages/index/index","pages/logs/logs","pages/test/test"],"sitemapLocation": "sitemap.json" }- 在路由跳轉的時候,必須要加上 / 才可以正確跳轉
- 不同的路由跳轉會有所區別,有的是不允許跳轉到 tabbar 頁面 的
小程序使用分包
-
@官方API - 全局配置(app.json)當中的subpackages配置項
-
@官方API - 使用分包和示例
-
特點
- 加載小程序的時候先加載主播,當需要訪問分包的頁面時候才加載分包內容
- 分包的頁面可以訪問主包的文件,數據,圖片等資源
- 目前小程序分包大小有以下限制:
- 整個小程序所有分包大小不超過 20M
- 單個分包/主包大小不能超過 2M
-
主包
- 主包通常放置啟動頁(tabBar)頁面
-
分包
- 除了主包,其他就都是分包了
-
常規分包和獨立分包
-
常規分包
- 開發者通過在app.json的subpackages字段聲明項目分包結構
- 特點
- 加載小程序的時候先加載主包,當需要訪問分包頁面的時候才加載分包內容
- 分包的頁面可以訪問主包的文件,數據,圖片等資源
-
獨立分包
-
在app.json的subpackages字段當中的每一個配置項中添加independent為true
-
特點
- 獨立分包可以單獨訪問分包的內容,不需要下載主包
- 獨立分包不能依賴主包或者其他包的內容
-
獨立分包使用場景
- 通常某些頁面和當前小程序的其他頁面關聯不大的時候可以進行獨立分包
- 比如: 臨時加的廣告頁 或者是 活動頁
-
-
使用常規分包的具體步驟和示例
打包之前的app.json的pages配置項"pages": ["pages/index/index","pages/songDetail/songDetail","pages/video/video","pages/search/search","pages/recommendSong/recommendSong","pages/personal/personal","pages/login/login"],(1).為分包建立文件夾
這里就建立一個名字叫做mysubpackages文件夾(2).將除了啟動頁(tabBar)的頁面文件夾放置在剛剛創建的文件夾當中
- 注意,這里為了演示,其實應該將這里文件夾放置在pages文件夾下方的,也就是/mysubpackages/pages文件夾下方,和主包的目錄結構保持一致的
(3).app.json配置項修改
app.json當中的pages配置項只留下主包
"pages": ["pages/index/index","pages/video/video","pages/personal/personal" ],將分包寫入app.json當中的subpackages配置項
- subpackages 中,每個分包的配置有以下幾項:
app.json當中subpackages配置項
"subpackages": [{"root": "mysubpackages","name": "所有分包","pages": ["login/login","recommendSong/recommendSong","search/search","songDetail/songDetail"]}],(4).更改跳轉路徑
//跳轉到搜索界面toSearchPage(){wx.navigateTo({// url: '/pages/search/search',url:"/mysubpackages/login/login"});},(5).目錄結構
分包預下載
- @官方API - 分包預下載
- 略
微信小程序生命周期
- @官方API - 生命周期
- 復習下vue的生命周期
- beforeCreated,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed
- 小程序生命周期
- onLoad
- onShow(會重復出現)
- onReady
- onHide 路由重定向的時候如果選擇了比如說wx.navigatorTo之類的保活的,就會產生隱藏生命周期
- onUnload 相當于是銷毀的生命周期
- 具體的圖片
小程序使用npm包步驟
(1).初始化
npm init -y(2).勾選使用npm(有的項目需要勾選,現在沒有這個選項了)
(3).下載需要的包
npm install moment --save(4).引入包
// pages/boundingClientRect/boundingClientRect.js import moment from "moment"(5).引入包后構建npm
- 開發工具 —> 工具 —> 構建npm
- 會將node_modules中的包打包到miniprogram_npm中
如果步驟錯了,會報這個錯誤module 'pages/boundingClientRect/moment.js' is not defined, require args is 'moment''
只需要再次構建下npm就可以
- 注意
- 測試的時候引入axios包,然后按照這個流程發現不行,可能是小程序不支持axios吧
小程序的ajax請求發送和二次封裝
- @官方API - wx.request
- 需要注意的是
- 在h5的時候,全局對象為window,但是在微信小程序是沒有window的,取而代之的全局對象是wx
- 所以是用wx.xxxx來調用微信提供的方法
- wx.request規定必須是https協議 ,最大并發為10
ajax請求發送
發送請求示例代碼
wx.request({url: 'example.php', //僅為示例,并非真實的接口地址data: {x: '',y: ''},header: {'content-type': 'application/json' // 默認值},success (res) {console.log(res.data)} })二次封裝
// 二次封裝請求 import config from "./config"; /*** params:* url:請求地址* method:請求方式(默認get)* data:請求數據(默認 {} )*/ export default (url, data = {}, method = "get") => {return new Promise((resolve, reject) => {wx.request({url: config.host + url,method,data,header: {//寫入配置項},success(res) {//Do Something},fail(reason) {//返回錯誤原因reject(reason);}});}); }小程序使用自定義組件
- @官網API - 自定義組件介紹
- @官網API - properties
(1)建立文件夾
- 1.先依次建立一個文件夾叫componets/NavHeader
(2)右鍵新建Component
- 2.1.在NavHeader文件夾右鍵,選中新建Component,輸入與文件夾同名的名稱
- 2.2.NavHeader文件夾當中的結構和普通的頁面結構一樣,唯一不同的是不會自動在app.json當中的配置項pages中注冊,因為不是頁面嘛
(3)構建NavHeader的結構
-
3.1 書寫NavHeader結構并使用NavHeader.js當中的propertyies屬性
- 可以看到,選擇新建Component生成的js文件會自動添加如下內容,我們使用的多的,就是 properties
-
3.2 在NavHeader.wxml中使用NavHeader.js的properties屬性
<!--components/NavHeader/NavHeader.wxml--> <view><text>標題:{{title}}</text><text>描述:{{desc}}</text> </view>
(4)其他組件注冊使用自定義組件
- 在要使用此組件的頁面的xxx.json里面的配置項目usingCompoents去注冊,比如下方的index.json當中注冊使用組件NavHeader
index.json當中使用自定義組件NavHeader(相當于注冊組件吧有點)
{"usingComponents": {"NavHeader":"/components/NavHeader/NavHeader"} }(5使用并傳值
index.wxml中使用(也就是xxx.wxml中使用)
<!-- 使用自定義組件 --><NavHeader title="我是標題" desc="我是描述"></NavHeader>tabBar底部導航的實現
-
@官方API- tabBar
-
tabBar配置項用的比較多的
- color: tab 上的文字默認顏色,僅支持十六進制顏色
- selectedColor:tab 上的文字選中時的顏色,僅支持十六進制顏色
- backgroundColor:tab 的背景色,僅支持十六進制顏色
- list: tab 的列表,詳見 list 屬性說明,最少 2 個、最多 5 個 tab
-
注意的是
- 假如有需求需要計算一個容器的高度比如通過calc計算,那么在計算高度的時候,比如減去一部分的高度,這個時候可以忽略tabBar的高度,而不用減去,因為微信小程序會自動處理
示例 app.json當中添加配置項
{"tabBar": {"color": "#333","selectedColor": "#d43c33","backgroundColor": "#fff","list": [{"pagePath": "pages/index/index","text": "首頁","iconPath": "/static/images/tabs/tab-home.png","selectedIconPath": "/static/images/tabs/tab-home-current.png"},{"pagePath": "pages/video/video","text": "視頻","iconPath": "/static/images/tabs/video.png","selectedIconPath": "/static/images/tabs/video-current.png"},{"pagePath": "pages/personal/personal","text": "個人中心","iconPath": "/static/images/tabs/tab-my.png","selectedIconPath": "/static/images/tabs/tab-my-current.png"}]}, }效果圖
js文件使用this.data.xxx和this.xxx和this.setData的區別
// pages/test/test.js Page({data: {}, })this.data.xxx
- this.data.xxx 操作當前配置項當中data的屬性值,但是操作不會更新視圖
this.xxx
- 操作當前由Page生成的實例化對象上的屬性
- 可以用來綁定一個共用,唯一的值,比如說單例
this.setData
- this.setData({ value: 'leaf' })可以更新配置項當中data的屬性值,并且會引發視圖更新
元素當中id和data-xxx在辨別數據的使用
- 有時候我們想一個函數被二個不同功能的組件所觸發,但是所處理的功能不同,就可以為組件添加id或者是data-xxx來區分
- id區分和data-xxx區分主要區別就是id只能有一個,而data-xxx可以有多個
- 在回調函數的事件對象當中通過currentTarget 或者target來獲取id或者data-xxx屬性
- currentTarget和target的區別主要在于是否是事件委派,如果沒有事件委派,那么二者沒有區別
- 如果有事件委派/委托,區別如下
- currentTarget是綁定事件的元素(父元素)
- target: 是觸發事件的元素(子元素)
有如下結構
可以看到,test.wxml的二個view組件都賦予了同一個回調函數,那么如何區分呢?這里添加了id和data-index
<!--pages/test/test.wxml--> <text>\n</text> <text>\n</text> <text>\n</text> <view bindtap="handleTouch" id="one" data-index="0">我是組件1</view> <text>\n</text> <view bindtap="handleTouch" id="two" data-index="1">我是組件2</view>test.js內容
handleTouch(event){console.log(event); },我們任意單擊一個view,輸出查看下事件對象event,可以看到,currentTarget和target記錄著一些數據,正好是我們所設置的數據,那么就可以以此來區分是哪一個組件觸發的了
完整js代碼如下
handleTouch(event) { //獲取組件的id let id = event.target.id; if (id === 'one') {console.log("組件1觸發的"); } if (id === 'two') {console.log("組件2觸發的"); } },當然,也可以通過data-xxx來區分
handleTouch(event) { //獲取組件的id let index = event.target.dataset.index; if (index === '0') {console.log("組件1觸發的"); } if (index === '1') {console.log("組件2觸發的"); } },文本超出顯示省略號或文本超出兩行后顯示省略號
- 需要注意的是
- overflow屬性只會在塊級元素才會生效
文本超出顯示省略號
- 關鍵代碼就是下面這三行
示例
- @在線演示
文本超出兩行后顯示省略號
- 關鍵代碼如下
示例
- @在線演示
小程序的輕提示(Toast)
- @官方API - Toast
- 和其他不同的就是小程序的輕提示除了none,其他都只限于7個漢字的長度
- 并且小程序的輕提示-wx.showLoading必須要調用wx.hideToast進行手動關閉才可以,其他的就不用
小程序當中視頻的操作
-
@官方API - video
-
想要操作視頻,比如說跳轉到指定位置,倍速播放的時候,就需要對視頻(video)進行操作了
-
大致操作就是先創建屬于這個視頻的上下文對象,然后對上下文對象進行操作
- 設計到視頻的操作有很多,可以查看官方API的說明~
- bindtimeupdate : 播放進度變化時觸發
- bindfullscreenchange: 視頻進入和退出全屏時觸發
-
下方步驟為操作一個video的基本步驟
(0)wxml基本結構
<!--pages/videotest/videotest.wxml--> <view><!-- 視頻1 --><video id="1" src="http://vfx.mtime.cn/Video/2019/03/18/mp4/190318214226685784.mp4"></video><button bindtap="handlePlay">播放/暫停視頻1</button> </view>(1)創建視頻上下文對象
- @官方API - createVideoContext
- let 當前video的上下文對象 = wx.createVideoContext(video組件的id)
(2)控制視頻的播放/暫停/跳轉
- @官方API - 視頻上下文操作方法
補充:由于微信問題,視頻播放下一個的時候不會自動暫停上一個視頻,所以這里需要使用視頻上下文進行處理
-
演示內容,當播放視頻1的時候,又跑去播放視頻2,那么視頻1會被暫停播放
-
示例wxml基本結構
- 記得綁定bindplay哦
js代碼
handlePlay(event) {//1.先獲取下視頻的idlet videoId = event.target.id;//1.5 判斷之前是否創建過了,如果創建過了,則暫停播放if(this.videoContext){//暫停上一個視頻this.videoContext.pause();}//2.創建視頻的上下文對象this.videoContext = wx.createVideoContext(videoId);},小程序的video組件設置為100%出現黑色邊框
- @官方API - video
- 設置video組件的object-fit屬性為cover即可
如圖
scroll-view滾動到指定位置并且有過渡效果
- @官網API -scroll-view
- 實現滾動到指定位置的二個屬性
- scroll-into-view: 值應為某子元素id(id不能以數字開頭)。設置哪個方向可滾動,則在哪個方向滾動到該元素
- scroll-with-animation : 在設置滾動條位置時使用動畫過渡
- 實現原理
- 通過動態設置scroll-into-view的值來實現
效果
代碼實現
wxml
<!--pages/bar/bar.wxml--> <scroll-view class="nav-tab" enable-flex scroll-x scroll-into-view="{{'scroll'+selectedId}}" scroll-with-animation><view class="nav" wx:for="{{navList}}" wx:key="id" id="{{'scroll'+item.id}}"><view class="nav-item {{selectedId==item.id?'active':''}}" bindtap="changNavTab" id="{{item.id}}">{{item.name}}</view></view> </scroll-view>js
// pages/bar/bar.js Page({/*** 頁面的初始數據*/data: {//數據列表navList: [{"id": 58100,"name": "現場","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 60100,"name": "翻唱","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 1101,"name": "舞蹈","url": "","relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 58101,"name": "聽BGM","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 262158,"name": "萬有引力","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 261121,"name": "告白","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 259132,"name": "云村放映廳","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 259129,"name": "超燃聯盟","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 264120,"name": "熱歌看得見","url": null,"relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 243125,"name": "#歌手#","url": "","relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 243123,"name": "致敬英雄","url": "","relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 254120,"name": "滾石唱片行","url": "","relatedVideoType": null,"selectTab": false,"abExtInfo": null},{"id": 249121,"name": "宮崎駿","url": "","relatedVideoType": null,"selectTab": false,"abExtInfo": null},],//默認選中項selectedId:'58100'},//單擊標簽跳轉到指定標簽changNavTab(event){this.setData({selectedId:event.target.id})},})wxss
/* pages/bar/bar.wxss */ .nav-tab{display: flex;white-space: nowrap;margin-top: 15rpx;height: 60rpx;/* flex-wrap: nowrap; */ } .nav-tab .nav {padding: 0 10rpx;margin: 0 10rpx;height: 60rpx; } .nav-tab .nav .nav-item{padding-bottom: 7rpx;font-size: 28rpx; } .nav-tab .nav .nav-item.active{border-bottom: 1rpx solid #ee5d44; }用戶轉發分享和自定義轉發分享內容
如果想要區分是當前頁面調用了button觸發的分享還是右上角轉發菜單觸發的分享,只需要在onShareAppMessage回調當中結構出from,通過from判斷
onShareAppMessage({from}) {if (from === 'menu') {//右上角轉發菜單調用的分享} else {//為按鈕調用的分享} }button實現
- 通過設置button的open-type屬性為share,即成為了一個分享功能的按鈕,其實這樣子已經可以使用了,但是我們可以自定義分享的圖片和標題~
- 想要自定義,就需要在對應頁面的js文件當中添加onShareAppMessage回調
- @官網API-onShareAppMessage
wxml
<!--pages/share/share.wxml--> <button open-type="share">單擊我分享</button>js
// pages/share/share.js Page({/*** 用戶點擊右上角分享*/onShareAppMessage() {//如果都留空,則都采取默認值return {title:"我來分享啦~~~我是自定義內容",imageUrl:"https://dreamlove.top/img/favicon.png"}} })自定義內容后的效果
微信小程序背景音頻的播放
- @官方API - BackgroundAudioManager
- @官方API - BackgroundAudioManager 實例
- 大體步驟如下
(1)獲取全局唯一的背景音頻管理對象,返回BackgroundAudioManager 實例
-
@官方API - BackgroundAudioManager
-
注意的是
-
從微信客戶端6.7.2版本開始,若需要在小程序切后臺后繼續播放音頻,需要在 app.json 中配置 requiredBackgroundModes 屬性。開發版和體驗版上可以直接生效,正式版還需通過審核。
{"requiredBackgroundModes": ["audio"], }
-
(2)操作BackgroundAudioManager 實例
- @官方API - BackgroundAudioManager 實例
- 比較常用的實例屬性
- startTime: 音頻開始播放的位置(單位:s)。
- src:音頻的數據源(2.2.3 開始支持云文件ID)。默認為空字符串,當設置了新的 src 時,會自動開始播放,目前支持的格式有 m4a, aac, mp3, wav。
- title😗*(必填)**音頻標題,用于原生音頻播放器音頻標題(必填)。原生音頻播放器中的分享功能,分享出去的卡片標題,也將使用該值。
- duration:當前音頻的長度(單位:s),只有在有合法 src 時返回。(只讀)
- currentTime:當前音頻的播放位置(單位:s),只有在有合法 src 時返回。(只讀)
- 比較常用的方法
- play(): 播放音樂
- pause(): 暫停音樂
- seek(跳轉到的位置): 跳轉到指定位置(單位為s)
- onTimeUpdate(callback):監聽背景音頻播放進度更新事件,只有小程序在前臺時會回調。
- onEnded():監聽背景音頻自然播放結束事件
微信小程序的授權登錄和獲取openid
wx.getUserProfile( 2022 年 10 月 25 日 24 時后 會失效)
-
@官方API地址
-
@即將廢棄公告
-
授權動作只會發生一次,必須要清除緩存后才可以重新請求授權,并且授權信息永不過期
-
授權過程如下
(1).button按鈕綁定回調
<!--pages/userprofile/userprofile.wxml--> <button bindtap="handleUserInfo">單擊我申請授權</button>(2).自定義一個函數,這里取名 handleUserInfo 并且添加wx.getUserProfile方法 需要注意的是,事件名都是小寫
// pages/userprofile/userprofile.js handleUserInfo() {wx.getUserProfile({desc: '請求授權',success: (res) => {console.log("用戶同意授權");console.log(res);},fail: (reason) => {console.log("用戶拒絕授權");console.log(reason);}})},(3).處理授權結果
- 成功結果輸出
- 失敗結果輸出
獲取openid
-
@官方API - wx.login
-
@官方API - auth.code2Session
-
wx.login與auth.code2Session結合使用
-
wx.login
- 調用接口獲取登錄憑證(code)。通過憑證進而換取用戶登錄態信息,包括用戶在當前小程序的唯一標識(openid)、微信開放平臺帳號下的唯一標識(unionid,若當前小程序已綁定到微信開放平臺帳號)及本次登錄的會話密鑰(session_key)等。用戶數據的加解密通訊需要依賴會話密鑰完成。
-
auth.code2Session
- 登錄憑證校驗。通過 wx.login 接口獲得臨時登錄憑證 code 后傳到開發者服務器調用此接口完成登錄流程。更多使用方法詳見 小程序登錄
-
步驟如下
(1).wx.login獲取登錄憑證
handleOpenid() {wx.login({success: (res) => {//獲取登錄憑證let code = res.code;}})},(2).有了登錄憑證,再通過auth.code2Session獲取openid
- 這里我沒有自己后臺服務器,就直接這樣子用了,其實可以通過后臺來調用,這樣子就不會泄露自己的開發信息了
(3).處理結果
- 授權成功輸出
- 授權失敗輸出這里錯誤的appid
小程序更新數據狀態的區別
- 實時更新(每發一次請求就更新一部分數據)
- 優點: 用戶等待時間較短
- 缺點: 多次更新頁面
- 統一更新
- 優點: 減少更新的次數,只更新1次
- 缺點: 網絡較差的時候用戶等待時間過長,可能會看到白屏
小程序的數據存儲
-
@官方API - 操作數據存儲
-
不同小程序的數據存儲相互獨立,互不干擾. @官方解釋網站
-
同一個微信用戶,同一個小程序 storage 上限為 10MB。storage 以用戶維度隔離,同一臺設備上,A 用戶無法讀取到 B 用戶的數據;不同小程序之間也無法互相讀寫數據。
-
插件隔離策略
- 同一小程序使用不同插件:不同插件之間,插件與小程序之間 storage 不互通。
- 不同小程序使用同一插件:同一插件 storage 不互通。
-
與h5的storage不同的是,h5的需要轉化為json格式的字符串后存儲,而小程序可以直接存儲對象,也可以存儲json格式字符串
wx.setStorageSync(存數據)
- 將數據存儲在本地緩存中指定的 key 中。會覆蓋掉原來該 key 對應的內容。除非用戶主動刪除或因存儲空間原因被系統清理,否則數據都一直可用。單個 key 允許存儲的最大數據長度為 1MB,所有數據存儲上限為 10MB。
示例 - 直接存儲對象
let data = {"objects": [{"ID": "1","JobTitle": "Software Engineer","EmailAddress": "Gil_West3007@elnee.tech","FirstNameLastName": "Gil West"},{"ID": "2","JobTitle": "Associate Professor","EmailAddress": "Leslie_Little2936@naiker.biz","FirstNameLastName": "Leslie Little"},] } wx.setStorageSync('userInfo', data.objects);調試器信息 - Storage項
wx.getStorageSync(取數據)
let data1 = wx.getStorageSync('userInfo'); console.log("獲取的數據",data1);調試器輸出信息
小程序scroll-view的下拉刷新
- @官方API-scroll-view組件
- scroll-view需要開啟和設置的屬性
- refresher-triggered: 設置當前下拉刷新狀態,true 表示下拉刷新已經被觸發,false 表示下拉刷新未被觸發(會顯示相應的效果)
- refresher-enabled : 是否開啟自定義下拉刷新,true開啟,false關閉(默認)
- scroll-view需要添加的回調或監聽
- bindrefresherrefresh:自定義下拉刷新被觸發
- scroll-view需要實現上拉加載更多只需要添加
- bindscrolltolower 滾動到底部/右邊時觸發就可以
- 順帶一提
- 使用calc計算scroll-view的高度的時候,calc的計算符號和數字之間必須要分開來才可以,否者計算會無效!并且如果小程序有tabBar(底部導航),可以不用減去底部導航的高度(小程序會自動處理)
示例
- 模擬請求發送數據,1s后關閉下拉刷新并顯示提示
效果圖
wxml
<!--pages/refreshscroll/refreshscroll.wxml--> <scroll-view class="item-container" scroll-y refresher-enabled refresher-triggered="{{isRefresh}}" bindrefresherrefresh="handlePullRefresh" ><view class="item">我是內容</view><view class="item">我是內容</view><view class="item">我是內容</view><view class="item">我是內容</view><view class="item">我是內容</view> </scroll-view>js
// pages/refreshscroll/refreshscroll.js Page({/*** 頁面的初始數據*/data: {isRefresh:false,//是否處于正在刷新的狀態},handlePullRefresh(){// console.log("用戶下拉刷新了");//當用戶觸發下拉刷新,data當中的'isRefresh'的值會自動被小程序更改為true//模擬請求發送數據,1s后關閉下拉刷新并顯示提示setTimeout(()=>{//設置當前下拉刷新狀態this.setData({isRefresh:false});//顯示用戶提示wx.showToast({title: '刷新成功!',});},1000);}, })wxss
/* pages/refreshscroll/refreshscroll.wxss */ .item-container{border: 1rpx solid red;height: 400rpx; }為什么小程序沒有引入css樣式都會生效?
-
在html開發的時候,我們會通過@import或者link標簽來引入css文件,但是微信小程序卻不用我們去引入,那是為什么?
-
我們在app.json的配置項pages已經書寫了一條,比如下面代碼,我們知道,所有頁面都需要寫在pages當中
{"pages": ["pages/index/index",],"sitemapLocation": "sitemap.json" } -
在我們進入頁面,比如說index頁面的時候,小程序回去尋找pages/index文件夾,然后依次訪問,尋找與訪問頁面同名的文件,index.wxml, index.wxss ,index.js ,index.json
- 所以你可以試試看,把index.wxss改為index11.wxss,然后再去訪問index頁面,就會丟失樣式
@import 和import 引入css區別和小程序引入css?
- 一句話@import引入css樣式在html文件,或者css文件當中,
- 而import是用來引入模塊的,當然,如果有webpack工具也是可以通過import引入css文件的
@import的用法
- (1) html當中的link標簽中使用
- (2) html當中的style標簽中使用
- (3) css文件當中引入
@import區別
- link是XHTML標簽,除了加載CSS外,還可以定義RRS等其他事務。@import屬于CSS范疇,只能加載CSS
- link引用CSS樣式,是和頁面加載同步進行加載,@import是等頁面加載完后才開始加載。
- link是XHTML標簽,無兼容問題;@import是在CSS2.1提出的,低版本的瀏覽器不支持。
- link支持使用Javascript控制DOM去改變樣式;而@import不支持。
小程序引入css
- @ 官方API - wxss
- 使用@import語句可以導入外聯樣式表,@import后跟需要導入的外聯樣式表的相對路徑,用;表示語句結束
示例
/** app.wxss **/ @import "common.wxss"; .middle-p {padding:15px; }微信小程序動態類(class)
- vue的時候動態類
- 小程序的動態類
使用事件委托,children層存在嵌套時無法獲取標識符id,非嵌套時可以如期獲取,嵌套獲取不到標識符id的解決辦法
- 有人提出這個問題,然后我自己也遇到了這個問題,就來記錄下
- 先說嵌套時候的解決辦法
- 通過為子元素添加mark屬性
- @官方API - mark屬性
- mark屬性簡介
- 在基礎庫版本 2.7.1 以上,可以使用 mark 來識別具體觸發事件的 target 節點。此外, mark 還可以用于承載一些自定義數據(類似于 dataset )。
- 當事件觸發時,事件冒泡路徑上所有的 mark 會被合并,并返回給事件回調函數。(即使事件不是冒泡事件,也會 mark 。)
委派子元素層存在嵌套獲取不到標識符id的情況的演示
- 本來想通過事件委派,然后通過event.target.id來獲取是哪一個元素所觸發的,這樣子方便尋找數據,但是實際情況卻是,當單擊到了子元素嵌套的元素的時候,就獲取不到id了
演示動畫,可以看到,單擊子元素內部的索引號或者郵箱地址的時候,出現獲取不到id的情況
委派子元素層存在嵌套獲取id的辦法-通過mark屬性
- @官方API - mark
實現代碼
wxml
<!--pages/weipaimark/weipaimark.wxml--><view class="list-container" bindtap="handleClick" ><view class="item" wx:for="{{userInfo}}" wx:key="id" mark:index="{{index}}"><text>索引號{{index}}</text><text>郵箱地址:{{item.EmailAddress}}</text></view> </view>js
handleClick(event){ //一旦單擊到子元素內容,就會輸出為空 // console.log(event.target.id); console.log(event.mark.index); },wxss
/* pages/weipaimark/weipaimark.wxss */.list-container{border: 1rpx solid red; } .list-container .item{margin-bottom: 10rpx;border: 1px solid blue; }演示效果
其他知識點
js操作的鍵值為變量的時候,需要使用中括號
// pages/refreshscroll/refreshscroll.js Page({data: {priority: {// 優先級'vip': 1111,'user': 1,},},onLoad(options) {let type = 'vip';this.setData({[type]:9999});console.log(this.data.priority);},})判斷類型的時候,老師說最好是全等來判斷
位移運算符轉化為數字
- 這里使用無符號右移運算符轉換為數字~
- 如果轉換過程中有字母,則返回0
- 補充
- ! 一個感嘆號表示取反
- !! 二個感嘆號轉化為布爾值
- !!! 三個感嘆號表示轉化為布爾值并取反
object的toString和Array的toString和其他的toString
-
toString()函數的作用是返回object的字符串表示,JavaScript中object默認的toString()方法返回字符串[object Object]。定義類時可以實現新的toString()方法,從而返回更加具有可讀性的結果。
-
JavaScript對于數組對象、函數對象、正則表達式對象以及Date日期對象均定義了更加具有可讀性的toString()方法:
object的toSting(經常用來判斷數據類型)
- 如果不是object,而是function,需要通過Object.prototype.toSting.call()來調用
- 通過toString()返回類型后可以通過slice(8,-1)來獲取具體類型,代碼功能為從索引為8的開始取,直到倒數第二個
array當中的toString
- array當中的toString會返回以逗號分割的字符串
函數的toString
- function的toString()方法將返回函數的文本定義
Date的toString
- Date的toString()方法將返回一個具有可讀性的日期時間字符串
正則的toString
- RegExp的toString()方法與function的toString()方法類似,將返回正則表達式的文本定義
設計模式之單例模式,工廠模式簡說
單例模式
- 創建多個對象的情況下,使用一個變量來保存,始終只有一個對象
- 當創建新的對象的時候就會把之前的對象覆蓋掉
- 可以節省內存空間
工廠模式
- 根據不同的參數創建不同的對象
如果遍歷的是數組里面的對象,那么修改遍歷時候的遍歷項,會影響原數組
-
@在線演示
-
代碼示例如下,可以看到,更改了找到的item項目后,原來的也會改變
數組的includes,indexOf,find,findIndex ,concat ,slice,splice
includes
- includes() 方法用來判斷一個數組是否包含一個指定的值,根據情況,如果包含則返回 true,否則返回 false。
indexOf
- indexOf()方法返回在數組中可以找到一個給定元素的第一個索引,如果不存在,則返回-1。
find
- 方法返回數組中滿足提供的測試函數的第一個元素的值,找到后就會停止查找,否則返回 undefined。
findIndex
- findIndex()方法返回數組中滿足提供的測試函數的第一個元素的索引,找到后就會停止查找,若沒有找到對應元素則返回-1。
concat
- concat() 方法用于合并兩個或多個數組。此方法不會更改現有數組,而是返回一個新數組。
slice
- slice() 方法返回一個新的數組對象,這一對象是一個由 begin 和 end 決定的原數組的淺拷貝(包括 begin,不包括end)相當于左閉右開。原始數組不會被改變。
splice
- splice() 方法通過刪除或替換現有元素或者原地添加新的元素來修改數組,并以數組形式返回被修改的內容。此方法會改變原數組。
calc計算高度時候的一個坑,因為符號問題
- 錯誤的寫法,運算符和操作數之間沒有空格分開
- 正確的寫法,運算符和操作數之間用空格分開
display:flex和float不能同時使用!!!因為display:flex開啟后是內容撐開容器,float就無法浮動了,因為沒有位置了
開啟定位后子元素相當于父元素水平垂直居中
- 原理可以看看這@文章
- 簡單來說就是盒子計算的問題
設置旋轉的中心點
-
參考的文章1 https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
-
參考的文章2 http://www.360doc.com/content/20/0710/23/25947829_923464975.shtml
-
在沒有設置旋轉中心的時候,我們設置transform:rotate(45deg);都是圍繞元素中點來旋轉的,如下圖
-
但是有時候我們需要設置旋轉中心,就需要通過transform-origin來設置了
- 比如transform-origin:50px 50px,意思就是將中心點移動到距離容器x軸50px的位置,y軸50px的位置
-
也可以設置為右上角頂點 transform-origin:0 0
- 旋轉動畫 transform-origin:0 0 并設置transform:rotate(45deg)效果
小程序生命周期的onLoad當中的參數options,用于路由傳參
- 原生小程序url有長度限制,如果傳參內容過長會自動截取掉
- options.id可以傳入的id參數
在組件 wxss 中不應使用 ID 選擇器、屬性選擇器和標簽名選擇器。
如題~
總結
以上是生活随笔為你收集整理的微信小程序相关知识点和云音乐项目制作遇到的问题及解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 运维自动化之服务器信息采集
- 下一篇: 运营笔记:SEO快排那些事儿!