简体中文
vue.js 是流行的js框架,它提供了:
但 vue.js 并不支持web之外的其他平台,也不支持uts。
uni-app x 为vue开发者提供了跨平台的解决方案。
uni-app x 中,web平台内置了vue.js,其他平台为 DCloud 参考vue规范提供的兼容实现。
在 uni-app x 中,页面和组件的文件后缀名均为 *.uvue
。u 即 uni 的意思。
页面与组件均符合vue的单文件组件规范,只不过页面需要在pages.json中注册且多了一批生命周期和API。
在非web平台,uvue 尽可能拉齐了vue.js的功能,但仍有些不常用的功能暂未提供,需注意查看相关文档的兼容性。同时 uvue 也新增了 easycom 等技术,简化组件的使用。
hello uvue 是非常重要的vue示例,演示了各种vue功能的应用。
HBuilderX/uni-app x,会跟踪vue版本的升级,版本映射表如下
HBuilderX | vue版本 |
---|---|
4.14 | 3.4 |
一个 uvue 页面/组件,符合vue单文件组件规范(SFC),有3个根节点标签:
<template>
<script>
<style>
注意html中,根节点是<html>
,<script>
和<style>
是子节点。但在uvue中,这3个节点都是一级节点。
vue的script分组合式和选项式,下面先提供1个基于组合式的数据绑定和修改的示例,点击按钮,修改按钮的文字。
<template>
<view class="content">
<!-- button的文字绑定了响应式变量title,点击事件绑定了buttonClick方法-->
<button @click="buttonClick">{{title}}</button>
</view>
</template>
<script setup>
let title = ref("Hello world") //定义一个响应式变量title,默认赋值为Hello world
const buttonClick = () => {
title.value = "按钮被点了" //对响应式变量title的.value属性赋值,界面上button的文字会自动同步修改
}
/*
function buttonClick() { // 简单的function方式也可以用,但在不同平台的作用域有细微差异。所以一般推荐上方箭头函数的写法。
title.value = "按钮被点了"
}
*/
onLoad(() => {
// 页面启动的生命周期,这里编写页面加载时的逻辑
})
</script>
<style>
.content {
width: 750rpx;
}
</style>
可以看出整体和html还是很接近的。但响应式变量和绑定机制,可以免去写大量的dom操作代码,让开发更高效轻松。
基于选项式的示例,下面章节会提供。
template中文名为模板
,它类似html的标签。但有2个区别:
script
和 style
是 html 的二级节点。但在 uvue 文件中,template
、script
、style
这3个是平级关系。template
中写的全都是 vue 组件(包括内置基础组件、自定义前端uvue组件、uts原生插件组件),每个组件支持属性、事件、vue 指令,还可以绑定 vue 的 data 数据。组件,即component,是vue中非常重要的概念,或者说现代开发框架都离不开组件概念。
我们知道js逻辑可以封装为函数或类库。而对于页面上可视的元素,则可以将ui、样式、逻辑一起封装为组件。详见uvue组件规范
在 uni-app x 中, <view>
是最基本的视图容器组件,<text>
则是文字组件,<button>
是按钮组件。这些都是内置组件
一个页面或组件只能有一个template标签,template下面可以有多个二级节点,即多个根组件。如下:
<template>
<view>
<text v-if="titleShow" :style="'color:' + titleColor">{{title}}</text> <!-- text组件的text绑定了响应式变量title、v-if指令绑定了titleShow、style绑定了titleColor-->
</view>
<scroll-view >
<button @click="buttonClick_changeText" type="primary">修改文字内容</button>
<button @click="buttonClick_showHide">点击让文字组件显示或消失</button>
<button @click="buttonClick_changeColor">修改文字颜色</button>
</scroll-view>
</template>
<script setup>
let title = ref("Hello world") //定义一个响应式变量title,默认赋值为hello world
const buttonClick_changeText = () => {
title.value = "新文字内容" //对响应式变量title的.value属性赋值,界面上文字会自动同步修改
}
let titleShow = ref(true) //决定标题文字是否显示
const buttonClick_showHide = () => {
titleShow.value = !titleShow.value //对响应式变量的.value属性赋值,界面上文字组件的v-if指令绑定了titleShow,所以会动态显示消失
}
let titleColor = ref("black")
const buttonClick_changeColor = () => {
titleColor.value = "red" //对响应式变量的.value属性赋值,界面上文字组件的style属性绑定了titleColor,所以会变色
}
</script>
组件有很多概念,属性、事件、指令。如果还不了解相关概念,请参阅 组件介绍
script中编写逻辑代码。
uvue中只能有一个script标签。
script标签的属性如下:
注意: 所有 vue
公开的 API
都是不需要 import
的, uni-app x
会自动引入。
比如不需要写:
import { ref } from 'vue';
vue最初只有选项式API,从vue3起,新增了组合式API。
所谓选项式,就是把script的内容在export default {} 中约定不同的对象,在其中通过多个选项的对象来定义data、method和生命周期。
框定好这些后,开发者就在这个框框里分别写自己的业务逻辑。
这种方式易用但不够灵活。所以在vue3以前,部分开发者会认为react更难学、更灵活,所以更高级。
vue3新增的组合式API,是纯编程的,解决了选项式不够灵活的问题。同时维持了易学的特点。让vue变的即容易、又灵活。
uni-app x不再支持vue2。在vue3中,组合式和选项式是可以混合使用的。
但注意不支持一个页面/组件有2个script,分别写选项式和组合式。
开发者可以根据自己的喜好选择2种写法,但还有几个差别需要注意:
export default {}
外,这些都是应用级全局的,略微影响性能。见下组合式 API,也称 Composition API,或 setup函数。
组合式提供了更灵活自由、更简洁的编程方式,通过代码而不是通过规范约定死的选项来定义data、method和生命周期。
如下页面代码的逻辑是:
title
,初始值是"Hello world"。{{}}
模板写法,里面写响应式变量title
,那么title
的值就会绑定到按钮的文字区,即按钮的初始文字是"Hello world"@click
,指向了一个方法buttonClick
,点击按钮即触发这个方法的执行<template>
<view>
<!-- button的文字绑定了响应式变量title,点击事件绑定了buttonClick方法-->
<button @click="buttonClick">{{title}}</button>
</view>
</template>
<script setup>
let title = ref("Hello world") //定义一个响应式变量title,默认赋值为Hello world
const buttonClick = () => {
title.value = "按钮被点了" //对响应式变量title的.value属性赋值,界面上button的文字会自动同步修改
}
/*
function buttonClick() { // 简单的function方式也可以用,但在不同平台的作用域有细微差异。所以一般推荐上方箭头函数的写法。
title.value = "按钮被点了"
}
*/
onLoad(() => {
// 页面启动的生命周期,这里编写页面加载时的逻辑
})
</script>
选项式 API,也称 Option API,指在script中写export default {}
,在其中通过多个选项的对象来定义data、method和生命周期。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。
以下代码的逻辑与上一章节组合式API的示例相同,只是写法改成了选项式写法。
<template>
<view>
<button @click="buttonClick">{{title}}</button>
</view>
</template>
<script>
export default {
data() {
return {
title: "Hello world", // 定义绑定在页面上的data数据
}
},
onLoad() {
// 页面启动的生命周期,这里编写页面加载时的逻辑
},
methods: {
buttonClick: function () {
this.title= "按钮被点了" //对响应式变量title赋值,界面上button的文字会自动同步修改
},
}
}
</script>
对比之前组合式的、相同业务逻辑的代码,可以看到两种方式的差异:
上述代码比较简单,如果涉及到响应式变量的类型定义,那么会更明显的感受到组合式的灵活和简洁。
export default
外的代码选项式主代码在export default {}
里。但既然有export default {}
里的代码,那么就有 export default {}
外面的代码。
写在外面一般有几种情况:
<script>
const TAB_OFFSET = 1; // 外层静态变量不会跟随页面关闭而回收
import charts from 'charts.uts'; // 导入外部js/ts模块
import swiperPage from 'swiper-page.uvue'; //导入非easycom的组件
type GroupType = {
id : number,
title : string
} // 在uts中,为下面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个注意事项:
export default {}
外的代码写的太复杂,会影响应用启动速度,占用更多内存。beforeDestroy
或 destroyed
生命周期进行处理。style的写法与web的css基本相同。但在App端,由于并非webview渲染,支持的css有限。详见
本章节重点讲解uvue下样式的使用注意事项。
一个页面/组件允许有多个style标签。
style通过lang属性,可以支持less、scss、stylus等css预处理语言。
名称 | 类型 | 默认值 | 兼容性 | 描述 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
lang | string | - | ||||||||||||||
| ||||||||||||||||
scoped | Any | - | - | |||||||||||||
module | Any | - | - |
Web | Android | iOS |
---|---|---|
4.0 | 3.9 | 4.11 |
uni-app x
支持绑定 UTSJSONObject
和 Map
类型数据。Map
的性能高于 UTSJSONObject
数据类型。从 uni-app x 4.01
起,Web平台也支持了 Map
类型绑定。如下示例中,给view组件的style和class分别绑定了2个data,就可以通过在逻辑代码里修改data而实现动态修改样式。
<template>
<view>
<view :style="styleMap" :class="classMap"></view>
</view>
</template>
<script lang="uts">
export default {
data() {
return {
styleMap: new Map<string, string>([['border', '2px solid red'], ['background-color', 'green']]),
classMap: new Map<string, boolean>([['w-100', true], ['h-100', true], ['rounded', false]])
}
}
}
</script>
<style lang="scss" scoped>
.w-100 {
width: 100px;
}
.h-100 {
height: 100px;
}
.rounded {
border-radius: 8px;
}
</style>
处于
scoped
样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用:deep()
这个伪类:
<style scoped>
.a :deep(.b) {
/* ... */
}
</style>
App | Web |
---|---|
x | 4.13+ |
单文件组件的 <style>
标签支持使用 v-bind
CSS 函数将 CSS 的值链接到动态的组件状态:
<template>
<text class="text">hello</text>
</template>
<script>
export default {
data() {
return {
color: 'red'
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
这个语法同样也适用于 <script setup>
,且支持 UTS 表达式 (需要用引号包裹起来):
<script setup>
const theme = {
color: 'red'
}
</script>
<template>
<text class="view">hello</text>
</template>
<style scoped>
.text {
color: v-bind('theme.color');
}
</style>