Vue (Vue2)基础知识梳理

插值操作

1. mustache 语法

首先定义一些变量:

const app = new Vue({
    el:"app",
    data:{
        meseage:"hello world",
        firstName:"zhang",
        lastName:"heng"
        count:100
    }
})

然后我们可以在html标签中使用{{}}形式来将变量展现出来

 <div id="app">
        <h2>{{message}}</h2>
        <h2>{{message}},one</h2>
        <h2>{{firstName}} {{lastName}}</h2>
 </div>

也可以在语法中写一些简单的表达式

 <h2>{{firstName + " "+lastName}}</h2> 
 <h2>{{content*2}}</h2>

2.常见标签指令的使用

v-once

该指令后面没有表达式,用于执行一次性的插值.当数据再次改变时,插值处的数据是不会更新的

 <h2 v-once>{{message}}</h2>

v-html

双大括号会将数据解释为普通的文本节点, 如果你要是渲染html代码,就使用该指令

    <div id="app">
        <h2>{{url}}</h2>
        <h2 v-html="url"></h2>
    </div>

``` ```js const app = new Vue({ el: '#app', data: {
---------------------------------------------------

        message: 'helloWorld!',
        url:'<a href="https://www.baidu.com">百度一下</a>'
    }
    });

渲染出来的效果如下:
image-20210625202357120

DOM节点如下:
image-20210625202431766

注意:这个指令使用需要注意安全问题,不要随意渲染任何html代码,有可能会导致XSS攻击,所以要对可信的html代码进行渲染

v-text

该标签和插值语法一样,但是不够灵活

v-pre

用于跳过这个元素和它子元素的编译过程

<h2 v-pre>{{message}}</h2>

结果:
image-20210625203013692

v-bind

Mustache 语法不能作用在 HTML attribute 上,v-bind可以动态改变属性值

1. 基本使用

动态修改img标签的src属性值

 <img v-bind:src="imgURL" alt="">

v-bind的简写形式

 <img :src="imgURL" alt="">

此时imgURL就是一个变量

2. 动态绑定class属性

对象形式

 <h2 class="类名" v-bind:class="{类名1:Boolean,类名2:Boolean}">{{message}}</h2>

可以通过这样的方式来绑定class属性,若对应类名的布尔值为true,则就添加这个类名,反之则去除,同时你用了这种动态绑定的方式绑定的类名,也可以用最原始的方式来再添加类名,然后这些类名会合并赋予给标签

数组形式

 <h2 :class="['类名1','类名2']">{{message}}</h2>

数组项也可以是变量

<h2 :class="[active,line]">{{message}}</h2>
    const app = new Vue({    
      el: '#app',    
      data: {          
      message: 'helloWorld!',
      active:'aaa',        
      line:'bbb'
       }    
    });

3. 动态绑定style属性

对象语法

 <!-- 写法: <h2 :style="{属性名:属性值}">{{message}}</h2> -->    
<h2 :style="{fontSize:'50px'}">{{message}}</h2>
<h2 :style="{fontSize:finalSize}">{{message}}</h2>
<h2 :style="{fontSize:finalSize1+'px',color:finalColor}">{{message}}</h2><h2 :style="getStyle()">{{message}}</h2>

数组语法
单独把一个对象当成数组每一个数组对象

<h2 :style="[baseStyle,baseStyle1]">{{message}}</h2>
        const app = new Vue({            
          el: '#app',            
          data: {                
          message: 'helloWorld!',                
          baseStyle: {                    
          backgroundColor: 'red'                
          },                
          baseStyle1: {                    
          fontSize: '100px'               
          }           
        }       
       });

计算属性

模板中虽然可以写表达式,但是在模板中写大量的表达式会显得很混乱,对于一些复杂的逻辑都该使用计算属性

1. 基本使用

    <div id="app">        <h2>{{fullName}}</h2>    </div>
    const app = new Vue({    
      el: '#app',    
      data: {         
      message: 'helloWorld!',        
      firstName:'阿尔托莉雅',        
      lastName:'潘德拉贡'       
      },       
  //计算属性       
      computed: {           
        fullName:function(){            
          return this.firstName+" "+this.lastName;           
         }      
   }    
});

2. 复杂操作

 <div id="app"><h2>总价格:{{totalPrice}}</h2></div>
    const app = new Vue({    
      el: '#app',    
      data: {         
      message: 'helloWorld!',        
      books:[
            {id:110,name:'xxx从入门到放弃',price:19},               
             {id:111,name:'yyy从入门到放弃',price:29},               
                {id:112,name:'zzz从入门到放弃',price:39},              
                    {id:113,name:'java从入门到放弃',price:49} 
     ]   
   },    
  computed: {        
      totalPrice:function(){              
      let result=0;             
      for(let i=0;i<this.books.length;i++) {                
        result+=this.books[i].price;            
          }              
        return result;         
     }   
  },  
 });

这里我们使用方法也可以实现,但是计算属性有缓存机制,是基于响应式的缓存机制,如果相关响应式依赖没有发生改变,计算属性是会利用缓存,多次访问只会返回之前的结果,而方法则是访问一次就会执行一次,比较消耗性能

3. 计算属性的getter和setter

之前我们的写法是一种简写方式

      computed: {          
        fullName:function(){           
        return this.firstName+" "+this.lastName;        
     }     
   } 

完整写法如下:

     fullName:{               
     //set方法就是监视fullName的值,当fullName发生改变时会自动回调set方法,当然你也可以在set方法里设置修改 
    fullName的值              
 //可以给set方法设置一个参数来引入修改值,从而修改fullName               
 //一般set是不设置的所以就不写             
    set:function(newValue){                
    //return '123';                
    const names=newValue.split(' ');                
    this.firstName=names[0];                 
    this.lastName=names[1];            
  },              
//使用fullName这个属性本质上就是调用get这个方法,所以就可以使用上便的简写方式,而且也可以解释为啥fullName不用加(),而使用方法是需要加()的             
 get:function(){                  
//return 'abc';                  
   return this.firstName+" "+this.lastName;               
    }     
   }    
  }

侦听器

计算属性可以做到的watch都能做到反之不行,当然能用计算属性就用计算属性,watch中可以执行任何逻辑,如函数节流,Ajax异步获取数据,操作DOM等

基本使用

watch: {    
// 如果 `question` 发生改变,这个函数就会运行,函数有两个参数,变量改变后的值,变量改变前的值

  question: function (newQuestion, oldQuestion) {      
  this.answer = 'Waiting for you to stop typing...'      
  this.debouncedGetAnswer()   
 },
//如果你要单独监听对象中的某个属性也可这样写
"info.name":function(new, old) {//...}   

深度侦听
此时可以将要侦听的对象设置成对象形式,就可以设置一些其他的选项了

watch:{
  info:{
    handler(new, old) {
    //...
    },
    deep:true,//是否开启深度监听
    immediate:true//是否立即调用一次
  }
}

$watch

  //通过以下形式使用
  const unwatch = this.$watch("info", 
    function(new, old) {}, 
    {//option
      deep:true, 
    }
)
//$watch函数返回一个函数,调用该函数可以取消监听
unwatch();

如果我们要侦听对象数组中某一个对象的属性变化,可以使用一个组件,将数组的每一项传入渲染出来的组件中,在组件中去侦听对象的属性改变,而不是在父组件中通过deep侦听。

动态渲染

1. 条件渲染

v-if

用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

<h1 v-if="true">Vue is awesome!</h1>

当然也有 v-else , 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

<div v-if="Math.random() > 0.5">  Now you see me</div><div v-else>  Now you don't</div>

v-show

v-if 用法一样,区别就是 v-show 仅仅只是给dom节点修改display属性,而 v-if 是删除和重新渲染dom节点,v-if的开销较大,所以一般频繁显示的dom推荐使用 v-show

2. 列表渲染

v-for

用于遍历数组,生成列表

<ul id="example-1">  <li v-for="item in items" :key="item.message">    {{ item.message }}  </li></ul>
const example1 = new Vue({ 
   el: '#example-1', 
   data: {   
   items: [     
    { message: 'Foo' },      
    { message: 'Bar' }   
  ]  
 }
})

v-for 作用域中我们可以访问父级所有的属性值, v-for 可以指定第二个参数就是当前项的索引

v-for 中的key作用 key作用

事件绑定

1. 绑定到原生DOM元素上

通过v-on 标签监听 DOM 事件,并且绑定一个方法,在事件触发时执行

 <button v-on:click="handleButton1">原生DOM中</button> 
 <!--语法糖--> 
 <button @click="handleButton1">原生DOM中</button>
export default {   
 name:'',    
 data () {        
  return {}    
},   
 methods: {     
   handleButton1(){           
     console.log("原生dom事件");     
   } 
 },
}

vue会把默认事件对象作为参数传入方法,如果需要手动手动获取浏览器的event对象,可以使用 $event

2. 绑定到组件上

我们引入一个组件,并为其绑定一个事件

<btn @click="handleButton2" />

btn.vue组件

<template>   
 <div>     
 <button>组件中的dom</button>   
 </div>
</template>
<script type="text/ecmascript-6">
export default {    
  name:'',    
  data () {      
    return {}   
 },   
 methods: {},
}
</script>

直接在组件上绑定点击是不会触发的,有两种方式可以

  1. 使用修饰符.native 在一个组件的根元素上直接监听一个原生事件。
<btn @click.native="handleButton2" />
  1. 在组件内部绑定一个事件,然后通过$emit方式 定义一个自定义事件,让父组件来执行相应逻辑
   <template>    
     <div>      
       <button @click="handleChildBtn">组件中的dom</button>   
     </div>
   </template>
<script type="text/ecmascript-6">
export default {    
  name:'',    
   data () {      
    return {}   
},  
 methods: {     
   handleChildBtn(e){       
   console.log("点击");     
   this.$emit("click", e);  
    } 
   },
  }
   </script>

父组件:

<btn @click="handleButton2" />

一般组件的点击事件可以通过第二种实现,保证父组件来处理逻辑

过滤器

用于一些常用的文本格式化

<!-- 在双花括号中 -->{{ message | capitalize }}<!-- 在 `v-bind` 中 --><div v-bind:id="rawId | formatId"></div>

在组建的选项中定义局部过滤器

filters: {  
  capitalize: function (value) {   
   if (!value) return ''    
  value = value.toString()    
  return value.charAt(0).toUpperCase() + value.slice(1) 
 }
}

定义全局的过滤器

import Vue from 'vue'
Vue.filter('capitalize', function (value) {  
  if (!value) return ''  
  value = value.toString()  
  return value.charAt(0).toUpperCase() + value.slice(1)
})

数据双向绑定

1. 基本使用

使用v-model指令进行数据绑定

<input type="text" v-model="message">{{message}}
 const app = new Vue({    
    el: '#app',    
    data: {       
    message: 'helloWorld!'    
  }  
});

输入框修改, 会同步修改message的值 同理修改message也会修改输入框的值

2. 和其他表单控件使用

textarea

<textarea v-model="message" placeholder="add multiple lines"></textarea>

radio

radio 原来是需要name属性来保证选项互斥,使用v-model后就不需要了

<input type="radio" id="one" value="One" v-model="picked">  
<label for="one">One</label>  
<br>  
<input type="radio" id="two" value="Two" v-model="picked">  
<label for="two">Two</label>  
<br>  
<span>Picked: {{ picked }}</span>

checkbox

单个复选框绑定布尔值

<label for="license">      
<input type="checkbox" id="license" v-model="isAgree" />同意协议    
</label>    
<h2>你选择的是:{{ isAgree }}</h2>

多个复选框需要绑定数组

    <!--多选框-->    
<input type="checkbox" value="篮球" v-model="hobbies" />篮球    
<input type="checkbox" value="足球" v-model="hobbies" />足球    
<input type="checkbox" value="排球" v-model="hobbies" />排球    
<h2>你的爱好:{{ hobbies }}</h2>
data() {    
    return {      
    isAgree:true,      
    hobbies:[]    
  };  
},

select

默认单选

    <select name="abc" id="" v-model="fruit" >      
        <option value="苹果" >苹果</option>      
        <option value="香蕉" >香蕉</option>      
        <option value="榴莲" >榴莲</option>      
        <option value="梨子" >梨子</option>    
    </select>    
    <h2>你选了个{{fruit}}</h2>

select 标签中添加 multiple 属性即可单选,需要ctrl键配合,fruit将展示为数组

3. v-model基本原理

以input文本框为例, v-model可以看作以下代码的简写

<input type="text" v-bind:value="message" v-on:input="message=$event.target.value">

总之v-model就是语法糖

4. v-model 在组件中使用

vue2的v-model在vue3中有改动
父组件:

<childCpn v-model="propsData" /> 

默认相当于:

<childCpn :value="propsData" @input="propsData=$event" />

子组件:

<input type="text" :value="value" @input="$emit('input', $event.target.value)">
 props:['value']

注意事项:组件props要改成 value$emit事件要声明成 input

如果我们组件有多个数据需要双向绑定的话可以使用.sync修饰符, 因为v-model只能在一个组件标签中出现一个

 <childCpn :otherData.sync="otherData" />{{otherData}}

该修饰符也是一种语法糖,实际写法如下:

 @update:属性名="userInfo.name = $event" :属性名="userInfo.name"

子组件:

 <div @click="$emit('update:otherData', otherData+1)">得到{{otherData}}</div>

这里注意子组件$emit 发出的事件要根据该形式来编写,另外也不要直接修改props中的otherData,把改动传到父组件来修改是最好的,否则会出现警告

插槽

1. 基本使用

父组件引入子组件:

<childCpn> 我是插槽中的内容 </childCpn>

子组件:

<template>    
  <div>     
    <div>你好</div>     
    <slot></slot>    
  </div>
</template>

父组件引用的子组件中的文字内容就会替换子组件中的slot标签,插槽内可以包含任何模板代码,包括 HTML,

注意:父组件里面向子组件传递插槽内容的作用域也是父组件,不能访问子组件中的内容,总之父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的,还可以给子组件中的slot指定默认内容,如果父组件没有传递插槽内容给子组件们,会默认显示

2. 具名插槽

有时我们需要多个插槽

<div class="container">  
    <header>    
    <!-- 我们希望把页头放这里 -->  
    </header>  
    <main>    
    <!-- 我们希望把主要内容放这里 -->  
    </main>  
    <footer>    
    <!-- 我们希望把页脚放这里 -->  
    </footer>
</div>

slot有个属性name, 不带name属性的插槽也会有个隐含的name值为default

<template>    
    <div class="">      
        <div>你好</div>     
        <slot></slot>     
        <slot name="first"></slot>     
        <slot name="second"></slot>    
    </div>
</template>

父组件使用方式:

    <childCpn>      
        我是插槽中的内容      
        <template v-slot:first>        
            <div>我是第一</div>      
        </template>      
        <template v-slot:second>        
            <div>饿哦是第二</div>      
        </template>    
    </childCpn>

现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot<template> 中的内容都会被视为默认插槽的内容。

3. 作用域插槽

我们需要父组件能够访问到子组件中的内容

子组件:

<slot name="first" :value="value"></slot>

类似props的方式将value 所谓slot 的一个属性

父组件:

<template v-slot:first="slotProps">        
    <div>我是第一{{slotProps.value}}</div>
</template>

父组件将传递过来的props对象保存在我们自己命名的slotProps中,我们可取任意,当然也可以使用es6的解构语法省去取名了

      <template v-slot:first="{value}">        
        <div>我是第一{{value}}</div>      
      </template>
Last modification:July 20, 2021
如果觉得我的文章对你有用,请随意赞赏