Vue的基础知识(二)

本章将继续和大家分享Vue的一些基础知识。话不多说,下面我们直接上代码:

本文内容大部分摘自Vue的官网 :https://v2.cn.vuejs.org/v2/guide/

一、计算属性

示例如下:

 <!  DOCTYPE html  > 
 <  html  lang  ="en"  > 

 <  head  > 
     <  meta  charset  ="UTF-8"  > 
     <  meta  http-equiv  ="X-UA-Compatible"  content  ="IE=edge"  > 
     <  meta  name  ="viewport"  content  ="width=device-width, initial-scale=1.0"  > 
     <  title  > Vue中的计算属性 </  title  > 
     <  script  src  ="/lib/vue.js"  ></  script  > 
 </  head  > 

 <  body  > 
     <  div  id  ="app"  > 
         <  div  desc  ="计算属性"  > 
             <  p  > Original message: "{{ message }}" </  p  > 
             <  p  > Computed reversed message: "{{ reversedMessage }}" </  p  > 
         </  div  > 
     </  div  > 

     <  script  > 
         var  vm  =   new  Vue({
el:
' #app ' , // 挂载点 data: {
message:
' Hello ' },
computed: {
// 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this .message.split( '' ).reverse().join( '' );
}
},
methods: {
// 普通方法 reversedMessageMethod: function () { /* 1、我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
2、相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
3、我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。
然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
*/ return this .message.split( '' ).reverse().join( '' );
}
}
});
</ script > </ body > </ html >

结果:

 Original message: "Hello"

Computed reversed message: "olleH"

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

 // ...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...

你可以像绑定普通 property 一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

计算属性缓存 vs 方法:我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而, 不同的是计算属性是基于它们的响应式依赖进行缓存的 。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

二、侦听属性

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

示例如下:

 <!  DOCTYPE html  > 
 <  html  lang  ="en"  > 

 <  head  > 
     <  meta  charset  ="UTF-8"  > 
     <  meta  http-equiv  ="X-UA-Compatible"  content  ="IE=edge"  > 
     <  meta  name  ="viewport"  content  ="width=device-width, initial-scale=1.0"  > 
     <  title  > Vue中的侦听器 </  title  > 
     <  script  src  ="/lib/vue.js"  ></  script  > 
     <  script  src  ="/lib/axios.js"  ></  script  > 
     <  script  src  ="/lib/lodash.js"  ></  script  > 
 </  head  > 

 <  body  > 
     <  div  id  ="app"  > 
         <  div  desc  ="侦听属性"  > 
             <  p  >  请输入您的问题:  <  input  v-model  ="question"  > 
             </  p  > 
             <  p  > {{ answer }} </  p  > 
         </  div  > 
     </  div  > 

     <  script  > 
         var  vm  =   new  Vue({
el:
' #app ' , // 挂载点 data: {
question:
'' ,
answer:
' 在您提出问题之前,我不能给您答案! ' },
watch: {
// 如果 `question` 发生改变,这个函数就会运行 question: function (newQuestion, oldQuestion) { var _this = this ;
_this.answer
= ' 正在等待您停止输入... ' _this.debouncedGetAnswer();
}
},
created:
function () { // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。 // 在这个例子中,我们希望限制访问 接口 的频率 // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于 // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识, // 请参考:https://lodash.com/docs#debounce var _this = this ;
_this.debouncedGetAnswer
= _.debounce(_this.getAnswer, 1500 ); // debouncedGetAnswer 方法名可自定义 },
methods: {
getAnswer:
function () { var _this = this ; if (_this.question.indexOf( ' ? ' ) === - 1 ) {
_this.answer
= ' 问题通常包含问号! ' ; return ;
}

_this.answer
= ' 数据获取中... ' ;
axios.get(
' https://autumnfish.cn/api/joke ' )
.then(
function (response) {
_this.answer
= response.data;
})
.
catch ( function (error) {
_this.answer
= ' 请求接口异常: ' + error;
});
}
}
});
</ script > </ body > </ html >

在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

Lodash下载地址 :https://github.com/lodash/lodash/tree/4.17.21

三、Class 与 Style 绑定

示例如下:

 <!  DOCTYPE html  > 
 <  html  lang  ="en"  > 

 <  head  > 
     <  meta  charset  ="UTF-8"  > 
     <  meta  http-equiv  ="X-UA-Compatible"  content  ="IE=edge"  > 
     <  meta  name  ="viewport"  content  ="width=device-width, initial-scale=1.0"  > 
     <  title  > Class与Style绑定 </  title  > 
     <  script  src  ="/lib/vue.js"  ></  script  > 
 </  head  > 

 <  body  > 
     <  div  id  ="app"  > 
         <  div  desc  ="对象语法"  > 
             <!--  active 这个 class 存在与否将取决于数据 property isActive 的 真值。  --> 
             <!--  你可以在对象中传入更多字段来动态切换多个 class。此外,v-bind:class 指令也可以与普通的 class attribute 共存。  --> 
             <!--  当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。  --> 
             <  div  class  ="static"  v-bind:class  ="{ active: isActive, 'text-danger': hasError }"  ></  div  > 
             <!--  绑定的数据对象不必内联定义在模板里  --> 
             <  div  v-bind:class  ="classObject"  ></  div  > 
             <!--  我们也可以在这里绑定一个返回对象的计算属性  --> 
             <  div  v-bind:class  ="classObjectComputed"  ></  div  > 
         </  div  > 

         <  div  desc  ="数组语法"  > 
             <!--  我们可以把一个数组传给 v-bind:class,以应用一个 class 列表  --> 
             <  div  v-bind:class  ="[activeClass, errorClass]"  ></  div  > 
             <!--  如果你也想根据条件切换列表中的 class,可以用三元表达式  --> 
             <!--  这样写将始终添加 errorClass,但是只有在 isActive 是 真 时才添加 activeClass。  --> 
             <  div  v-bind:class  ="[isActive ? activeClass : '', errorClass]"  ></  div  > 
             <!--  不过,当有多个条件 class 时这样写有些繁琐,所以在数组语法中也可以使用对象语法  --> 
             <  div  v-bind:class  ="[{ active: isActive }, errorClass]"  ></  div  > 
         </  div  > 

         <  div  desc  ="绑定内联样式"  > 
             <!--  v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。  --> 
             <!--  CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名  --> 
             <  div  v-bind:style  ="{ color: activeColor, fontSize: fontSize + 'px' }"  ></  div  > 
             <!--  直接绑定到一个样式对象通常更好,这会让模板更清晰  --> 
             <!--  同样的,对象语法常常结合返回对象的计算属性使用  --> 
             <  div  v-bind:style  ="styleObject"  ></  div  > 
             <!--  v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:  --> 
             <  div  v-bind:style  ="[baseStyles, overridingStyles]"  ></  div  > 
         </  div  > 
     </  div  > 

     <  script  > 
         var  vm  =   new  Vue({
el:
' #app ' , // 挂载点 data: {
isActive:
true ,
hasError:
false ,
classObject: {
active:
true , ' text-danger ' : false },
activeClass:
' active ' ,
errorClass:
' text-danger ' ,
activeColor:
' red ' ,
fontSize:
30 ,
styleObject: {
color:
' red ' ,
fontSize:
' 13px ' },
baseStyles: {
color:
' black ' ,
fontSize:
' 13px ' },
overridingStyles: {
' text-align ' : ' center ' }
},
computed: {
classObjectComputed:
function () { return {
active:
this .isActive && ! this .hasError, ' text-danger ' : this .hasError
}
}
}
});
</ script > </ body > </ html >

渲染的结果如下:

 <  div  id  ="app"  > 
     <  div  desc  ="对象语法"  > 
         <  div  class  ="static active"  ></  div  > 
         <  div  class  ="active"  ></  div  > 
         <  div  class  ="active"  ></  div  > 
     </  div  > 
     <  div  desc  ="数组语法"  > 
         <  div  class  ="active text-danger"  ></  div  > 
         <  div  class  ="active text-danger"  ></  div  > 
         <  div  class  ="active text-danger"  ></  div  > 
     </  div  > 
     <  div  desc  ="绑定内联样式"  > 
         <  div  style  ="color: red; font-size: 30px;"  ></  div  > 
         <  div  style  ="color: red; font-size: 13px;"  ></  div  > 
         <  div  style  ="color: black; font-size: 13px; text-align: center;"  ></  div  > 
     </  div  > 
 </  div  > 

四、条件渲染

示例如下:


 <!  DOCTYPE html  > 
< html lang ="en" >

< head >
< meta charset ="UTF-8" >
< meta http-equiv ="X-UA-Compatible" content ="IE=edge" >
< meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
< title > Vue中的条件渲染 </ title >
< script src ="lib/vue.js" ></ script >
</ head >

< body >
< div id ="app" >
< div desc ="条件渲染" >
<!-- v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。 -->
<!-- 可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素。 -->
< template v-if ="loginType === 'username'" >
< label > Username </ label >
< input placeholder ="Enter your username" key ="username-input" >
</ template >
< template v-else-if ="loginType === 'telephone'" >
< label > Telephone </ label >
< input placeholder ="Enter your telephone" key ="telephone-input" >
</ template >
< template v-else >
< label > Email </ label >
< input placeholder ="Enter your email address" key ="email-input" >
</ template >

<!-- v-show 只是简单地切换元素的 CSS property display。 -->
< h1 v-show ="isShow" > Hello! </ h1 >
</ div >
</ div >

< script >
// 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
// 标签: Javascript

添加新评论