wxmp_note3

  • 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是没有效果的 
          然后手动 添加 &nbsp 来进行换行... 
          因为 &nbsp 的方法,需要在 text 标签上配备属性 decode="{{true}}"
          return text.replace(reg, '\n&nbsp&nbsp&nbsp&nbsp'); 这样添加一下就可以了-->
    
    <!--或者就不需要在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来表示监听。
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
      
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,692评论 0 3
  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,446评论 0 13
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,358评论 0 17
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,743评论 0 38
  • 2018年4月6日晚上,我和孩子玩跳一跳的游戏,是现实生活中的跳远游戏吧。在垫子上跳,垫子有四块,跳到最后一块上为...
    我心我愿秀阅读 130评论 1 2