-
wxs
: 既可以定义在wxml
中也可以写在单独的文件.wxs
中var format = function(text) { // 为了匹配\\n 然后进行对应的匹配 // 这里会执行一套完整的生命周期 所以刚开始执行 format 里面参数是 页面数据对象的时候 // 就会执行一次生命周期 然后会打印两次值 第一次是undefined if(!text) { return; } var reg = getRegExp("\\\\n", "g"); return text.replace(reg, '\n'); // 然后就执行了 // wxs // return '123123'; } // 不能使用const let es6语法... js也有不同 // 还的看文档中的正则是什么意思 module.exports = { format:format, }
在 book-detail.html 中调用这个方法:
<wxs src="指向引入这个文件的路径(只能用相对路径 ../../那种的)" module="util" /> <!--然后调用如下--> <text class="content">{{util.format()}}</text> <!--这里面的内容是自己解析成三段了 而不是一段 所以就是使用css的方法 text-indent是没有效果的 然后手动 添加   来进行换行... 因为   的方法,需要在 text 标签上配备属性 decode="{{true}}" return text.replace(reg, '\n    '); 这样添加一下就可以了--> <!--或者就不需要在wxs中编写,在wxs标签里编写就可以--> <wxs modules="util"> // 这个是编写 wxs 显示标签数量显示的方法的 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框的内容 // 然后就很简单的判断一下 就可以了 因为选择了一个 另外一个就是 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>
服务器限制是服务器限制,前端在做代码的时候 不应该过去以来服务器,前端也应该做一个限制。
加载时长反馈 体验优化
onLoad: function(options) {
// 这个就是 开始的时候 就开始加载 loading 样式
wx.showLoading();
// 如果要想判断promise请求完成后才结束 加载样式 最好使用Promise.all();
// 如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
Promise.all([detail, comments, likeStatus])
.then(res => {
// 然后执行 隐藏加载样式。然后把他们各自的逻辑写在这里
console.log(res);
this.setData({
book: res[0],
comment: res[1],
likeStatus: res[2]
})
// promise 除了 .all 还有一个 .race(竞争的意思)这个是有一个完成了就结束了回调了
wx.hideLoading();
})
}
封装一个 高阶 组件(如果一个组件 包含了大量的业务逻辑的话,那就可以称为高阶组件)
input
框设置一个auto-focus="true"
这样切换进去页面之后 就会获得自动聚焦功能封装成 高阶组件 就需要很大程度的复用性,一般数据和方法都要传递到父组件去,让父组件决定。
-
要用
业务
的思维,去考虑封装,新建一个modules
来进行承载业务逻辑的代码。组件也可可以有自己的业务逻辑,或者整个components 或者整个根目录文件夹下面承载
取决自己的设计模式或者开放程度。如果说只是为了做一个项目的话,那就都放在根目录就可以了
如果说要是为了 开源项目,就放到
components
最好。不建议放到自己的文件夹下面
// keyword.js 数据结构队列的应用
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) {
// 数组末尾进行删除 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);
}
-
组件呢,是有生命周期函数的,然后可以 进行调用
attached
代表初始化组件的时候,小程序默认初始化的一个生命周期函数。arrached() { const historyWords = keywordModel.getHistory() this.setData({ historyWords }) }
-
如果想获取输入框 点击标签或者 输入框输入的值;
const value = e.detail.value || e.detail.text;
-
如果想让
input
输入框点击之后 显示文本框的值;// input 有一个 value属性 然后可以使用双向绑定来进行设置input的值 // <input value="{{value}}" /> data: { value: "" } const value = e.detail.value || e.detail.text; // 应该在用户搜索成功之后 进行设置显示 this.setData({ value, })
监听用户滑动到页面底部 从而可以有一个分页加载的功能
- 一种可以使用小程序的
scroll-view
组件 - 一种可以使用 page页面的
onReachBottom
(建议大家优先选择)- 组件监听不到事件的触底效果,所以可以借助 page 页面进行监听,然后传递一个
true
或者false
来表示监听。
- 组件监听不到事件的触底效果,所以可以借助 page 页面进行监听,然后传递一个
import { random } from "../../common.js"
Page({
data: {
more: ''
},
onReachBottom() {
this.setData({
more: random(16)
})
}
})
Component({
properties: {
more: {
type: String, // 属性被赋值之后 如何让自己定义一个函数来加载数据呢?
// observer: function() {} 一种方法 另外一种如下
observer: '_load_more',
},
data: {
// 为loading加一个锁的概念 只有当请求完成了 才可以调用下一次请求
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
文件,如果要定义私有的方法,那应该都定义在文件的最底部。 - 注意避免死锁:
- 如果有网可以进行加载 解锁功能 如果断网了 然后也置为 false 了。所以再次上网之后不会加载了也。
- 特别注意:
- 如果页面中有 该值的参与显示,那么设置的时候 必须要用
this.setData
进行页面渲染
- 如果页面中有 该值的参与显示,那么设置的时候 必须要用
微信获取信息的机制
-
获取用户信息(不需要用户授权,就可以显示 用户昵称和头像)
- 使用小程序的组件
<open-data>
<!--只需要更换 type属性就可以啦 然后可以进行不授权的显示 用户昵称和头像--> <open-data type="userAvatarUrl"></open-data> <!--{overflow: hidden} 这个code配合raduis设置img然后才可以设置成圆形图片的--> <!--这种办法只能显示用户信息。但是如果想获取用户的信息就不是这么简单了-->
- 如果是静默。我们则不需要授权,如果是需要获取,我们就需要用户授权了
// 以前是 直接调用 wx.getUserInfo 来弹窗询问是否进行授权的api // 新版的API button组件是可以进行弹窗的 button组件是个ui 然后让用户主动去点击button
- 使用小程序的组件
<button open-type="getUserInfo" bindgetuserinfo="getUserInfo"></button>
getUserInfo(event) {
console.log(event); // event.detail属性下可以查看到用户相关的所有信息
}
// 每次拿到用户信息 不可能都去clike一下然后获取信息 所以就要使用到 wx.getUserInfo();
onLoad(options) {
// 如何在onLoad函数中 知道 用户是否授权
wx.getUserInfo({
success:data => { // 只有用户授权了 然后调用这个api 的success里面就会打印data
console.log(data);
}
}),
wx.getSeting({ // 这个函数是可以知道用户是否授权了的
success: data => {
if(data.authSetting['scope.userInfo']){
wx.getUserInfo({
success: data => {
console.log(data);
}
})
}
else {
}
}
});
}
- 这里就会有一个 image-button 的一个概念,button包含图片的一个组件,用来实现
分享
获取信息
的作用
<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定义的这个属性其实是我们的一个自定义属性
// 命名规则 子组件定义属性 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;
// 这个是在父组件的 事件监听函数中 打印出来的 自定义的事件
// this.setData({
// userInfo,
// })
}
-
如果你想从一个小程序 跳转到 另外一个小程序里面去,那么这两个小程序必须同时关联同一个公众号。
- 在 服务号或者订阅号 之间是可以做关联设置的。
<!-- target必须设置 app-id也是需要进行配置的(关联的小程序的id) --> <navigator target="miniProgram" app-id="xxxxxx" open-type="navigate"> <image class="vendor" src="xxx.jpg"></image> </navigator>
尽量少在
onload
中 书写代码逻辑。直接this.function
调用即可。
小程序的项目比较小,本身就是一个前端开发者的话 推荐使用 云开发
补充
开发版 体验版 正式版 区别
开发版 是开发者自己的体验开发的一款版本
-
体验版 是上线之前 让产品经理、项目经理、客户、测试工程师进行体验的。还没发布。
小程序体验版是一个刚刚做出来还没完善的版本,是供给开发人员测试用的
-
体验版支持调试模式,正式版本不支持调试模式。
而上线版本就是正式交付给企业对外开发的版本,是一个完善的版本。
通过 __wxConfig.envVersion 能判断用户所在的小程序版本
console.log('envVersion',__wxConfig.envVersion);
envVersion: 'develop', //开发版
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 任务
要运行gulp任务,只需切换到存放
gulpfile.js
文件的目录(windows平台请使用cmd或者Power Shell等工具),然后在命令行中执行gulp
命令就行了,gulp
后面可以加上要执行的任务名,例如gulp task1
,如果没有指定任务名,则会执行任务名为default
的默认任务。
-
-
gulp 的 API 介绍
-
gulp.src()
gulp.src()
方法正是用来获取流的,这个方法来读取你需要操作的文件就行了gulp.src(globs[, options])
globs参数是文件匹配模式(类似正则表达式),用来匹配文件路径(包括文件名),当然这里也可以直接指定某个具体的文件路径。当有多个匹配模式时,该参数可以为一个数组。
options为可选参数。通常情况下我们不需要用到。 -
gulp.dest()
gulp.dest()方法是用来写文件的,其语法为:
gulp.dest(path[,options])
path为写入文件的路径
options为一个可选的参数对象,通常我们不需要用到var gulp = require('gulp'); gulp.src('script/jquery.js') .pipe(gulp.dest('dist/foo.js')); //最终生成的文件路径为 dist/foo.js/jquery.js,而不是dist/foo.js
-