Vue(读音/vju/,类似于view)是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。
致谢
在传统开发中,用原生的JavaScriptDOM操作函数对DOM进行频繁操作的时候,浏览器要不停的渲染新的DOM树,导致页面看起来非常卡顿。
vue是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和DOM,这样大大加快了访问速度和提升用户体验。
vue的优势:
vue3相比vue2的优势:
如果你了解html、js,那么本章节将让你快速了解uni-app和它们的差异。
而在这个util.js里,要把之前的function封装为模块(module)的方法并导出(exports)。只有被导出的方法和属性才能被外部调用,不导出的属于模块内部函数和变量。这是es6的模块规范。
functionformatTime(time){returntime;//这里没写逻辑}module.exports={formatTime:formatTime}当然还有一些高级的用法,比如在导出时可以重命名
//直接使用js模块的属性。在hellouni-app有示例vardateUtils=require('../../../common/util.js').dateUtils;//将js导入并重命名为echarts,然后使用echarts.来继续执行方法。在hellouni-app有示例import*asechartsfrom'/components/echarts/echarts.simple.min.js';css外部文件导入。全局样式,在根目录下的app.vue里写入,每个页面都会加载app.vue里的样式。
以前是html标签,比如
那么标签和组件有什么区别,不都是用尖括号包围起来一段英文吗?
相比Web平台,Vue.js在uni-app中使用差异主要集中在两个方面:
uni-app项目对vue3.0的支持版本情况如下:
注意事项
在底层的实现上,Vue将模板编译成虚拟DOM渲染函数。结合响应性系统,Vue能够智能地计算出最少需要重新渲染多少组件,并把DOM操作次数减到最少。
数据绑定最常见的形式就是文本插值:
迄今为止,在我们的模板中,我们一直都只绑定简单的property键值。但实际上,对于所有的数据绑定,Vue.js都提供了完全的JavaScript表达式支持。
示例一
错误示例
你不应该在模板表达式中试图访问用户定义的全局变量。
指令是带有v-前缀的特殊属性。
动态地绑定一个或多个属性,v-bind缩写为‘:’,可以用于响应式地更新HTMLattribute:
如果isButtonDisabled的值是null或undefined,则disabledattribute甚至不会被包含在渲染出来的button元素中。
v-on指令,它用于监听DOM事件。v-on缩写为‘@’,下文简称为@事件
和前端框架中的理解不同,客户端里要实现复用的逻辑,会标记模板节点的状态,添加了v-once能保证节点只渲染一次,但是并不一定能优化渲染性能,反而可能会拖慢客户端复用节点时的比对效率。
我们可以传给:class(v-bind:class的简写)一个对象,实现动态地切换class。
也可以在对象中传入更多字段来动态切换多个class。此外,v-bind:class指令也可以与普通的class共存。
数组语法
可以把一个数组传给v-bind:class,以应用一个class列表。
在JavaScript中,truthy(真值)指的是在布尔值上下文中,转换后的值为真的值。所有值都是真值,除非它们被定义为假值(即除false、0、""、null、undefined和NaN以外皆为真值)。
不过,当有多个条件class时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
此外还可以用计算属性computed方法生成class或者style字符串,插入到页面中,举例说明:
:style的对象语法十分直观——看着非常像CSS,但其实是一个JavaScript对象。CSSproperty名可以用驼峰式(camelCase)或短横线分隔(kebab-case,记得用引号括起来)来命名:
:style的数组语法可以将多个样式对象应用到同一个元素上:
多重值
可以为style绑定中的property提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
v-if指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回truthy值的时候被渲染。使用v-else指令来表示v-if的“else块”。v-else元素必须紧跟在带v-if或者v-else-if的元素的后面,否则它将不会被识别。
因为v-if是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?
此时可以把一个template元素当做不可见的包裹元素,并在上面使用v-if。最终的渲染结果将不包含template元素。
注意,v-show不支持template元素,也不支持v-else。nvue页面不支持v-show。
v-if是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换,来控制元素的显示和隐藏。
根据应用场景选择
注意
v-for指令可以实现基于一个数组来渲染一个列表。
0.title:HowtodolistsinVue,1.author:JaneDoe,2.publishedAt:2021-05-10在遍历对象时,会按Object.keys()的结果遍历,但是不能保证它在不同JavaScript引擎下的结果都一致。
类似于v-if,你也可以利用带有v-for的template来循环渲染一段包含多个元素的内容。比如:
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如:表单输入值)的列表渲染输出。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一keyattribute:
不要使用对象或数组之类的非基本类型值作为v-for的key。请用字符串或数值类型的值。
示例:
不推荐在同一元素上使用v-if和v-for
当它们处于同一节点,v-if的优先级比v-for更高,这意味着v-if将没有权限访问v-for里的变量:
用法为v-on:click="methodName"或使用快捷方式@click="methodName"(uni-app里一般都使用@缩写方式)
指令的值,字符串里直接写js。比如下面的counter+=1就是一段js。
@事件(v-on)提供了事件修饰符:
在下面的示例中,输入框通过v-model绑定了message,用户在输入框里输入内容时,这个内容会实时赋值给message。当然在代码里为message赋值也会实时同步到界面上input里。这就是双向绑定。
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如,有一个嵌套数组对象:
data(){return{author:{name:'JohnDoe',books:['Vue2-AdvancedGuide','Vue3-BasicGuide','Vue4-TheMystery']}}}我们想根据author是否已经有一些书来显示不同的消息,可以使用模板内的表达式
所以,对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。
使用计算属性的例子
尝试更改应用程序data中books数组的值,你将看到publishedBooksMessage如何相应地更改。
计算属性还可以依赖多个Vue实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。
计算属性默认只有getter,不过在需要时你也可以提供一个setter,当手动修改计算属性的值时,就会触发setter函数,执行一些自定义的操作。
我们可以通过在表达式中调用方法来达到同样的效果:
这也同样意味着下面的计算属性将不再更新,因为Date.now()不是响应式依赖:
computed:{now(){returnDate.now()}}相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
我们为什么需要缓存?
假设我们有一个性能开销比较大的计算属性list,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于list。如果没有缓存,我们将不可避免的多次执行list的getter!如果你不希望有缓存,请用method来替代。
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么Vue通过watch选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
当你有一些数据需要随着其它数据变动而变动时,就可以使用Watch来监听他们之间的变化。
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue实例将会在实例化时调用$watch(),遍历watch对象的每一个property。
在选项参数中指定immediate:true将立即以表达式的当前值触发回调:
watch方法默认就是handler,而当immediate:true时,就会先执行handler方法。
exportdefault{data(){return{firstName:'Foo',lastName:'Bar',fullName:'FooBar'}},watch:{firstName:function(val){this.fullName=val+''+this.lastName},lastName:function(val){this.fullName=this.firstName+''+val}}}