您现在的位置是:网站首页> 小程序设计
vue基本使用
- 小程序设计
- 2021-03-17
- 1193人已阅读
使用变量
html 区域 {{变量}}
<template>
<view>
<view>Message: {{ msg }}</view>
</view></template><script>
export default {
data() {
return {
msg: 'Hello Vue!'
}
}
}</script>
动态地绑定一个或多个属性,或一个组件 prop
到表达式
<!-- 缩写 --> <image :src="imgUrl"></image> <!-- prop 绑定。“prop”必须在 my-component 中声明。--> <my-component :prop="someThing"></my-component> <button v-bind:disabled="isButtonDisabled">Button</button>
v-on 指令,它用于监听 DOM 事件。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>
v-html
更新元素的 innerHTML
。
- 注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。
- 如果试图使用 v-html 组合模板,可以重新考虑是否通过使用组件来替代。
- App端和H5端支持
v-html
,微信小程序会被转为rich-text
,其他端不支持v-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 必须声明为返回一个初始数据对象的函数(注意函数内返回的数据对象不要直接引用函数外的对象);否则页面关闭时,数据不会自动销毁,再次打开该页面时,会显示上次数据。
//正确用法,使用函数返回对象 data() { return { title: 'Hello' } }
Class 与 Style 绑定
可以传给 v-bind:class 一个对象,实现动态地切换 class
<template> <view> <!-- class --> <view class="static" :class="{ active: isActive}">111</view> <view class="static" :class="{ active: isActive, 'text-danger': hasError }">222</view> <!-- style --> <view v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">333</view> </view> </template> <script> export default { data() { return { isActive: true, hasError: false, activeColor:"green", fontSize:50 } } } </script> <style> .static{ color: #2C405A; } .active{ background-color: #007AFF; } .text-danger{ color: #DD524D; } </style>
渲染结果为
<view class="static active"></view>
当 isActive
或者 hasError
变化时,class 列表将相应地更新。例如,如果 hasError
的值为 true
,class 列表将变为 static active text-danger
。
数组语法
可以把一个数组传给 v-bind:class,以应用一个 class 列表。
<template> <view> <!-- class --> <view class="static" :class="[activeClass,errorClass]">111</view> <view class="static" v-bind:class="[isActive ? activeClass : '', errorClass]">222</view><!-- 三元表达式 --> <view class="static" v-bind:class="[{ active: isActive }, errorClass]">333</view> <!-- style --> <view v-bind:style="[{ color: activeColor, fontSize: fontSize + 'px' }]">444</view> </view></template><script> export default { data() { return { isActive: true, activeClass: 'active', errorClass: 'text-danger', activeColor:"green", fontSize:50 } } }</script><style> .static{ font-size:30rpx; } .active{ background-color: #007AFF; } .text-danger{ font-size:60rpx; color:#DD524D; }</style>
注意:以:style=""这样的方式设置px像素值,其值为实际像素,不会被编译器转换。
此外还可以用 computed
方法生成 class
或者 style
字符串,插入到页面中,举例说明:
<template> <!-- 支持 --> <view class="container" :class="computedClassStr"></view> <view class="container" :class="{active: isActive}"></view> <!-- 不支持 --> <view class="container" :class="computedClassObject"></view> </template> <script> export default { data () { return { isActive: true } }, computed: { computedClassStr () { return this.isActive ? 'active' : '' }, computedClassObject () { return { active: this.isActive } } } } </script>
v-if和v-else
v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy
值的时候被渲染。 使用 v-else
指令来表示 v-if 的“else 块”。
<template> <view> <view v-if="seen">现在你看到我了</view> <view v-else>你看不到我了</view> </view> </template> <script> export default { data() { return { seen: true } } } </script>
v-else-if
,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:
<template> <view> <view v-if="type === 'A'"> A </view> <view v-else-if="type === 'B'"> B </view> <view v-else-if="type === 'C'"> C </view> <view v-else> Not A/B/C </view> </view> </template> <script> export default { data() { return { type:'B' } } } </script>
类似于 v-else
,v-else-if
也必须紧跟在带 v-if
或者 v-else-if
的元素之后。
条件渲染分组
因为 v-if
是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 template
元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 template
元素。
<template v-if="seen"> <view>标题</view> <view>内容:现在你看到我了</view>
</template>
v-show
v-show
是一个根据条件展示元素选项的指令 。用法大致和 v-if
一样:
<view v-show="ok">Hello!</view>
不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS
属性的 display
。
注意,v-show 不支持 template 元素,也不支持 v-else。nvue 页面不支持 v-show。
v-if 和 v-show 区别
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多,不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,来控制元素的显示和隐藏。
根据应用场景选择
v-if
有更高的切换开销,如果在运行时条件很少改变,则使用 v-if 较好。v-show
有更高的初始渲染开销。如果需要非常频繁地切换,则使用 v-show 较好。
注意
- 不推荐同时使用
v-if
和v-for
。 - 当
v-if
与v-for
一起使用时,v-for
具有比v-if
更高的优先级。
在 v-for 里使用数组
v-for 指令可以实现基于一个数组来渲染一个列表。
v-for
指令需要使用item in items
形式的特殊语法,其中items
是源数据数组,而item
则是被迭代的数组元素的别名。- 第一个参数
item
则是被迭代的数组元素的别名。 - 第二个参数,即当前项的索引
index
,是可选的。
<template> <view> <view v-for="(item, index) in items"> {{ index }} - {{ item.message }}
</view>
</view>
</template>
<script>
export default {
data() {
return {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
}
}
</script>
在 v-for 里使用对象
你也可以用 v-for 来遍历一个对象的 property
。
- 第一个参数
value
是被迭代的对象元素的属性值。 - 第二个参数为
property
名称 (也就是键名)。 - 第三个参数作为索引。
<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: '2020-04-10'
}
}
}
}
</script>
结果:
0.title: How to do lists in Vue, 1.author: Jane Doe, 2.publishedAt: 2020-04-10
列表渲染分组
类似于 v-if
,你也可以利用带有 v-for
的 template
来循环渲染一段包含多个元素的内容。比如:
<template v-for="item in items"> <view>{{ item.message }}</view> <view class="divider" role="presentation"></view> </template>
key
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input
中的输入内容,switch
的选中状态),需要使用 :key
来指定列表中项目的唯一的标识符。
:key
的值以两种形式提供
- 使用
v-for
循环array
中item
的某个property
,该property
的值需要是列表中唯一的字符串或数字,且不能动态改变。 - 使用
v-for
循环中item
本身,这时需要item
本身是一个唯一的字符串或者数字
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
如不提供 :key,会报一个
warning
, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
示例:
<template> <view> <!-- array 中 item 的某个 property --> <view v-for="(item,index) in objectArray" :key="item.id"> {{index +':'+ item.name}}
</view> <!-- item 本身是一个唯一的字符串或者数字时,可以使用 item 本身 --> <view v-for="(item,index) in stringArray" :key="item"> {{index +':'+ item}}
</view>
</view>
</template>
<script>
export default {
data () {
return {
objectArray:[{
id:0,
name:'li ming'
},{
id:1,
name:'wang peng'
}],
stringArray:['a','b','c']
}
}
}
</script>
注意事项
- 在H5平台 使用 v-for 循环整数时和其他平台存在差异,如
v-for="(item, index) in 10"
中,在H5平台 item 从 1 开始,其他平台 item 从 0 开始,可使用第二个参数 index 来保持一致。 - 在非H5平台 循环对象时不支持第三个参数,如
v-for="(value, name, index) in object"
中,index 参数是不支持的。 - 小程序端数据为差量更新方式,由于小程序不支持删除对象属性,使用的设置值为 null 的方式替代,导致遍历时可能出现不符合预期的情况,需要自行过滤一下值为 null 的数据
在组件上使用 v-for
在自定义组件上,你可以像在任何普通元素上一样使用 v-for
。
<my-component v-for="item in items" :key="item.id"></my-component>
当在组件上使用 v-for 时,key是必须的。
事件处理器
监听事件
可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript
代码。
<template>
<view>
<button v-on:click="counter += 1">Add 1</button>
<text>The button above has been clicked {{ counter }} times.</text>
</view>
</template>
<script>
export default {
data() {
return {
counter:0
}
}
}
</script>
事件处理方法
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript
代码写在 v-on
指令中是不可行的。因此 v-on
还可以接收一个需要调用的方法名称。
示例:
<template> <view> <!-- `greet` 是在下面定义的方法名 --> <button v-on:click="greet">Greet</button> </view> </template> <script> export default { data() { return { name: 'Vue.js' } }, // 在 `methods` 对象中定义方法 methods: { greet(event){ // `event` 是原生 DOM 事件 console.log(event); uni.showToast({ title: 'Hello ' + this.name + '!' }); } } } </script>
内联处理器中的方法
除了直接绑定到一个方法,也可以在内联 JavaScript
语句中调用方法:
<template> <view> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> </view> </template> <script> export default { methods: { say(message) { uni.showToast({ title: message }); } } } </script>
有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event
把它传入方法:
<template> <view> <button v-on:click="warn('Form cannot be submitted yet.', $event)"> Submit </button> </view> </template> <script> export default { methods: { warn(message, event) { // 现在我们可以访问原生事件对象 if (event) { event.preventDefault() } uni.showToast({ title: message }); } } } </script>
事件修饰符
修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
:
v-on 提供了事件修饰符:
.stop
: 各平台均支持, 使用时会阻止事件冒泡,在非 H5 端同时也会阻止事件的默认行为.native
: 监听原生事件,仅在 H5 平台支持.prevent
: 仅在 H5 平台支持.capture
: 仅在 H5 平台支持.self
: 仅在 H5 平台支持.once
: 仅在 H5 平台支持.passive
: 仅在 H5 平台支持
<!-- 阻止单击事件继续传播 --> <view v-on:click.stop="doThis"></view>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self
会阻止所有的点击,而 v-on:click.self.prevent
只会阻止对元素自身的点击。
注意
- 为兼容各端,事件需使用 v-on 或 @ 的方式绑定,请勿使用小程序端的
bind
和catch
进行事件绑定。 - 若需要禁止蒙版下的页面滚动,可使用
@touchmove.stop.prevent="moveHandle"
,moveHandle
可以用来处理touchmove
的事件,也可以是一个空函数。
<view class="mask" @touchmove.stop.prevent="moveHandle"></view>
- 按键修饰符:
uni-app
运行在手机端,没有键盘事件,所以不支持按键修饰符。
事件映射表
// 事件映射表,左侧为 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'
}
表单控件绑定
v-model
你可以用 v-model 指令在表单 input
、textarea
及 select
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model 会忽略所有表单元素的
value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
<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表单组件
建议开发过程中直接使用 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) } } } </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>
计算属性和侦听器
计算属性computed
每一个计算属性都包含一个 getter
和一个 setter
,默认是利用 getter
来读取。所有 getter
和 setter
的 this
上下文自动地绑定为 Vue 实例。
计算属性的 getter
在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<view> {{ message.split('').reverse().join('') }}
</view>
这里是想要显示变量 message
的翻转字符串。当你想要在模板中多包含此处的翻转字符串时,就会更加难以处理。
所以,对于任何复杂逻辑,你都应当使用计算属性。
<template>
<view>
<view>Original message: "{{ message }}"</view>
<view>Computed reversed message: "{{ reversedMessage }}"</view>
</view>
</template>
<script>
export default {
data() {
return {
message: 'Hello'
}
},
computed: {
// 计算属性的 getter
reversedMessage(){
return this.message.split('').reverse().join('')
}
}
}
</script>
结果:
Original message: "Hello" Computed reversed message: "olleH"
你可以像绑定普通 property
一样在模板中绑定计算属性。
Vue 知道 reversedMessage
依赖于 message
,因此当 message
发生改变时,所有依赖 reversedMessage
的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter
函数是没有副作用 (side effect) 的,这使它更易于测试和理解。
计算属性还可以依赖多个 Vue 实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。
计算属性的 setter
在你需要时也可以提供一个 setter
函数, 当手动修改计算属性的值时,就会触发 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>
现在再运行 fullName = 'John Doe'
时,setter
会被调用,firstName
和 lastName
也会相应地被更新。
getter与setter区别
- get:通过设置get方法可以得到fullName的新值。
- set:通过set的方法,设置一个值(newValue)来改变fullName相关联的值,引起fullName重新的计算,相应的页面上fullName也会发生改变成新的内容。
计算属性缓存 vs 方法
我们可以通过在表达式中调用方法来达到同样的效果:
<template> <view> <view>Reversed message: "{{ reversedMessage() }}"</view> </view> </template> <script> export default { data() { return { message: 'Hello' } }, methods: { reversedMessage(){ return this.message.split('').reverse().join('') } } } </script>
可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。
只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:
computed: { now(){ return Date.now() } }
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
计算属性 vs 侦听属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch
。然而,通常更好的做法是使用计算属性而不是命令式的 watch
回调。
export default { data() { return { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' } }, watch: { firstName: function(val) { this.fullName = val + ' ' + this.lastName }, lastName: function(val) { this.fullName = this.firstName + ' ' + val } } }
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
export default { data() { return { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' } }, computed: { fullName(){ return this.firstName + ' ' + this.lastName } } }
侦听器watch
- 类型:{ [key: string]: string | Function | Object | Array }
- 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用
$watch()
,遍历watch
对象的每一个property
。
- 示例:
<template> <view> <input type="text" v-model="word"> </view></template><script> export default { data() { return { word: 'word' } }, watch: { /* 使用watch来响应数据的变化 */ word(newVal, oldVal) { console.log('最新值是:'+newVal,"原来的值是:"+ oldVal); } }, }</script>
示例:
<script> export default { data() { return { a: 1, b: 2, c: 3, d: 4, e: { f: { g: 5 } } } }, watch: { a: function(val, oldVal) { console.log('new: %s, old: %s', val, oldVal) }, // 方法名 b: 'someMethod', // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深 c: { handler: function(val, oldVal) { /* ... */ }, deep: true }, // 该回调将会在侦听开始之后被立即调用 d: { handler: 'someMethod', immediate: true }, // 你可以传入回调数组,它们会被逐一调用 e: [ 'handle1', function handle2(val, oldVal) { /* ... */ }, { handler: function handle3(val, oldVal) { /* ... */ }, /* ... */ } ], // watch vm.e.f's value: {g: 5} 'e.f': function(val, oldVal) { /* ... */ } } }</script>
下一篇:uniapp框架说明