Skip to content

页面简介 ​

qinjs 项目中,一个页面就是一个符合 Vue SFC规范 的 vue 文件。

  • 在 qinjs 中,后缀名是 .vue 文件。在 pages.json 的路由注册中不包含页面文件名后缀,同一个页面可以对应2个文件名。重名时优先级如下:

新建页面 ​

qinjs 中的页面,默认保存在工程根目录下的 pages 目录下。

每次新建页面,均需在 pages.json 中配置 pages 列表;未在 pages.json -> pages 中注册的页面, qinjs 会在编译阶段进行忽略。pages.json的完整配置参考:页面配置。

删除页面 ​

删除页面时,需做两件工作:

  • 删除.vue文件
  • 删除pages.json -> pages列表项中的配置

页面改名同理。

pages.json ​

pages.json是工程的页面管理配置文件,包括:页面路由注册、页面参数配置(原生标题栏、下拉刷新...)、首页tabbar等众多功能。

其篇幅较长,另见 pages.json

应用首页 ​

pages.json -> pages配置项中的第一个页面,作为当前工程的首页(启动页)。

json
{
  "pages": [
    {
      "path": "pages/index/index", //名字叫不叫index无所谓,位置在第一个,就是首页
      "style": {
        "navigationBarTitleText": "首页" //页面标题
      }
    },
    {
      "path": "pages/my",
      "style": {
        "navigationBarTitleText": "我的"
      }
    },
  ]
}
{
  "pages": [
    {
      "path": "pages/index/index", //名字叫不叫index无所谓,位置在第一个,就是首页
      "style": {
        "navigationBarTitleText": "首页" //页面标题
      }
    },
    {
      "path": "pages/my",
      "style": {
        "navigationBarTitleText": "我的"
      }
    },
  ]
}

页面内容构成 ​

qinjs 页面基于 vue 规范。一个页面内,有3个根节点标签 <template>、<script>、<style>,分别是模板组件区、脚本区、样式区。

html
<template>
  <view class="content">
    <button @click="buttonClick">{{title}}</button>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        title: "Hello world", // 定义绑定在页面上的data数据
      }
    },
    onLoad() {
      // 页面启动的生命周期,这里编写页面加载时的逻辑
    },
    methods: {
      buttonClick: function () {
        console.log("按钮被点了")
      },
    }
  }
</script>

<style>
  .content {
    width: 750rpx;
    background-color: white;
  }
</style>
<template>
  <view class="content">
    <button @click="buttonClick">{{title}}</button>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        title: "Hello world", // 定义绑定在页面上的data数据
      }
    },
    onLoad() {
      // 页面启动的生命周期,这里编写页面加载时的逻辑
    },
    methods: {
      buttonClick: function () {
        console.log("按钮被点了")
      },
    }
  }
</script>

<style>
  .content {
    width: 750rpx;
    background-color: white;
  }
</style>

template 模板区 ​

template 中文名为模板,它类似 html 的标签。但有 2 个区别:

  1. html 中 script 和 style 是 html 的二级节点。但在 vue 文件中, template 、 script 、 style 这 3 个是平级关系。
  2. html 中写的是web标签,但 vue 的 template 中写的全都是 vue 组件,每个组件支持属性、事件、 vue 指令,还可以绑定 vue 的 data 数据。
html
<template>
  <view>
    <text>标题</text>
  </view>
  <scroll-view>
    
  </scroll-view>
</template>
<template>
  <view>
    <text>标题</text>
  </view>
  <scroll-view>
    
  </scroll-view>
</template>

script 脚本区 ​

script 中编写脚本,可以通过 lang 属性指定脚本语言。

  • 在vue中,默认是js,可以指定ts。
html
<script lang="ts">
</script>
<script lang="ts">
</script>

在 vue 的选项式( option )规范中, script 下包含 export default {} 。(除了选项式,还有组合式)

页面级的代码大多写在 export default {} 中。写在里面的代码,会随着页面关闭而关闭。

export default 外的代码 ​

先来介绍写在export default {}外面的代码,一般有几种情况:

  1. import三方 js/ts 模块
  2. import 非 easycom 的组件(一般组件推荐使用easycom,无需导入注册)
  3. 在 ts 中,对 data 的类型进行 type 定义
  4. 定义作用域更大的变量
html
<script lang="ts">
  const TAB_OFFSET = 1; // 外层静态变量不会跟随页面关闭而回收
  import charts from 'charts.ts'; // 导入外部js/ts模块
  import swiperPage from 'swiper-page.vue'; //导入非easycom的组件
  type GroupType = {
    id : number,
    title : string
  } // 在ts中,为下面data数据的 groupList 定义类型
  export default {
    components: {
        swiperPage
    }, // 注册非easycom组件
    data() {
      return {
        groupList: [
          { id: 1, title: "第一组" },
          { id: 2, title: "第二组" },
        ] as GroupType[], // 为数据groupList定义ts类型
      }
    },
    onLoad() {},
    methods: {}
  }
</script>
<script lang="ts">
  const TAB_OFFSET = 1; // 外层静态变量不会跟随页面关闭而回收
  import charts from 'charts.ts'; // 导入外部js/ts模块
  import swiperPage from 'swiper-page.vue'; //导入非easycom的组件
  type GroupType = {
    id : number,
    title : string
  } // 在ts中,为下面data数据的 groupList 定义类型
  export default {
    components: {
        swiperPage
    }, // 注册非easycom组件
    data() {
      return {
        groupList: [
          { id: 1, title: "第一组" },
          { id: 2, title: "第二组" },
        ] as GroupType[], // 为数据groupList定义ts类型
      }
    },
    onLoad() {},
    methods: {}
  }
</script>

注意

开发者应谨慎编写 export default {} 外面的代码,这里的代码有 2 个注意事项:

  1. 在应用启动时执行。也就是这里的代码执行时机是应用启动、而不是页面加载。如果这里的代码写的太复杂,会影响应用启动速度和内存占用。
  2. 不跟随页面关闭而回收。在外层的静态变量不会跟随页面关闭而回收。

export default 里的代码 ​

export default {} 里的内容,是页面的主要逻辑代码。包括几部分:

  1. data:template 模板中需要使用的数据。具体另见
  2. 页面生命周期:如页面加载、隐藏、关闭,具体见下
  3. methods 方法,如按钮点击、屏幕滚动

如下页面代码的逻辑是:

  1. 在 data 中定义了 title ,初始值是"点我"
  2. 在页面中放置了一个 button 组件,按钮文字区使用 模板写法,里面写 title ,把data里的 title 绑定到按钮的文字区,即按钮的初始文字是"点我"
  3. 按钮的点击事件 @click ,指向了methods里的一个方法 buttonClick ,点击按钮即触发这个方法的执行
  4. buttonClick 方法里通过 this.title 的方式,访问 data 数据,并重新赋值为"被点了"。由于 vue 中 data 和界面是双向绑定,修改 data 中的 title 后,因为按钮文字绑定了 title ,会自动更新按钮的文字。

整体效果就是,刚开始按钮文字是"点我",点一下后按钮文字变成了"被点了"

html
<template>
  <view>
    <button @click="buttonClick">{{title}}</button>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        title: "点我", // 定义绑定在页面上的data数据
        // 多个data在这里继续定义。逗号分隔
      }
    },
    onLoad() {
      // 页面启动的生命周期,这里编写页面加载时的逻辑
    },
    // 多个页面生命周期监听,在这里继续写。逗号分隔
    methods: {
      buttonClick: function () {
        this.title = "被点了"
      },
      // 多个方法,在这里继续写。逗号分隔
    }
  }
</script>
<template>
  <view>
    <button @click="buttonClick">{{title}}</button>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        title: "点我", // 定义绑定在页面上的data数据
        // 多个data在这里继续定义。逗号分隔
      }
    },
    onLoad() {
      // 页面启动的生命周期,这里编写页面加载时的逻辑
    },
    // 多个页面生命周期监听,在这里继续写。逗号分隔
    methods: {
      buttonClick: function () {
        this.title = "被点了"
      },
      // 多个方法,在这里继续写。逗号分隔
    }
  }
</script>

本章节为页面代码介绍,并非 vue 教程,了解 data 数据需详见

style 样式区 ​

style 的写法与 web 的 css 基本相同。

详见css文档

页面生命周期 ​

qinjs 页面除支持 Vue 组件生命周期外还支持下方页面生命周期函数,可使用 Vue3 组合式 API。

函数名说明平台差异说明最低版本
onInit监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad百度小程序3.1.0+
onLoad监听页面加载,该钩子被调用时,响应式数据、计算属性、方法、侦听器、props、slots 已设置完成,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例。
onShow监听页面显示,页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
onReady监听页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用,注意如果渲染速度快,会在页面进入动画完成前触发
onHide监听页面隐藏
onUnload监听页面卸载
onResize监听窗口尺寸变化App、微信小程序、快手小程序
onPullDownRefresh监听用户下拉动作,一般用于下拉刷新,参考示例
onReachBottom页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项
onTabItemTap点击 tab 时触发,参数为Object,具体见下方注意事项微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、快手小程序、京东小程序
onShareAppMessage用户点击右上角分享微信小程序、QQ小程序、支付宝小程序、抖音小程序、飞书小程序、快手小程序、京东小程序
onPageScroll监听页面滚动,参数为Objectnvue不支持
onNavigationBarButtonTap监听原生标题栏按钮点击事件,参数为ObjectH5
onBackPress监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 qin.navigateBack ;详见app、H5、支付宝小程序
onNavigationBarSearchInputChanged监听原生标题栏搜索输入框输入内容变化事件H51.6.0
onNavigationBarSearchInputConfirmed监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发。H51.6.0
onNavigationBarSearchInputClicked监听原生标题栏搜索输入框点击事件(pages.json 中的 searchInput 配置 disabled 为 true 时才会触发)H51.6.0
onShareTimeline监听用户点击右上角转发到朋友圈微信小程序2.8.1+
onAddToFavorites监听用户点击右上角收藏微信小程序、QQ小程序2.8.1+

页面加载时序介绍 ​

接下来我们介绍onLoad 、 onReady 、 onShow 的先后关系,页面加载的详细流程。

  1. qinjs 框架,首先根据 pages.json 的配置,创建页面

所以原生导航栏是最快显示的。页面背景色也应该在这里配置。

2.根据页面 template 里的组件,创建 dom 。

这里的 dom 创建仅包含第一批处理的静态dom。对于通过 js/ts 更新 data 然后通过 v-for 再创建的列表数据,不在第一批处理。

注意

一个页面静态 dom 元素过多,会影响页面加载速度。

  1. 触发onLoad

此时页面还未显示,没有开始进入的转场动画,页面dom还不存在。

所以这里不能直接操作dom(可以修改 data ,因为 vue 框架会等待 dom 准备后再更新界面)。

onLoad 比较适合的操作是:接受上页的参数,联网取数据,更新 data 。

手机都是多核的, qin.request ,在子线程运行,不会干扰UI线程的入场动画,并行处理可以更快的拿到数据、渲染界面。

但 onLoad 里不适合进行大量同步耗时运算,因为此时转场动画还没开始。

  1. 转场动画开始

新页面开始进入的转场动画,动画默认耗时 300ms ,可以在路由 API 中调节时长。

  1. 页面 onReady

第2步创建 dom 是虚拟 dom , dom 创建后需要经历一段时间, UI 层才能完成了页面上真实元素的创建,即触发了 onReady 。

onReady 后,页面元素就可以自由操作了,比如 ref 获取节点。同时首批界面也渲染了。

注意: onReady 和转场动画开始、结束之间,没有必然的先后顺序,完全取决于 dom 的数量和复杂度。

如果元素排版和渲染够快,转场动画刚开始就渲染好了;

大多情况下,转场动画走几格就看到了首批渲染内容;

如果元素排版和渲染过慢,转场动画结束都没有内容,就会造成白屏。

联网进程从 onLoad 起就在异步获取数据更新data,如果服务器速度够快,第二批数据也可能在转场动画结束前渲染。

  1. 转场动画结束

再次强调,5和6的先后顺序不一定,取决于首批dom渲染的速度。

页面加载常见问题 ​

了解了页面加载时序原理,我们就知道如何避免页面加载常见的问题:

  • 优化白屏的方法:
  1. 页面 dom 太多,注意有的组件写的不好,会拖累整体页面。
  2. 联网不要在 onReady 里,那样太慢了,在 onLoad 里早点联网
  3. 在 pages.json 里配置原生导航栏和背景色
  4. 有的页面 template 内容非常少,整页就是一个需要联网加载的列表,这会造成虽然首批 dom 飞快渲染了,但页面其实还是白的,联网后才能显示字和图。 此时需要在 template 里做一些简单占位组件,比如 loading 组件、骨架屏,让本地先显示一些内容。
  • 卡住动画不启动的原因:
  1. 页面 dom 太多,注意有的组件写的不好,会拖累整体页面。
  2. onLoad 里执行了耗时的同步计算

onShow和onHide ​

注意页面显示,是一个会重复触发的事件。

a 页面刚进入时,会触发 a 页面的 onShow 。

当 a 跳转到 b 页面时, a 会触发 onHide ,而 b 会触发 onShow 。

但当 b 被关闭时, b 会触发 onUnload ,此时 a 再次显示出现,会再次触发 onShow 。

在 tabbar 页面(指 pages.json 里配置的 tabbar ),不同 tab 页面互相切换时,会触发各自的 onShow 和 onHide 。

onInit ​

注意

  • 仅百度小程序基础库 3.260 以上支持 onInit 生命周期
  • 其他版本或平台可以同时使用 onLoad 生命周期进行兼容,注意避免重复执行相同逻辑
  • 不依赖页面传参的逻辑可以直接使用 created 生命周期替代

onReachBottom ​

可在 pages.json 里定义具体页面底部的触发距离 onReachBottomDistance ,

比如设为 50 ,那么滚动页面到距离底部 50px 时,就会触发 onReachBottom 事件。

如使用 scroll-view 导致页面没有滚动,则触底事件不会被触发。 scroll-view 滚动到底部的事件请参考 scroll-view 的文档。

onPageScroll ​

参数说明

属性类型说明
scrollTopNumber页面在垂直方向已滚动的距离(单位px)
js
onPageScroll : function(e) { //nvue暂不支持滚动监听,可用bindingx代替
  console.log("滚动距离为:" + e.scrollTop);
},
onPageScroll : function(e) { //nvue暂不支持滚动监听,可用bindingx代替
  console.log("滚动距离为:" + e.scrollTop);
},

注意

  • onPageScroll 里不要写交互复杂的 js ,比如频繁修改页面。因为这个生命周期是在渲染层触发的,在非 h5 端, js 是在逻辑层执行的,两层之间通信是有损耗的。如果在滚动过程中,频发触发两层之间的数据交换,可能会造成卡顿。
  • 在 webview 渲染时,比如微信小程序、H5 中,也可以使用 wxs 监听滚动,参考;
  • 如果想实现滚动时标题栏透明渐变,在 H5 下,可在 pages.json 中配置 titleNView 下的 type 为 transparent ,参考。
  • 如果需要滚动吸顶固定某些元素,推荐使用 css 的粘性布局,参考插件市场。插件市场也有其他js实现的吸顶插件,但性能不佳,需要时可自行搜索。

onBackPress ​

参数说明

属性类型说明
fromString触发返回行为的来源:'backbutton'——左上角导航栏按钮及安卓返回键;'navigateBack'——qin.navigateBack() 方法。支付宝小程序端不支持返回此字段
js
export default {
  onBackPress(options) {
    console.log('from:' + options.from)
  }
}
export default {
  onBackPress(options) {
    console.log('from:' + options.from)
  }
}

注意

  • onBackPress 上不可使用 async ,会导致无法阻止默认返回
  • 支付宝小程序只有真机可以监听到非 navigateBack 引发的返回事件(使用小程序开发工具时不会触发 onBackPress ),不可以阻止默认返回行为

详细说明及使用:onBackPress 详解

onTabItemTap ​

参数说明

属性类型说明
indexNumber被点击 tabItem 的序号,从0开始
pagePathString被点击 tabItem 的页面路径
textString被点击 tabItem 的按钮文字
js
onTabItemTap : function(e) {
  console.log(e);
  // e的返回格式为json对象: {"index":0,"text":"首页","pagePath":"pages/index/index"}
},
onTabItemTap : function(e) {
  console.log(e);
  // e的返回格式为json对象: {"index":0,"text":"首页","pagePath":"pages/index/index"}
},

注意

  • onTabItemTap 常用于点击当前 tabitem ,滚动或刷新当前页面。如果是点击不同的 tabitem ,一定会触发页面切换。
  • 支付宝小程序平台 onTabItemTap 表现为点击非当前 tabitem 后触发,因此不能用于实现点击返回顶部这种操作

onNavigationBarButtonTap ​

参数说明

属性类型说明
indexNumber原生标题栏按钮数组的下标
js
onNavigationBarButtonTap : function (e) {
  console.log(e);
  // e的返回格式为json对象:{"text":"测试","index":0}
}
onNavigationBarButtonTap : function (e) {
  console.log(e);
  // e的返回格式为json对象:{"text":"测试","index":0}
}

组件生命周期 ​

qinjs 组件支持的生命周期,与 vue 标准组件的生命周期相同。这里没有页面级的 onLoad 等生命周期:

函数名说明平台差异说明最低版本
beforeCreate在实例初始化之前被调用。详见
created在实例创建完成后被立即调用。详见
beforeMount在挂载开始之前被调用。详见
mounted挂载到实例上去之后调用。详见 注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用$nextTickVue官方文档
beforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。详见仅H5平台支持
updated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。详见仅H5平台支持
beforeunmount实例销毁之前调用。在这一步,实例仍然完全可用。详见
unmountedVue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。详见

页面调用接口 ​

getApp() ​

getApp() 函数用于获取当前应用实例,一般用于获取 globalData 。也可通过应用实例调用 App.vue methods 中定义的方法。

实例

js
const app = getApp()
console.log(app.globalData)
app.doSomething() // 调用 App.vue methods 中的 doSomething 方法
const app = getApp()
console.log(app.globalData)
app.doSomething() // 调用 App.vue methods 中的 doSomething 方法

注意

  • 不要在定义于 App() 内的函数中,或调用 App 前调用 getApp() ,可以通过 this.$scope 获取对应的app实例
  • 通过 getApp() 获取实例之后,不要私自调用生命周期函数。

getCurrentPages() ​

getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,数组中的元素为页面实例,第一个元素为首页,最后一个元素为当前页面。如果获取页面的参数可使用 qin.getPageOpts()

每个页面实例的方法属性列表:

方法描述平台说明
page.route获取当前页面的路由 

注意

getCurrentPages()仅用于展示页面栈的情况,请勿修改页面栈,以免造成页面状态错误。
页面关闭时,对应页面实例会在页面栈中删除。

注意

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 不能在首页 onReady 之前进行页面跳转。

页面通讯 ​

qin.$emit(eventName,OBJECT) ​

触发全局的自定义事件。附加参数都会传给监听器回调。

属性类型描述
eventNameString事件名
OBJECTObject触发事件携带的附加参数

代码示例

js
  qin.$emit('update',{msg:'页面更新'})
  qin.$emit('update',{msg:'页面更新'})

qin.$on(eventName,callback) ​

监听全局的自定义事件。事件可以由 qin.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。

属性类型描述
eventNameString事件名
callbackFunction事件的回调函数

代码示例

js
  qin.$on('update',function(data){
    console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
  })
  qin.$on('update',function(data){
    console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
  })

qin.$once(eventName,callback) ​

监听全局的自定义事件。事件可以由 qin.$emit 触发,但是只触发一次,在第一次触发之后移除监听器。

属性类型描述
eventNameString事件名
callbackFunction事件的回调函数

代码示例

js
  qin.$once('update',function(data){
    console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
  })
  qin.$once('update',function(data){
    console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
  })

qin.$off([eventName, callback]) ​

移除全局自定义事件监听器。

属性类型描述
eventNameArray<String>事件名
callbackFunction事件的回调函数

注意

  • 如果没有提供参数,则移除所有的事件监听器;
  • 如果只提供了事件,则移除该事件所有的监听器;
  • 如果同时提供了事件与回调,则只移除这个回调的监听器;
  • 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;

代码示例

$emit、$on、$off常用于跨页面、跨组件通讯,这里为了方便演示放在同一个页面

html
  <template>
    <view class="content">
      <view class="data">
        <text>{{val}}</text>
      </view>
      <button type="primary" @click="comunicationOff">结束监听</button>
    </view>
  </template>

  <script>
    export default {
      data() {
        return {
          val: 0
        }
      },
      onLoad() {
        setInterval(()=>{
          qin.$emit('add', {
            data: 2
          })
        },1000)
        qin.$on('add', this.add)
      },
      methods: {
        comunicationOff() {
          qin.$off('add', this.add)
        },
        add(e) {
          this.val += e.data
        }
      }
    }
  </script>

  <style>
    .content {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
    }

    .data {
      text-align: center;
      line-height: 40px;
      margin-top: 40px;
    }

    button {
      width: 200px;
      margin: 20px 0;
    }
  </style>
  <template>
    <view class="content">
      <view class="data">
        <text>{{val}}</text>
      </view>
      <button type="primary" @click="comunicationOff">结束监听</button>
    </view>
  </template>

  <script>
    export default {
      data() {
        return {
          val: 0
        }
      },
      onLoad() {
        setInterval(()=>{
          qin.$emit('add', {
            data: 2
          })
        },1000)
        qin.$on('add', this.add)
      },
      methods: {
        comunicationOff() {
          qin.$off('add', this.add)
        },
        add(e) {
          this.val += e.data
        }
      }
    }
  </script>

  <style>
    .content {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
    }

    .data {
      text-align: center;
      line-height: 40px;
      margin-top: 40px;
    }

    button {
      width: 200px;
      margin: 20px 0;
    }
  </style>

注意

  • qin.$emit、 qin.$on 、 qin.$once 、qin.$off 触发的事件都是 App 全局级别的,跨任意组件,页面,vue 等
  • 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 qin.$on 注册监听,onUnload 里边 qin.$off 移除,或者一次性的事件,直接使用 qin.$once 监听

扩展阅读:

路由 ​

qinjs 页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径及页面样式。类似小程序在 app.json 中配置页面路由一样。所以 qinjs 的路由用法与 Vue Router 不同,如仍希望采用 Vue Router 方式管理路由,可在插件市场搜索 Vue-Router。

路由跳转 ​

qinjs 有两种页面路由跳转方式:调用API跳转。

注意

页面返回时会自动关闭 loading 及 toast, modal 及 actionSheet 不会自动关闭。
页面关闭时,只是销毁了页面实例,未完成的网络请求、计时器等副作用需开发者自行处理。

页面栈 ​

框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:

路由方式页面栈表现触发时机
初始化新页面入栈qinjs 打开的第一个页面
打开新页面新页面入栈调用 API   qin.push
页面重定向当前页面出栈,新页面入栈调用 API   qin.replace
页面返回页面不断出栈,直到目标返回页调用 API  qin.navigateBack
Tab 切换页面全部出栈,只留下新的 Tab 页面调用 API  qin.switchTab
重加载页面全部出栈,只留下新的页面调用 API  qin.reLaunch

页面代码规范介绍 ​

qinjs 支持在 template 模板中嵌套 <template/> 和 <block/>,用来进行 列表渲染 和 条件渲染。

<template/> 和 <block/> 并不是一个组件,它们仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

<block/> 在不同的平台表现存在一定差异,推荐统一使用 <template/>。

代码示例

html
<template>
  <view>
    <template v-if="test">
      <view>test 为 true 时显示</view>
    </template>
    <template v-else>
      <view>test 为 false 时显示</view>
    </template>
  </view>
</template>
<template>
  <view>
    <template v-if="test">
      <view>test 为 true 时显示</view>
    </template>
    <template v-else>
      <view>test 为 false 时显示</view>
    </template>
  </view>
</template>
html
<template>
  <view>
    <block v-for="(item,index) in list" :key="index">
      <view>{{item}} - {{index}}</view>
    </block>
  </view>
</template>
<template>
  <view>
    <block v-for="(item,index) in list" :key="index">
      <view>{{item}} - {{index}}</view>
    </block>
  </view>
</template>