-
wxs
: 既可以定義在wxml
中也可以寫在單獨的文件.wxs
中var format = function(text) { // 為了匹配\\n 然后進行對應的匹配 // 這里會執(zhí)行一套完整的生命周期 所以剛開始執(zhí)行 format 里面參數(shù)是 頁面數(shù)據(jù)對象的時候 // 就會執(zhí)行一次生命周期 然后會打印兩次值 第一次是undefined if(!text) { return; } var reg = getRegExp("\\\\n", "g"); return text.replace(reg, '\n'); // 然后就執(zhí)行了 // wxs // return '123123'; } // 不能使用const let es6語法... js也有不同 // 還的看文檔中的正則是什么意思 module.exports = { format:format, }
在 book-detail.html 中調(diào)用這個方法:
<wxs src="指向引入這個文件的路徑(只能用相對路徑 ../../那種的)" module="util" /> <!--然后調(diào)用如下--> <text class="content">{{util.format()}}</text> <!--這里面的內(nèi)容是自己解析成三段了 而不是一段 所以就是使用css的方法 text-indent是沒有效果的 然后手動 添加   來進行換行... 因為   的方法浅妆,需要在 text 標簽上配備屬性 decode="{{true}}" return text.replace(reg, '\n    '); 這樣添加一下就可以了--> <!--或者就不需要在wxs中編寫,在wxs標簽里編寫就可以--> <wxs modules="util"> // 這個是編寫 wxs 顯示標簽數(shù)量顯示的方法的 var limit = function(array, length) { return array.slice(0, length); } var format = function(text) { if(!text) { return; } var reg = getRegExp("\\\\n", "g"); return text.replace(reg, '\n'); } modules.exports = { limit:limit, format:format } </wxs>
-
wxs
可以編寫小程序的過濾器障癌,他是小程序自己的腳本語言凌外,主要是增加wxml
的編程能力的。
// .wxs 文件 var highlight = function(index) { if(index == 0) { return 'e-tag1' } if(index == 1) { return 'e-tag2' } return '' } module.exports= { highlight :highlight }
-
黑灰色的遮擋層頁面 其實也可以 做成一個組件…涛浙。 然后做一個
opacity z-index
兩個-
input
有一個事件bind:confirm
可以出去康辑,input框的確認按鈕。// 獲取的時候 const commentInput = event.detail.value // 這個是獲取input框的內(nèi)容 // 然后就很簡單的判斷一下 就可以了 因為選擇了一個 另外一個就是 undefined const comment = event.detail.text || event.detail.value; // 判斷一個 防止為空的字符串 if(!comment) { return } if(comment.length > 12) { wx.showToast({ title: "短評不能超過12個字", icon: "none" }) return } bookModel.postComment(this.data.book.id, comment) .then(res => { wx.showToast({ title: "+1", icon: "none" }) this.data.commmit.unshift({ content: comment, nums: 1 }) this.serData({ comments: this.data.comments, posting: false }) })
<!--comment == true 是可以的 或者說 .length == 0 也是可以的 --> <text wx:if="{{comment==true}}">僅可點擊標簽+1</text> <text wx:else>暫無短評</text> <text bind:tap="inCancel" class="cancel">取消</text>
服務器限制是服務器限制轿亮,前端在做代碼的時候 不應該過去以來服務器疮薇,前端也應該做一個限制。
加載時長反饋 體驗優(yōu)化
onLoad: function(options) {
// 這個就是 開始的時候 就開始加載 loading 樣式
wx.showLoading();
// 如果要想判斷promise請求完成后才結(jié)束 加載樣式 最好使用Promise.all();
// 如果參數(shù)中 promise 有一個失斘易ⅰ(rejected)按咒,此實例回調(diào)失敗(reject)但骨,失敗原因的是第一個失敗 promise 的結(jié)果励七。
Promise.all([detail, comments, likeStatus])
.then(res => {
// 然后執(zhí)行 隱藏加載樣式。然后把他們各自的邏輯寫在這里
console.log(res);
this.setData({
book: res[0],
comment: res[1],
likeStatus: res[2]
})
// promise 除了 .all 還有一個 .race(競爭的意思)這個是有一個完成了就結(jié)束了回調(diào)了
wx.hideLoading();
})
}
封裝一個 高階 組件(如果一個組件 包含了大量的業(yè)務邏輯的話奔缠,那就可以稱為高階組件)
input
框設(shè)置一個auto-focus="true"
這樣切換進去頁面之后 就會獲得自動聚焦功能封裝成 高階組件 就需要很大程度的復用性掠抬,一般數(shù)據(jù)和方法都要傳遞到父組件去,讓父組件決定校哎。
-
要用
業(yè)務
的思維两波,去考慮封裝,新建一個modules
來進行承載業(yè)務邏輯的代碼闷哆。組件也可可以有自己的業(yè)務邏輯腰奋,或者整個components 或者整個根目錄文件夾下面承載
取決自己的設(shè)計模式或者開放程度。如果說只是為了做一個項目的話阳准,那就都放在根目錄就可以了
如果說要是為了 開源項目氛堕,就放到
components
最好。不建議放到自己的文件夾下面
// keyword.js 數(shù)據(jù)結(jié)構(gòu)隊列的應用
class KeywordModel {
key = 'q'
maxLength = 10
getHistory() {
return wx.getStoragesync(this.key);
if(!words) {
return []
}
return words
}
getHot() {
}
addToHistory(keyword) {
let words = this.gitHistory();
const has = words.includes(keyword)
if(!has) {
// 數(shù)組末尾進行刪除 keyword 的第一位
const length = words.length
if(legth >= this.maxLength) {
words.pop(); // 刪除最后一位
}
words.unshift(keyword)
wx.setStoragesync(this.key, words)
}
}
}
export { KeywordModel };
import { KeywordModel } from 'keyword.js';
const keywordModel = new KerwordMode();
onConfirm(event) {
const word = event.detail.value;
keywordModel.addToHistory(word);
}
-
組件呢野蝇,是有生命周期函數(shù)的讼稚,然后可以 進行調(diào)用
attached
代表初始化組件的時候,小程序默認初始化的一個生命周期函數(shù)绕沈。arrached() { const historyWords = keywordModel.getHistory() this.setData({ historyWords }) }
-
如果想獲取輸入框 點擊標簽或者 輸入框輸入的值锐想;
const value = e.detail.value || e.detail.text;
-
如果想讓
input
輸入框點擊之后 顯示文本框的值;// input 有一個 value屬性 然后可以使用雙向綁定來進行設(shè)置input的值 // <input value="{{value}}" /> data: { value: "" } const value = e.detail.value || e.detail.text; // 應該在用戶搜索成功之后 進行設(shè)置顯示 this.setData({ value, })
監(jiān)聽用戶滑動到頁面底部 從而可以有一個分頁加載的功能
- 一種可以使用小程序的
scroll-view
組件 - 一種可以使用 page頁面的
onReachBottom
(建議大家優(yōu)先選擇)- 組件監(jiān)聽不到事件的觸底效果乍狐,所以可以借助 page 頁面進行監(jiān)聽赠摇,然后傳遞一個
true
或者false
來表示監(jiān)聽。
- 組件監(jiān)聽不到事件的觸底效果乍狐,所以可以借助 page 頁面進行監(jiān)聽赠摇,然后傳遞一個
import { random } from "../../common.js"
Page({
data: {
more: ''
},
onReachBottom() {
this.setData({
more: random(16)
})
}
})
Component({
properties: {
more: {
type: String, // 屬性被賦值之后 如何讓自己定義一個函數(shù)來加載數(shù)據(jù)呢?
// observer: function() {} 一種方法 另外一種如下
observer: '_load_more',
},
data: {
// 為loading加一個鎖的概念 只有當請求完成了 才可以調(diào)用下一次請求
loading: false
},
methods: {
_load_more() {
if(!this.data.q) {
return
}
if(this.data.loading) {
return
}
const length = this.data.dataArray.length
bookModel.search(length, this.data.q).then(res => {
this.data.loading = true
const tempArray = this.data.dataArray.concat(res.books)
this.setData({
dataArray: tempArray
})
this.data.loading = false
})
}
}
},
})
// common.js
const chars= ['0'..'9','a'...'z'];
const random = function generateMixed(n) {
var res = "";
for(var o = 0; o< n; o++) {
var id = Math.ceil(Math.random() * 35);
res += chars[id];
}
return res;
}
export { random };
-
js
文件藕帜,如果要定義私有的方法烫罩,那應該都定義在文件的最底部。 - 注意避免死鎖:
- 如果有網(wǎng)可以進行加載 解鎖功能 如果斷網(wǎng)了 然后也置為 false 了洽故。所以再次上網(wǎng)之后不會加載了也贝攒。
- 特別注意:
- 如果頁面中有 該值的參與顯示,那么設(shè)置的時候 必須要用
this.setData
進行頁面渲染
- 如果頁面中有 該值的參與顯示,那么設(shè)置的時候 必須要用
微信獲取信息的機制
-
獲取用戶信息(不需要用戶授權(quán)时甚,就可以顯示 用戶昵稱和頭像)
- 使用小程序的組件
<open-data>
<!--只需要更換 type屬性就可以啦 然后可以進行不授權(quán)的顯示 用戶昵稱和頭像--> <open-data type="userAvatarUrl"></open-data> <!--{overflow: hidden} 這個code配合raduis設(shè)置img然后才可以設(shè)置成圓形圖片的--> <!--這種辦法只能顯示用戶信息隘弊。但是如果想獲取用戶的信息就不是這么簡單了-->
- 如果是靜默。我們則不需要授權(quán)荒适,如果是需要獲取梨熙,我們就需要用戶授權(quán)了
// 以前是 直接調(diào)用 wx.getUserInfo 來彈窗詢問是否進行授權(quán)的api // 新版的API button組件是可以進行彈窗的 button組件是個ui 然后讓用戶主動去點擊button
- 使用小程序的組件
<button open-type="getUserInfo" bindgetuserinfo="getUserInfo"></button>
getUserInfo(event) {
console.log(event); // event.detail屬性下可以查看到用戶相關(guān)的所有信息
}
// 每次拿到用戶信息 不可能都去clike一下然后獲取信息 所以就要使用到 wx.getUserInfo();
onLoad(options) {
// 如何在onLoad函數(shù)中 知道 用戶是否授權(quán)
wx.getUserInfo({
success:data => { // 只有用戶授權(quán)了 然后調(diào)用這個api 的success里面就會打印data
console.log(data);
}
}),
wx.getSeting({ // 這個函數(shù)是可以知道用戶是否授權(quán)了的
success: data => {
if(data.authSetting['scope.userInfo']){
wx.getUserInfo({
success: data => {
console.log(data);
}
})
}
else {
}
}
});
}
- 這里就會有一個 image-button 的一個概念,button包含圖片的一個組件刀诬,用來實現(xiàn)
分享
獲取信息
的作用
<button open-type="{{openType}}" bindgetuserinfo="onGetUserInfo"
plain='{{true}}' class="container">
<slot name="img"></slot>
</button>
<style>
.container{
padding: 0 !important;
boder: none !important;
}
</style>
Component({
options: { // 由于開啟了插槽所以在這需要配置
multipleSlots: true
},
properties: {
openType: { // 在imageButton定義的這個屬性其實是我們的一個自定義屬性
// 命名規(guī)則 子組件定義屬性 open-type 然后父組件定義屬性 openType
type: String
}
},
data: {
},
methods: {
onGetUserInfo(event) {
this.triggerEvent('getuserinfo', event.detail, {});
}
}
})
<!--父組件中插入的標簽-->
<v-button wx:if="{{authorized}}"
open-type="getUserInfo" class="avatar-postion" bind:getuserinfo="onGetUserInfo">
<image slot="img" class="avatar" src="/image/my/my.png"></image>
</v-button>
<view wx:if="{{!authorized}}"
class="avator-container avator-position">
<image src="userInfo.avatarUrl" class="avatar"></image>
<text>{{ userInfo.nickname }}</text>
</view>
// 父組件的js
data: {
authorized: false; // 這個是控制 ui 界面元素的切換的 老套路
userInfo: null
}
onGetUserInfo(event) {
const userInfo = event.detail.userInfo;
if(userInfo) {
this.setData({
userInfo,
})
}
// const userInfo = event.detail.userInfo;
// 這個是在父組件的 事件監(jiān)聽函數(shù)中 打印出來的 自定義的事件
// this.setData({
// userInfo,
// })
}
-
如果你想從一個小程序 跳轉(zhuǎn)到 另外一個小程序里面去咽扇,那么這兩個小程序必須同時關(guān)聯(lián)同一個公眾號。
- 在 服務號或者訂閱號 之間是可以做關(guān)聯(lián)設(shè)置的舅列。
<!-- target必須設(shè)置 app-id也是需要進行配置的(關(guān)聯(lián)的小程序的id) --> <navigator target="miniProgram" app-id="xxxxxx" open-type="navigate"> <image class="vendor" src="xxx.jpg"></image> </navigator>
盡量少在
onload
中 書寫代碼邏輯肌割。直接this.function
調(diào)用即可。
小程序的項目比較小帐要,本身就是一個前端開發(fā)者的話 推薦使用 云開發(fā)
補充
開發(fā)版 體驗版 正式版 區(qū)別
開發(fā)版 是開發(fā)者自己的體驗開發(fā)的一款版本
-
體驗版 是上線之前 讓產(chǎn)品經(jīng)理把敞、項目經(jīng)理、客戶榨惠、測試工程師進行體驗的奋早。還沒發(fā)布。
小程序體驗版是一個剛剛做出來還沒完善的版本赠橙,是供給開發(fā)人員測試用的
-
體驗版支持調(diào)試模式耽装,正式版本不支持調(diào)試模式。
而上線版本就是正式交付給企業(yè)對外開發(fā)的版本期揪,是一個完善的版本掉奄。
通過 __wxConfig.envVersion 能判斷用戶所在的小程序版本
console.log('envVersion',__wxConfig.envVersion);
envVersion: 'develop', //開發(fā)版
envVersion: 'trial', //體驗版
envVersion: 'release', //正式版
gulp
-
顯示全局安裝
npm install -g gulp // 然后需要在使用的gulp項目中單獨安裝一次 npm install gulp // 如果想要吧gulp寫進項目的依賴中 則需要加上 npm install --save-dev gulp
-
開始使用gulp
-
建立
gulpfile.js
var gulp = require('gulp'); gulp.task('default',function(){ console.log('hello world'); });
-
運行 gulp 任務
要運行g(shù)ulp任務,只需切換到存放
gulpfile.js
文件的目錄(windows平臺請使用cmd或者Power Shell等工具)凤薛,然后在命令行中執(zhí)行gulp
命令就行了姓建,gulp
后面可以加上要執(zhí)行的任務名,例如gulp task1
缤苫,如果沒有指定任務名速兔,則會執(zhí)行任務名為default
的默認任務。
-
-
gulp 的 API 介紹
-
gulp.src()
gulp.src()
方法正是用來獲取流的活玲,這個方法來讀取你需要操作的文件就行了gulp.src(globs[, options])
globs參數(shù)是文件匹配模式(類似正則表達式)涣狗,用來匹配文件路徑(包括文件名)谍婉,當然這里也可以直接指定某個具體的文件路徑。當有多個匹配模式時镀钓,該參數(shù)可以為一個數(shù)組穗熬。
options為可選參數(shù)。通常情況下我們不需要用到掸宛。 -
gulp.dest()
gulp.dest()方法是用來寫文件的死陆,其語法為:
gulp.dest(path[,options])
path為寫入文件的路徑
options為一個可選的參數(shù)對象,通常我們不需要用到var gulp = require('gulp'); gulp.src('script/jquery.js') .pipe(gulp.dest('dist/foo.js')); //最終生成的文件路徑為 dist/foo.js/jquery.js,而不是dist/foo.js
-