uni-app一套代码多个平台运行,算是懒人和小团队的福音。
官网:https://uniapp.dcloud.io
vue是它的主要语言,之前对vue了解不多。既然新的开始,就从新版3开始学习。
vue官方文档等待以后再看,直接看uni的。
不同于现在html结构,它的结构变成这样(vue单文件组件规范)
<template>
<view>
注意必须有一个view,且只能有一个根view。所有内容写在这个view下面。
</view>
</template>
<script>
export default {
}
</script>
<style>
</style>
template是网页部份; script是脚本部份; style是样式部份。好处是减少了文件管理的复杂,对于洁癖的我比较有好感。
外部文件引用
<script>
var util = require('../util.js'); // 引用文件
var formatedTime = util.formatTime(play); // 引用文件中的方法
</script>
在util.js中
function formatTime(time) {
return time;//这里没写逻辑
}
module.exports = {
formatTime: formatTime
}
这与微信小程序差不多。
css外部引用也有变化
<style>
@import "./common/uni.css";
.uni-hello-text{
color:#7A7E83;
}
</style>
js有所变化,已经有点象前后端的感觉了,即前端使用变量,后端来控制变量。
<template>
<view>
<text>{{textvalue}}</text><!-- 这里演示了组件值的绑定 -->
<button :type="buttontype" @click="changetextvalue()">修改为789</button><!-- 这里演示了属性和事件的绑定 -->
</view>
</template>
<script>
export default {
data() {
return {
textvalue:"123",
buttontype:"primary"
};
},
onLoad() {
this.textvalue="456"//这里修改textvalue的值,其实123都来不及显示就变成了456
},
methods: {
changetextvalue() {
this.textvalue="789"//这里修改textvalue的值,页面自动刷新为789
}
}
}
</script>
插值
最常见的文本插值
<template>
<view>
<view>Message: {{ msg }}</view>
</view>
</template>
<script>
export default {
data() {
return {
msg: 'Hello Vue!'
}
}
}
</script>
JavaScript表达式
<template>
<view>
<view>{{ number + 1 }}</view>
<view>{{ ok ? 'YES' : 'NO' }}</view>
<!-- 把一个字符串分割成字符串数组,颠倒其元素的顺序,把数组中的所有元素放入一个字符串 -->
<view>{{ message.split('').reverse().join('') }}</view>
</view>
</template>
<script>
export default {
data() {
return {
number:1,
ok:true,
message: 'Hello Vue!'
}
}
}
</script>
直接在{{}}中进行计算和函数运行
<template>
<view>
<view v-for="(item,index) in 10">
<!-- 通过%运算符求余数,实现隔行换色的效果 -->
<view :class="'list-' + index%2">{{index%2}}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return { }
}
}
</script>
<style>
.list-0{
background-color: #aaaaff;
}
.list-1{
background-color: #ffaa7f;
}
</style>
在双引号中也能进行运算?
指令
v-bind 动态绑定一个或多个属性,缩写为:
<!-- 完整语法 -->
<image v-bind:src="imgUrl"></image>
<!-- 缩写 -->
<image :src="imgUrl"></image>
<button v-bind:disabled="isButtonDisabled">Button</button>
v-on 用于监听事件,缩写为@
<!-- 完整语法 -->
<view v-on:click="doSomething">点击</view>
<!-- 缩写 -->
<view @click="doSomething">点击</view>
v-once 只渲染一次
<!-- 单个元素 -->
<view v-once>This will never change: {{msg}}</view>
<!-- 有子元素 -->
<view v-once>
<text>comment</text>
<text>{{msg}}</text>
</view>
但看说明不支持h5和微信小程序
v-html 内容按html来支持
<template>
<view>
<view v-html="rawHtml"></view>
</view>
</template>
<script>
export default {
data() {
return {
rawHtml: '<div style="text-align:center;background-color: #007AFF;"><div >我是内容</div><img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/d8590190-4f28-11eb-b680-7980c8a877b8.png"/></div>'
}
}
}
</script>
data
//正确用法,使用函数返回对象
data() {
return {
title: 'Hello'
}
}
//错误写法,会导致再次打开页面时,显示上次数据
data: {
title: 'Hello'
}
//错误写法,同样会导致多个组件实例对象数据相互影响
const obj = {
title: 'Hello'
}
data() {
return {
obj
}
}
Class 与 Style 绑定
:class 是 v-bind:class 的简写。可以与普通的 class 共存。
<view class="static" :class="{ active: isActive}">hello uni-app</view>
<view class="static" :class="{ active: isActive, 'text-danger': hasError }">hello uni-app</view>
这里通过判断isActive和hasError是否为真,添加class。
数组语法,也就是同时使用多个变量所对应的样式
<template>
<view>
<view :class="[activeClass,errorClass]">hello uni-app</view>
</view>
</template>
<script>
export default {
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
}
</script>
<style>
.active{
background-color: #007AFF;
}
.text-danger{
font-size:60rpx;
color:#DD524D;
}
</style>
渲染的结果为:
以下class通过computed中的函数计算返回,这样就更强大了,还避免前端复杂性。
<template>
<view>
<view class="container" :class="computedClassStr">hello uni-app</view>
<view class="container" :class="{active: isActive}">hello uni-app</view>
</view>
</template>
<script>
export default {
data() {
return {
isActive: true
}
},
computed: {
computedClassStr() {
return this.isActive ? 'active' : ''
}
}
}
</script>
<style>
.active {
background-color: #007AFF;
font-size:30px;
}
</style>
绑定内联样式
<template>
<view :style="{ color: activeColor, fontSize: fontSize + 'px' }">hello uni-app</view>
</template>
<script>
export default {
data() {
return {
activeColor: 'red',
fontSize: 30
}
}
}
</script>
上面这个示例将变量引入了style,但很不直观。
<template>
<view :style="styleObject">hello uni-app</view>
</template>
<script>
export default {
data() {
return {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
}
}
</script>
这个示例就直接将脚本中变量包含的样式给了style。
同样,也可以用数组将多个样式应用到同一个元素
<view :style="[baseStyles, overridingStyles]">hello uni-app</view>
<script>
export default {
data() {
return {
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
}
}
</script>
多重值,用于不同浏览器环境下,匹配可以支持的值
<view :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></view>
条件渲染
v-if v-else v-else-if
<template>
<view>
<view v-if="seen">现在你看到我了</view>
<view v-else>你看不到我了</view>
</view>
</template>
<script>
export default {
data() {
return {
seen: true
}
}
}
</script>
v-show 只是简单的显示与不显示,但都会渲染。即只是display属性的控制。
列表渲染
v-for
<template>
<view>
<view v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</view>
</view>
</template>
<script>
export default {
data() {
return {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
}
}
</script>
它也可以用来遍历json对象
<template>
<view>
<view v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</view>
</view>
</template>
<script>
export default {
data() {
return {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2021-05-10'
}
}
}
}
</script>
结果为
0.title: How to do lists in Vue,
1.author: Jane Doe,
2.publishedAt: 2021-05-10
事件处理
多事件处理
<template>
<view>
<!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
<button @click="one($event), two($event)">
Submit
</button>
</view>
</template>
<script>
export default {
methods: {
one(event) {
// first handler logic...
console.log("event1: ",event);
},
two(event) {
// second handler logic...
console.log("event2: ",event);
}
}
}
</script>
事件修饰符
.stop 阻止冒泡
... 还有几个仅h5支持
<view @click.stop="doThis"></view>
事件映射表
左侧为 WEB 事件,右侧为 uni-app
对应事件
click: 'tap',
touchstart: 'touchstart',
touchmove: 'touchmove',
touchcancel: 'touchcancel',
touchend: 'touchend',
tap: 'tap',
longtap: 'longtap', //推荐使用longpress代替
input: 'input',
change: 'change',
submit: 'submit',
blur: 'blur',
focus: 'focus',
reset: 'reset',
confirm: 'confirm',
columnchange: 'columnchange',
linechange: 'linechange',
error: 'error',
scrolltoupper: 'scrolltoupper',
scrolltolower: 'scrolltolower',
scroll: 'scroll'
表单输入绑定
<template>
<view>
<input v-model="message" placeholder="edit me">
<text>Message is: {{ message }}</text>
</view>
</template>
<script>
export default {
data() {
return {
message:""
}
}
}
</script>
uni-app表单组件
H5 的 select 标签用 picker 组件进行代替
<template>
<view>
<picker @change="bindPickerChange" :value="index" :range="array">
<view class="picker">
当前选择:{{array[index]}}
</view>
</picker>
</view>
</template>
<script>
export default {
data() {
return {
index: 0,
array: ['A', 'B', 'C']
}
},
methods: {
bindPickerChange(e) {
console.log(e)
this.index = e.detail.value
}
}
}
</script>
表单元素 radio 用 radio-group 组件进行代替
<template>
<view>
<radio-group class="radio-group" @change="radioChange">
<label class="radio" v-for="(item, index) in items" :key="item.name">
<radio :value="item.name" :checked="item.checked" /> {{item.value}}
</label>
</radio-group>
</view>
</template>
<script>
export default {
data() {
return {
items: [{
name: 'USA',
value: '美国'
},
{
name: 'CHN',
value: '中国',
checked: 'true'
},
{
name: 'BRA',
value: '巴西'
},
{
name: 'JPN',
value: '日本'
},
{
name: 'ENG',
value: '英国'
},
{
name: 'TUR',
value: '法国'
}
]
}
},
methods: {
radioChange(e) {
console.log('radio发生change事件,携带value值为:', e.target.value)
}
}
}
</script>
计算属性的 setter
<template>
<view>
<view>{{ fullName }}</view>
</view>
</template>
<script>
export default {
data() {
return {
firstName: 'Foo',
lastName: 'Bar'
}
},
computed: {
fullName: {
// getter
get(){
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue){
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
}
</script>
侦听器watch
当你有一些数据需要随着其它数据变动而变动时,就可以使用Watch来监听他们之间的变化。
<template>
<view>
<input type="number" v-model="a" style="border: red solid 1px;" />
<input type="number" v-model="b" style="border: red solid 1px;" />
<view>总和:{{sum}}</view>
<button type="default" @click="add">求和</button>
</view>
</template>
<script>
export default {
data() {
return {
a:1,
b:1,
sum: ""
}
},
watch: {
/* 使用watch来响应数据的变化,第一个参数为newVal新值,第二个参数oldVal为旧值*/
a: function(newVal, oldVal) {
console.log("a--newVal: ", newVal, "a--oldVal: ",oldVal);
},
b: function(newVal, oldVal) {
console.log("b--newVal: ", newVal, "b--oldVal: ",oldVal);
}
},
methods: {
add() {
this.sum = parseInt(this.a) + parseInt(this.b)
}
}
}
</script>
在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调:
<template>
<view>
<input type="number" v-model="a" style="border: red solid 1px;" />
<input type="number" v-model="b" style="border: red solid 1px;" />
<view>总和:{{sum}}</view>
<button type="default" @click="add">求和</button>
</view>
</template>
<script>
export default {
data() {
return {
a:1,
b:1,
sum: ""
}
},
watch: {
a: {
handler(newVal, oldVal) {
console.log("a------: ", newVal, oldVal);
},
immediate: true//初始化绑定时就会执行handler方法
},
b: {
handler(newVal, oldVal) {
console.log("b------: ", newVal, oldVal);
},
immediate: true//初始化绑定时就会执行handler方法
}
},
methods: {
add() {
this.sum = parseInt(this.a) + parseInt(this.b)
}
}
}
</script>
为了发现对象内部值的变化,可以在选项参数中指定 deep: true 。深度监听一个对象整体的变化(即监听对象所有属性值的变化)
<template>
<view>
<input type="number" v-model="obj.a" style="border: red solid 1px;" />
<input type="number" v-model="obj.b" style="border: red solid 1px;" />
<view>总和:{{sum}}</view>
<button type="default" @click="add">求和</button>
</view>
</template>
<script>
export default {
data() {
return {
obj: {
a: 1,
b: 1,
},
sum:""
}
},
watch: {
obj: {
handler(newVal, oldVal) {
console.log('obj-newVal:' + JSON.stringify(newVal), 'obj-oldVal:' + JSON.stringify(oldVal), );
},
deep: true//对象中任一属性值发生变化,都会触发handler方法
}
},
methods: {
add() {
this.sum = parseInt(this.obj.a) + parseInt(this.obj.b)
}
}
}
</script>
如果不想监听 obj 中其他值,只想监听 obj.a 的值的变化,可以写成字符串形式监听。
export default {
data() {
return {
obj: {
a: 1,
b: 1,
}
}
},
watch: {
"obj.a": {//监听obj对象中的单个属性值的变化
handler(newVal, oldVal) {
console.log('obj-newVal:' + newVal, 'obj-oldVal:' + oldVal);
}
}
}
}