3_vue基础语法

1. 准备空项目

拷贝上一节写好的 工程文件到新的项目目录下,按照目录结构存放这些文件。

  • package.json
  • webpack.config.json
  • index.tpl
  • src/main.js
  • src/components/App.vue

后面所有编写的代码都会针对 App.vue文件来进行编辑。 组织好以后,打开命令行工具,执行 cnpm i 安装已经在package.json文件中声明的包文件到 node_modules 文件夹中
在这里插入图片描述
src/componetns/App.vue文件内容,

<template>
    <div>
        
    </div>
</template>
<script>
    export default {
        data() {
            return {
               
            }
        }
    }
</script>
<style scoped>
</style>

src/main.js文件内容

import Vue from 'vue/dist/vue.js'
import App from './components/App.vue'
Vue.component("App",App)
new Vue({
  el: '#app',
  template: '<App />',
})

index.tpl 文件内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue入门</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

2. Vue框架如何处理 template

Vue模板中代码都是符合 HTML规范的,但是在Vue的底层实现上Vue 将模板编译成虚拟 DOM 渲染函数。也就是说template中看起来像DOM元素的标签会被Vue编译成虚拟DOM对象,然后Vue会把这些虚拟DOM渲染成真实的DOM交给浏览器。

所以应该正确看待tmplate中的HTML代码,它们实际上是会被Vue处理的虚拟DOM,只不过看起来像HTML。

2.1 数据绑定

Vue中的数据绑定就是将 Vue中 的data,methods等与模板中的虚拟DOM进行绑定。模板中无非就是在两个地方需要进行绑定:

  • 文本
  • 标签属性

绑定就是将Vue模型中的对象绑定到 标签属性和标签里面的文本上。

2.2 文本绑定

使用 {{ JavaScript表达式 }} 的语法, 前面一直在使用这种方式, 这种语法只能绑定标签文本内容的值,不能用在标签的属性上,要想在标签属性上使用绑定,则应该使用 Vue指令进行绑定。 {{ }} 输出的时候会对字符串进行原样输出。 如果要输出一些HTML标签字符串在页面上显示,就不能用 {{ }}的方式,需要用到 指令(Directives) v-html 来输出

在这种绑定中Vue完全支持JavaScript表达式,如:(来源于官方文档 https://cn.vuejs.org/v2/guide/syntax.html)

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>

2.3 标签属性绑定

比如要将data中的变量绑定到 div的id属性上,此时需要用到 v-bind 指令,如果要为标签绑定事件处理函数,则需要用到v-on指令。

下面的例子中为div标签绑定了id属性和 click事件,当点击div之后执行函数,渲染一段html文本到div上,浏览器会解析HTML代码

src/components/App.vue

<template>
  <div>
    <div v-bind:id="idShowText">
      <!-- 这个div中显示文本信息, 原样输出文本内容 -->
      {{ msgText }}
    </div>
 	<!-- 属性中要进行绑定一律用指令 -->
    <div v-bind:id="idShowHTML" v-on:click="showMsg">
      <!-- 这个div中显示HTML文本信息,浏览器会解析字符串中的HTML -->
      <p v-html="msgHTML" />
    </div>
  </div>
</template>
<script>
export default {
  data() {   
    return {
      idShowText: "idShowText",//给div的id属性的值
      idShowHTML: "idShowHTML",
      msgText: '这是一段文本字符串<br />包含的HTML标签会原样显示出来',
      msgHTML: '点击这个标签后显示的字符串包含HTML,这个HTML会被浏览器解析'
    };
  },
  methods: {
      showMsg(){
        this.msgHTML = '<span> 这是一个Span标签</span>' //修改msgHTML变量的内容
      }
  }
};
</script>
<style scoped>
    #idShowText,#idShowHTML{
        width: 500px;
        height: 50px;
        border: 1px solid red
    }
    #idShowHTML {
        cursor: pointer;
    }
</style>

npm run dev 启动服务,效果如下:
在这里插入图片描述
点击下面的那个div,发现输出的 标签被浏览器给解析了,使用 {{ }} 语法的原样输出来了。
在这里插入图片描述

2.4 属性绑定的简写形式

标签的一般属性绑定使用 v-bind: 属性名,事件绑定用 v-on : 事件名

事件名称为 标准DOM事件名称去掉on之后的字符串。如 onclick ==> click

上面的 v-bind:id=“idShowText” 可以简写为 :id= “idShowText” , v-on:click=“showMsg” 可以简写为

@click=“showMsg”

后面双引号,当然也可以是单引号中的内容不要当成字符串,它实际上还是JavaScript表达式。注意v-html是没有简写的,因为它根本就不是在绑定属性,只是占用了标签属性的位置

<template>
  <div>
    <div :id="idShowText">
      <!-- 这个div中显示文本信息 -->
      {{ msgText }}
    </div>

    <div :id="idShowHTML" @click="showMsg">
      <!-- 这个div中显示HTML文本信息 -->
      <p v-html="msgHTML" />
    </div>
  </div>
</template>

3. 指令

指令是模板语法的第二个主要概念。指令Directives是带有v-前缀的特殊属性。指令的属性值是单个的JavaScript表达式(v-for)除外,而且必须添加到一个Vue模板元素才能生效。它的职责是当表达式的值发生改变时,来更新DOM元素。

官方文档 https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4 列出了Vue中能够使用的所有指令。
这里只对条件判断和循环做介绍,其它指令等用到了再做详细介绍

3.1 条件判断指令

条件判断需要用到 v-if v-else v-else-if ,这与JavaScript语言中的条件判断类似。指令必须要作用到元素上才能生效

下面案例的功能是:点击按钮后,启动定时器,定时器每个1秒产生一个随机数,页面上根据随机数的范围显示不同的内容。
在这里插入图片描述
src/components/App.vue

<template>
  <div>
    <button @click="startTimer">启动定时器</button> 
    <button @click="stopTimer">停止定时器</button> 
    <div>
        <template v-if="radomValue<=0.3">
            随机值为: {{ radomValue }} 
            <div>
                <span style="color: green">安全</span>
            </div>
        </template>
        <template v-else-if="radomValue>0.3 && radomValue<=0.6">
            随机值为: {{ radomValue }} 
            <div>
                <span style="color: orange">警告</span>
            </div>
        </template>
        <template v-else>
            随机值为: {{ radomValue }} 
            <div>
                <span style="color: red">危险</span>
            </div>
        </template>
    </div>
  </div>
</template>
<script>
let timer=null; //保存定时器
export default {
  data() {   
    return {
        radomValue: 0,
    };
  },
  methods: {
      startTimer(){
        this.radomValue =  Math.random() //产生一个随机数
        timer=window.setTimeout(this.startTimer,1000) //1秒后再次执行startTimer
      },
      stopTimer(){
        if(timer){
          window.clearTimeout(timer) //停止定时器
          timer=null //将定时器对象置为空
        }
      }
  }
};
</script>

3.2 循环指令

v-for 主要用来对数组进行循环遍历。下面演示的效果为 先显示学生列表,点击按钮后按照年龄进行排序。
在这里插入图片描述
点击升序后,按照升序排列
在这里插入图片描述
点击降序后,按照降序排列
在这里插入图片描述
src/components/App.vue

<template>
  <div>
    <button @click="sort"> {{ order? '升序':'降序'}} </button> 
    <ul>
      <li v-for="(item,index) in students" :key="item.id"> 
        {{index}} &nbsp;&nbsp;&nbsp; 
        {{item.name}} &nbsp;&nbsp;&nbsp;
        {{item.age}}
      </li>
    </ul>
  </div>
</template>
<script>
let students = [
  {id: 1,name: '张三', age : 20},
  {id: 2,name: '李四', age : 19},
  {id: 3,name: '王五', age : 23},
  {id: 4,name: '赵六', age : 18},
]
export default {
  data() {   
    return {
        order : true ,// true为升序,false为降序
        students    
    }
  },
  methods: {
      sort(){
          this.students.sort((a,b)=> {
            if(this.order){
                return a.age-b.age
            }else{
              return b.age-a.age
            }
          })
          this.order=!this.order
      }
  }
}
</script>

可以看到,只要更改了data中的数据,页面会自动更新渲染。v-for 可以遍历一个数组,也可以遍历一个对象。后面有一个特殊的属性 :key ,这个属性是用来标识虚拟DOM元素的。我们知道这里的元素会被Vue 编译成虚拟DOM,有了 key属性后可以唯一的标识这个属性,当数据发生变化的时候,Vue会重新渲染DOM,有了DOM的唯一标识后,当数据发生变化,Vue在处理这些虚拟DOM的时候,可以很方便的找到元素。更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

3.3 数组操作与视图更新

对于数组,以下的方法执行后,会更改原有数组对象的内容,此时视图界面会重新渲染。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

数组的以下方法执行后会返回一个新的数组,原有数组对象内容不会发生变化,界面不会引发界面元素的更新。

  • filter()
  • concat()
  • slice()

这种情况下,只需要将返回的新的数组赋值到为data中替换原有数组即可引发视图页面的更新。
详细说明请看官方文档 https://cn.vuejs.org/v2/guide/list.html#%E6%95%B0%E7%BB%84%E6%9B%B4%E6%96%B0%E6%A3%80%E6%B5%8B

Vue在检测到数组变化时,并不是直接重新渲染整个列表,而是最大化复用DOM元素。替换的数组中,含有相同元素的项不会被重新渲染,所以当用新数组替换旧数组的时候,不用担心性能问题。这也是为什么 v-for 循环的时候总是要设置一个 :key 的原因所在。

以下数组的变动,Vue无法检测到,不会触发视图更新

  • 通过索引直接为数组赋值。比如:this.students[0]={ … }。
  • 修改数组的长度,如: this.students.length=1

要想更改数组元素引发视图更新,可以使用Vue对象提供的静态set方法,比如:

Vue.set(this.students,0,{...})

但是上面的 src/components/App.vue组件中因为没有import Vue 对象,所以无法直接使用Vue对象。 但是App.vue是一个组件,组件实例化之后实际上是一个 Vue的实例对象。实例对象提供了 s e t 方 法 ( 注 意 前 面 有 一 个 set方法(注意前面有一个 set符号,参看官方文档 https://cn.vuejs.org/v2/api/#%E5%AE%9E%E4%BE%8B%E6%96%B9%E6%B3%95-%E6%95%B0%E6%8D%AE)

也可以使用数组对象的splice方法来解决。 splice是从数组中添加或删除项目,然后返回被删除的项目或者添加过的项目。而且该方法会改变原数组

let students = [
  {id: 1,name: '张三', age : 20},
  {id: 2,name: '李四', age : 19},
  {id: 3,name: '王五', age : 23},
  {id: 4,name: '赵六', age : 18},
] 
let s=students.splice(0,2) //第一个参数表示开始索引,第二个参数表示个数。其含义就是从students数组中删除2个元素(第二个参数指定),从索引为0 的位置开始(第一个参数指定)。操作后返回的s为一个新的数据,就是被删掉的数组('张三'和'李四')。students数组剩下 '王五'和'赵六'两个元素,王五的索引为0,赵六的索引为1

/*  
s中的内容
0: {id: 1, name: "张三", age: 20}
1: {id: 2, name: "李四", age: 19}

students中的内容
0: {id: 3, name: "王五", age: 23}
1: {id: 4, name: "赵六", age: 18}
*/

//从索引0开始,删除1个元素,然后插入后面的第三个参数和第四个参数,第二个参数后面都表示要插入的数据,可以有多个
s= students.splice(0,1,{id:3,name:'王5',age:24},{id:5,name:'孙七',age:28})
/*  
s中的内容
0: {id: 3, name: "王五", age: 23}

students中的内容
0: {id: 3, name: "王5", age: 24}
1: {id: 5, name: "孙七", age: 28}
2: {id: 4, name: "赵六", age: 18}
*/

3.4 事件绑定指令

对于v-on:xxx=“yyy” 指令,前面已经使用过了,也可以简写成 @xxx=‘yyy’ ,yyy可以有如下写法:

  • 直接写事件处理的代码, 比如: @click=“count=count+1” count为data中定义的属性
  • 函数名称,比如: @click=“greet” greet为在methods中定义的方法
  • 函数调用,比如:@click=“greet(‘hello’)” greet为在methods中定义的方法,有一个参数。

总之,将yyy看成是JavaScript代码即可。

3.4.1 事件对象

如果希望在事件处理函数中能访问到事件对象该如何操作?Vue提供了一个特殊的变量$event,这个变量用于访问原生DOM事件对象,可以在调用事件处理函数的时候,作为参数传递进去,比如:

<button @click="startTimer($event)" />
methods:{
    startTimer(event){
        ....
    }
}

3.4.2 修饰符

当一个事件发生时,调用指定的事件处理函数,将事件对象$event传入事件处理函数,此时如果希望阻止DOM元素默认行为,就需要调用 event.preventDefault() 来处理,比如 连接 ,当发生click事件后,a元素默认行为就是跳转到 href指定的地址上,要阻止默认事件发生,就需要这样来写:

<A href='http://www.163.com' @click="handle($event)" />

methods:{
    handle(event){
        event.preventDefault() //阻止默认行为
    }
}

Vue中类似于对事件对象的方法调用,可以使用修饰符来处理。其格式为: @xxx.zzz=‘yyy’

  • xxx为事件名称

  • zzz为修饰符,可选的值有:

    • .stop 阻止单击事件继续传播
    • .prevent 阻止DOM元素默认行为
    • .capture 使用事件捕获模式,即DOM元素自身触发的事件先在这里处理,然后才交由DOM内部的子元素处理
    • .self 只有当event.target 是当前元素自身是触发处理函数。即如果事件是从当前DOM元素的子元素触发的,此时不会调用事件处理函数
    • .once 事件只会触发一次
    • .passive 告诉浏览器,你不想阻止事件的默认行为,它刚好与 .prevent相反。
  • yyy为事件处理函数。

使用修饰符的时候,事件处理函数不是必须的,也就是说 yyy部分可以省略。

修饰符可以串联,但是使用的时候要注意串联的顺序,要知道修饰符其实相当于调用event对象的方法。比如:

<A href='http://www.163.com' @click.stop.prevent /> <!-- 这里没有指定事件处理函数 -->

3.4.3 按键修饰符

在监听键盘事件的时候,键盘上的每一个键都有一个keyCode(一个数字)比如:

<input v-on:keyup.13="handle"> <!-- 在input元素上按下键盘上的回车键后,执行handle方法 -->

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

官方文档: https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E7%A0%81

3.5 class与style绑定

每个元素上都有class属性和style属性,可以使用 v-bind来绑定:

<div v-bind:class='' v-bind:style=''></div> 

也可以简写为:

<div :class='' :style=''></div> 

:class和 :style绑定的时候,可以绑定对象和数组。

3.5.1 绑定对象

<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<!--  对象的key是样式的class名称, value是data中的变量,如果这个变量为true,则表示class类名会应用到元素上 -->

<div class='myClass' :class="{ active: isActive, 'text-danger': hasError }"></div>
<!--  class指定的类名和 :class经过计算后确定的类名会叠加 -->

也可以直接指定一个对象:

<!--  直接为:class指定一个data中的变量 -->
<div :class="classObject"></div>
data: {
  classObject: {active: true,'text-danger': false}
}

3.5.2 绑定数组

也可以为 :class指定一个数组,数组的元素所代表的就是 class类名

<div :class="[activeClass, errorClass]"></div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

数组中的元素其实也可以是一个对象,这是对象与数组混合的写法

<div v-bind:class="[{ active: isActive }, errorClass]"></div>
data: {
  isActive: true,
  errorClass: 'text-danger'
}

3.5.3 style绑定

style绑定与class绑定类似,都可以使用对象和数组的语法。是对象的时候有一些小小的区别:

  • :style ="{key:value,key:value}" key为css属性名,value为css属性值,可以是变量
  • :class= ‘{key:value,key:value}’ key为class类名,value为变量
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}

直接绑定一个对象:

<div :style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

数组:

<div :style="[baseStyles, overridingStyles]"></div>

baseStyles与overridingStyles 是对象。对象中包含css属性。

3.6 表单与v-model

Vue中表单输入元素可以使用v-model 将 data中的数据与输入元素进行双向绑定。所谓双向绑定就是当表单输入元素(如文本框 input type=text )的value与 data中的数据进行绑定,这个绑定是双向的。一方的改变,另外一方会跟着改变。

下面来做一个实验. 文本框绑定msg变量,msg变量中有默认值。 input框用 v-model让它与msg绑定。 下面用 {{ msg}} 输出 msg变量中的值。 当按钮按下的时候,修改msg的值。

<template>
  <div>
      这里输入的值与msg模型数据进行了双向绑定 :<input type="text"  v-model="msg">
      <br />
      <div>
       msg变量的值: {{ msg}}
      </div>
      <br />
      <button @click="msg='我是被按钮修改过的msg值'">修改msg的值</button>
  </div>
</template>
<script>
export default {
  data() {   
    return {
      msg:'msg默认值'     
    }
  }
};
</script>

在这里插入图片描述
当修改文本框的值后,发现下面 用 {{ msg }} 输出的值也跟着变了,当点击按钮后, 文本框中的值和 {{ msg }} 显示的也是一致的。
在这里插入图片描述

3.6.1 可以使用 v-model 的表单输入元素

  • 文本框 input type=‘text’
  • 多行文本框 textarea
  • 复选框 input type=‘checkbox’
  • 单选按钮 input type=‘radio’
  • 选择框 select

3.6.2 修饰符

  • .lazy 转变为使用 change事件进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
  • .number 将用户的输入值转为数值类型
  • .trim 自动过滤用户输入的首尾空白字符
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >

4. 计算属性

有时需要对data中定义的属性做一些加工处理的时候,当然可以在 methods中定义函数来对data中的数据进行加工,显示的时候调用函数来显示最终的结果。这种方式虽然可以,但是当数据发生变化的时候,这个函数就不会自动调用最终达到重新渲染的效果了。

此时可以通过定义计算属性来解决。计算属性用起来像属性,但实际上它是一个函数。

src/components/App.vue
在这里插入图片描述

<template>
  <div>
     <button @click="chageTime">显示时间</button>
      <div> {{now}} </div>
  </div>
</template>

<script>
export default {
  data() {   
    return {
      time: new Date()
    }
  },
  methods:{
      chageTime(){
        this.time=new Date()
        window.setTimeout(this.chageTime,1000)
      }
  },
  computed: {
    now :function(){
      return `${this.time.getHours()}:${this.time.getMinutes()}:${this.time.getSeconds()}`
    }
  },
};
</script>

now 就是一个计算属性,放在 computed对象中,它本质上是一个函数,但是绑定模板的时候可以当属性用。

now这个计算属性关联了属性 time,当单机按钮后, changeTime每隔一秒更改time的值,可以看到计算属性now被调用,视图被重新渲染了。

5. watch 监听器

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

src/components/App.vue


<template>
  <div>
     <button @click="chageTime">显示时间</button>
      <div> {{now}} </div>
  </div>
</template>

<script>
export default {
  data() {   
    return {
      time: new Date()
    }
  },
  methods:{
      chageTime(){
        this.time=new Date()
        window.setTimeout(this.chageTime,1000)
      }
  },
  computed: {
    now :function(){
      return `${this.time.getHours()}:${this.time.getMinutes()}:${this.time.getSeconds()}`
    }
  },
  watch: {
    //监听data 中的time属性变化
    time: function(newTime, oldTime){
        console.log(`newTime : ${newTime}, oldTime: ${oldTime}`)
    } 
  }
};
</script>

可以看到watch 中定义的 time与data 中的定义的time是一致的,表示 要监听 data中的time。 watch中的time是一个函数,这个函数有两个参数,一个是变化后的值,一个是变化前的值。
运行后可以看到,只要time值发生变化,就会新旧值都会通过 console 输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

paopao_wu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值