Vue框架-基础知识(vue指令、实例生命周期、计算属性与监听属性、插槽理解、组件介绍、数据交互、ES6语法等)

Vue.js 介绍

  • vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的。相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用Vue.js。

什么是MVVM模式?

Vue框架-基础知识(vue指令、实例生命周期、计算属性与监听属性、插槽理解、组件介绍、数据交互、ES6语法等)_第1张图片

  • ViewModel是Vue.js的核心,它是一个Vue实例。Vue实例是作用于某一个HTML元素上的,这个元素可以是HTML的body元素,也可以是指定了id的某个元素。

当创建了ViewModel后,双向绑定是如何达成的呢?

  • 从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据.
  • 从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。

下面展示一下栗子:

  • vue的使用是从一个对象开始的,先创建一个js的对象 new Vue
  • el查找标签的参数
  • data存放数据的参数
  • methods封装函数的参数
<html>
    <head>
        <meta charset="UTF-8">
        <title>title>
    head>

    <body>
        
        <div id="app">
            {{ message }}
        div>
    body>
    <script src="js/vue.js">script>
    <script>
        // 这是我们的Model
        var exampleData = {
            message: 'Hello World!'
        }

        // 创建一个 Vue 实例或 "ViewModel"
        // 它连接 View 与 Model
        new Vue({
            el: '#app',
            data: exampleData
        })
    script>
html>
  • 使用Vue的过程就是定义MVVM各个组成部分的过程的过程。
    • 1:定义View
    • 2:定义Model
    • 3:创建一个Vue实例或者ViewModel,它用于连接View和Model
  • 在创建Vue实例时,需要传入一个选项对象,选项对象可以包含数据挂载元素方法模生命周期钩子等等。

    • 1.选项对象el属性指向Viewel: '#app'表示该Vue实例将挂载到
      ...
      这个元素;data属性指向Modeldata: exampleData表示我们的Model是exampleData对象
    • 2.Vue.js有多种数据绑定的语法,最基础的形式是·文本插值(也叫大胡子),使用一对大括号语法,在运行时{{ message }}会被数据对象的message属性替换,所以页面上会输出”Hello World!”。

    下面举一个双向绑定栗子:

  • MVVM模式本身是实现了双向绑定的,在Vue.js中可以使用v-model指令在表单元素上创建双向数据绑定。

        
        <div id="app">
            <p>{{ message }}p>
            <input type="text" v-model="message"/>
        div>
  • 可以把上面的代码,给它包含在< body>标签中进行一下运行,能更深刻的理解一下v-model指令的双向绑定。

Vue.js的常用指令

什么是vue.js的指令呢?

  • Vue.js的指令是以v-开头的,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性
v-if指令
  • v-if是条件渲染指令,它根据表达式的真假来删除和插入元素,它的基本语法如下:

    v-if="content"
  • v-if取值为false不是隐藏 是删除标签(销毁标签)

    
    <html>
    <head>
      <meta charset="UTF-8">
      <title>title>
    head>
    <body>
    <div id="app">
      <h1>Hello, Vue.js!h1>
      <h1 v-if="yes">Yes!h1>
      <h1 v-if="no">No!h1>
      <h1 v-if="age >= 25">Age: {{ age }}h1>
      <h1 v-if="name.indexOf('fe') >= 0">Name: {{ name }}h1>
    div>
    body>
    <script src="vue.js">script>
    <script>
    
      var vm = new Vue({
          el: '#app',
          data: {
              yes: true,
              no: false,
              age: 28,
              name: 'fe_cow'
          }
      })
    script>
    html>
  • 大家能想象出来下面的页面哪些数据不会出现么 ?

    • 我们需要注意的是:yes, no, age, name这4个变量都来源于Vue实例选项对象的data属性。
    • 数据的yes属性为true,所以“YES!”会被输出。
    • 数据的no属性为false,所以”No!”不会被输出。
    • 运算式age >= 25返回true,所以”Age: 28”会被输出。
    • 运算式name.indexOf('fe') >= 0返回false,所以”Name: fe_cow”会被输出。

v-if指令是根据条件表达式的值(v-if='xxx')来执行元素的插入或者删除行为。

v-else指令
  • 可以用v-else指令为v-ifv-show添加一个“else块”。v-else元素必须立即跟在v-ifv-show元素的后面——否则它不能被识别。

    
    <html>
    
    <head>
      <meta charset="UTF-8">
      <title>title>
    head>
    <body>
    <div id="app">
      <h1 v-if="age >= 25">Age: {{ age }}h1>
      <h1 v-else>Name: {{ name }}h1>
      <h1>---------------------分割线---------------------h1>
      <h1 v-show="name.indexOf('1') >= 0">Name: {{ name }}h1>
      <h1 v-else>Sex: {{ sex }}h1>
    div>
    body>
    <script src="vue.js">script>
    <script>
      var vm = new Vue({
          el: '#app',
          data: {
              age: 28,
              name: 'fe_cow',
              sex: 'cow'
          }
      })
    script>
    html>
  • v-else元素是否渲染在HTML中,取决于前面使用的是v-if还是v-show指令。

  • v-if为true,后面的v-else不会渲染到HTML;v-show为true,但是后面的v-else仍然可以渲染到HTML中。

v-show 指令
  • v-show也是条件渲染指令,和v-if指令不同的是,使用v-show指令的元素始终会被渲染到HTML,它只是简单地为元素设置CSS的style属性。

  • 下面我们举个栗子:

    
    <html>
    <head>
      <meta charset="UTF-8">
      <title>title>
    head>
    <body>
    <div id="app">
      <h1>Hello, Vue.js!h1>
      <h1 v-show="yes">Yes!h1>
      <h1 v-show="no">No!h1>
      <h1 v-show="age >= 25">Age: {{ age }}h1>
      <h1 v-show="name.indexOf('fe') >= 0">Name: {{ name }}h1>
    div>
    body>
    <script src="vue.js">script>
    <script>
    
      var vm = new Vue({
          el: '#app',
          data: {
              yes: true,
              no: false,
              age: 28,
              name: 'fe_cow'
          }
      })
    script>
    html>
  • 可能有同学会发现,这不是更上面的v-if没有什么区别么?指示命令换成了v-show

    • 打开浏览器(chrome)按F12,找到Elements,找到你内容的标签,查看没有展现出来的代码变成了

      No!

      ,发现跟上面的v-if的区别了吧。
    • 如果一个标签要么显示要么隐藏 为了提高代码执行效率可以用v-show,但是如果是多个标签之前切换显示隐藏只能用v-if。
v-for指令
  • v-for指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似:
    • v-for:列表和字典

<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>Documenttitle>
    <script src="js/vue.js">script>
head>
<body>
    
    <div id="app">
        <ul>
            
            <li v-for="i in mylist"> {{ i }}li>
        ul>
        
        
        <ul>
            <li v-for="(i, j) in mylist">{{j+1}}{{ i }}li>
        ul>

        <ul>
            
            <li v-for="i in mydict">{{ i }}li>
        ul>
        <ul>
            
            <li v-for="(i, j) in mydict">{{ j }}:{{i}}li>
        ul>
    div>
    <script>
    var vm = new Vue({
        el:'#app',
        data:{
            mylist: ['邪不压正1', '邪不压正2', '邪不压正3'],
            mydict: {'name':'laowang', 'age':38}
        }
    })
    script>
body>
html>
  • 我们在选项的data属性中定义了一个mylist数组,mydicct字典,然后在#app元素内使用v-for遍历mylist数组和mydict字典。数组可以输出索引,字典也可以输出键值,这点跟python中拆包很像。
v-bind指令
  • v-bind指令:控制html内容控制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>Documenttitle>
    <script src="js/vue.js">script>
head>
<body>
    
    <div id="app">
        <div>{{ num }}div>
        <div>{{ str }}div>
        <div>{{ num + 1}}div>
        <div>{{ str.split('').reverse().join('') }}div>
        
        <div>{{ bool?'成立':'不成立' }}div>
        
        
        <a v-bind:href="url1" class="box">控制html属性hrefa>
        <a :href="url2">控制html属性href 淘宝a>
    div>
    <script>
    var vm = new Vue({
        el:'#app',
        data:{
            num:1,
            str:'abcdefg',
            bool:false,
            url1:'http://www.baidu.com',
            url2:'http://www.taobao.com'
        }
    })
    script>
body>
html>
绑定class html属性
  • 将v-bind指令也可以绑定class html属性, 如果isclass1是true的话,就会绑定class1这个类。

<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>Documenttitle>
    <script src="js/vue.js">script>
head>
<body>
    <div id="app">
        
        
        <div :class="{class1:isclass1, class2:isclass2}">1111111111111div>
        <div :class="myobject1">222222222div>
        
        <div :class="[myclass3, myclass4]">333333div>
        
        <div :class="[isclass2?'aa':'bb']">44444444div>
    div>
    <script>
    var vm = new Vue({
        el:'#app',
        data:{
            isclass1:true,
            isclass2:false,
            myobject1:{
                active:false,
                current:true
            },
            myclass3:'class3',
            myclass4:'class4'
        }
    })
    script>
body>
html>
v-on指令
  • v-on指令用于给监听DOM事件,它的用语法和v-bind是类似的,例如监听< a>元素的点击事件:

    • < a v-on:click=”doSomething”>
  • 有两种形式调用方法:绑定一个方法(让事件指向方法的引用),或者使用内联语句。

    
    <html>
      <head>
          <meta charset="UTF-8">
          <title>title>
      head>
      <body>
          <div id="app">
              <p><input type="text" v-model="message">p>
              <p>
                  
                  <button v-on:click="greet">Greetbutton>
              p>
              <p>
                  
                  <button v-on:click="say('Hi')">Hibutton>
              p>
          div>
      body>
      <script src="js/vue.js">script>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  message: 'Hello, Vue.js!'
              },
              // 在 `methods` 对象中定义方法
              methods: {
                  greet: function() {
                      // // 方法内 `this` 指向 vm
                      alert(this.message)
                  },
                  say: function(msg) {
                      alert(msg)
                  }
              }
          })
      script>
    html>
    v-bind和v-on的缩写
  • Vue.js为最常用的两个指令v-bindv-on提供了缩写方式。v-bind指令可以缩写为一个冒号,v-on指令可以缩写为@符号

     
     <a href="javascripit:void(0)" v-bind:class="activeNumber === n + 1 ? 'active' : ''">{{ n + 1 }}a>
     
     <a href="javascripit:void(0)" :class="activeNumber=== n + 1 ? 'active' : ''">{{ n + 1 }}a>
    
     
     <button v-on:click="greet">Greetbutton>
    
     
     <button @click="greet">Greetbutton>                                      
    
v-model 表单数据绑定
  • 每个表单的name代表的是key,value代表输入的值。

    
    <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>Documenttitle>
      <script src="js/vue.js">script>
    head>
    <body>
      
      <div id="app">
          <input type="text" v-model="txt">
          <div>{{ txt }}div>
          <select v-model="sel">
              <option value="0">北京option>
              <option value="1">上海option>
              <option value="2">广州option>
          select>
          <div>{{sel}}div>
          
          <input type="radio" value="nan" v-model="rad"><input type="radio" value="nv" v-model="rad"><div>{{ rad }}div>
      div>
      <script>
      var vm = new Vue({
          el:'#app',
          data:{
              txt:'请输入用户名',
              sel:0,
              rad:'nv'
          }
      })
      script>
    body>
    html>

Vue中的样式绑定:

  • 第一种方式 Vue中的class对象绑定:

    • !this.xxxx :取反的意思
    
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <title>Vue中class对象绑定title>
       <script src="js/vue.js">script>
       <style>
           .activated{
               color: red;
           }
       style>
    head>
    <body>
    <div id="app">
       <div @click="handleDivClick"
            :class="{activated: isActivated}">
           hello world
       div>
    div>
    <script>
       var vm = new Vue({
           el: '#app',
           data: {
               isActivated: false
           },
           //!this.isActivated 取反的意思
           methods: {
               handleDivClick: function () {
                   this.isActivated = !this.isActivated
               }
           }
       })
    script>
    body>
    html>
    • 第二种方式 Vue种class中数组:
    
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <title>Vue中class数组绑定title>
       <script src="js/vue.js">script>
       <style>
           .activated{
               color: red;
           }
       style>
    head>
    <body>
    <div id="app">
       <div @click="handleDivClick"
            :class="[activated, activatedOne]">
           hello world
       div>
    div>
    <script>
       var vm = new Vue({
           el: '#app',
           data: {
               activated: '',
               activatedOne: 'activated-one'
           },
           // 三元表达式? 如果this.activated不为空字符串的时候,就给它变成空
           methods: {
               handleDivClick: function () {
                   this.activated = this.activated === 'activated'? '':'activated'
               }
           }
       })
    script>
    body>
    html>
    • 第三种方式:通过style对象和数组来表达:

    • 还可以在style数组中给它添加一个样式: :style="[styleObj, {fontSize:'20px'}]"

    
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <title>Vue中style 对象和数组绑定title>
       <script src="js/vue.js">script>
       <style>
           .activated{
               color: red;
           }
       style>
    head>
    <body>
    <div id="app">
       <div @click="handleDivClick"
            :style="[styleObj, {fontSize:'20px'}]">
           hello world
       div>
    div>
    <script>
       var vm = new Vue({
           el: '#app',
           data: {
               styleObj: {
                   color: 'black'
               }
           },
           // 三元表达式? 如果this.activated不为空字符串的时候,就给它变成空
           methods: {
               handleDivClick: function () {
                   this.styleObj.color =  this.styleObj.color === 'black'? 'red':'black'
               }
           }
       })
    script>
    body>
    html>

Vue中条件渲染:

  • 每次循环的时候,循环标签中最好都带有:key='item.id'值,会提高性能。

  • 当想要修改数组的内容的时候,不能通过修改下边的vm.list[0] = {id:'111',text:'222'}执行,应该采用·数组的变异方法:(push,pop,shift,unshift,splice,sort,reverse)

    • vm.splice(下标, 删除几条,{新增内容})
    • 通过改变数组的引用vm.list = [{},{},{}]
    • 通过Vue.set方法:Vue.set(vm.对象名, 1下标, 5更改的名字)
    • 通过Vue的实例:vm.$set(vm.对象名, 1下标, 5更改的名字)
  • template:模板占位符

  • 给对象添加数据:

    • Vue.set(vm.对象名, “address”,”beijing’) 就可以了

    • 通过Vue实例方法实现:`vm.$set(vm.对象名, ”address’,’beijing’)

实例生命周期:

  • 每个Vue实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新 DOM 等。同时在这个过程中会自动运行一些叫做生命周期钩子的函数,我们可以使用这些函数,在实例的不同阶段加上我们需要的代码,实现特定的功能。
beforeCreate:
  • 实例初始化之后数据观测 (data observer)event/watcher 事件配置之前被调用。
created:
  • 实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始。
beforeMount:
  • 挂载开始之前被调用:相关的 render 函数首次被调用。
mounted:
  • 实例挂载到dom之后被调用,可以当成是vue对象的ready方法来使用,一般用它来做dom的初始化操作
beforeDestroy:
  • 组件被销毁之前调用。
destroyed:
  • 组件销毁之后调用
beforeUpdate:
  • 数据发生变化前调用。
updated:
  • 数据发生变化后调用 。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>VUE实例生命周期函数title>
    <script src="js/vue.js">script>
head>
<body>
 <div id="app">
 div>
 <script>
     // 生命周期函数就是vue实例在某一个时间点会自动执行的函数
     var vm = new Vue({
         el:'#app',
         template:"
{{test}}
"
, data: { test:'hello word' }, // 在实例初始化之后调用 beforeCreate: function () { console.log("beforCreate") }, //在实例创建完成后立即调用 created: function () { console.log("created") }, // 在挂载开始之前被调用 在有template模板的时候不渲染 beforeMount: function(){ console.log(this.$el) console.log("beforeMount") }, // 在挂载之后可以调用 在实例中有tempalte模板的时候渲染里面的内容 mounted: function () { console.log(this.$el) console.log("mounted") }, // 在组件被销毁之前它会被执行 在控制台打vm.$destroy()就会执行这俩个方法 beforeDestroy: function () { console.log("beforeDestroy") }, // 在组件被销毁之后它会执行 destroyed:function () { console.log("destroyed") }, // 在数据被改变之前会执行 在控制台输入: vm.test="dell" beforeUpdate 和 updated就会被调用 beforeUpdate: function () { console.log("beforeUpdate") }, // 在数据被改变之后会执行 updated:function () { console.log("updated") } })
script> body> html>

模板语法:

  • 第一种:插值表达式{{}}

  • 第二种:在 < div v-text=’name’> < /div>

  • 第三种:在< div v-html=’name’> < /div>

    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>模板语法title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="app">
      <div>{{name + 'fe_cow'}}div>
      <div v-text="name + 'fe_cow'">div>
      <div v-html="name + 'fe_cow'">div>
    div>
    <script>
      var vm = new Vue({
          el:'#app',
          data: {
              name:'fe_cow'
              // name:'

    fe_cow

    '
    } })
    script> body> html>

计算属性:

  • 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。计算属性还有缓存机制, 计算属性有返回值。例如:

    • 第一种写法:
    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>计算属性 computed方法  缓存机制title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="app">
      <div>{{fullName}}div>
      <div>{{age}}div>
    
    div>
    <script>
      var vm = new Vue({
          el:'#app',
          data: {
              firstName: 'Fe',
              lastName: 'Cow',
              age: 27
          },
          // 计算属性的缓存, 在控制台中打vm.age = 28 可以观察看,并没有走fullName这里,因为fullName中的this.firstName 和 lastName都没有发生改变
          computed: {
              fullName: function () {
                  console.log('执行了一次计算')
                  return this.firstName + this.lastName
              }
          }
      })
    script>
    body>
    html>
  • 使用methods方法 差值表达式后面有()也能达到计算属性,但是建议不使用,因为它没有缓存:

    • 第二种写法
    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>计算属性 methods 不建议使用 没有缓存机制title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="app">
      <div>{{fullName()}}div>
      <div>{{age}}div>
    
    div>
    <script>
      var vm = new Vue({
          el:'#app',
          data: {
              firstName: 'Fe',
              lastName: 'Cow',
              age: 27
          },
          methods: {
              fullName: function () {
                  console.log('执行了一次计算')
                  return this.firstName + this.lastName
              }
          }
      })
    script>
    body>
    html>
计算属性的setter 和 getter

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>计算属性的setter 和 gettertitle>
    <script src="js/vue.js">script>
head>
<body>
<div id="app">
    <div>{{fullName}}div>
    <div>{{age}}div>

div>
<script>
    var vm = new Vue({
        el:'#app',
        data: {
            firstName: 'Fe',
            lastName: 'Cow',
            age: 27
        },
        computed: {
            // 在控制台打 vm.fullName = 'hello word' 改变了fullName的值,set中的value就会接收到 进行切割,重新给firstName 和 lastName重新赋值 
            fullName:{
                get: function () {
                    return this.firstName + this.lastName
                },
                // value set接收到get中 fullName中的值
                set: function (value) {
                    console.log('进入了Set里面')
                    var arr = value.split(' ')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            }
        }
    })
script>
body>
html>

侦听属性:

  • 侦听属性的作用是侦听某属性值的变化,从而做相应的操作,侦听属性是一个对象,它的是要监听的对象或者变量,值一般是函数,当你侦听的元素发生变化时,需要执行的函数,这个函数有两个形参,第一个是当前值第二个是变化后的值

    • 下面栗子是侦听data中的fullName,如果firstName发生改变,就会调用watch方法,就会改变fullName的值。
    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>监听属性 watchtitle>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="app">
      <div>{{fullName}}div>
      <div>{{age}}div>
    
    div>
    <script>
      var vm = new Vue({
          el:'#app',
          data: {
              firstName: 'Fe',
              lastName: 'Cow',
              fullName: 'Fe_cow',
              age: 27
          },
          watch: {
              firstName:function(){
                  console.log('执行一次')
                  this.fullName = this.firstName + this.lastName
              },
              lastName: function () {
                  console.log('执行二次')
                  this.fullName = this.firstName + this.lastName
              }
          }
      })
    script>
    body>
    html>

过滤器:

  • Vue.js允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值v-bind 表达式

    
    {{ prize | RMB }}
    
    
    <div v-bind:id="rawId | formatId">div>
    • 过滤器实际上是一个函数,可以在一个组件的选项中定义组件内部过滤器:

    • filters:定义的是局部变量:需要在实例内部定义

    filters:{
    RMB:function(value){
      if(value=='')
      {
        return;
      }
      return '¥ '+value;
    }
    }
    • 或者在创建 Vue 实例之前全局定义过滤器

    • Vue.filter('名字',匿名函数){}:定义全局变量:

    Vue.filter('Yuan',function(value){
    if(value=='')
    {
      return;
    }
    return value+'元';
    });
    • 总体的栗子如下:
    
    <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>Documenttitle>
      <script src="js/vue.js">script>
    head>
    <body>
      
      <div id="app">
          
          <div>{{ price1 | yuan | RMB}}div>
          <div>{{ price2 | yuan | RMB}}div>
      div>
      <div id="box">
          <div>{{ price1 | RMB }}div>
          <div>{{ price2  |RMB }}div>
      div>
      <script>
      // 全局过滤器:作用于所有对象 -- 要求全局过滤器必须定义再所有对象的上面
      // Vue.filter(名字,function(){})
      Vue.filter('RMB', function(vals){
          if(vals == 0){
              return vals
          }
          return '¥' + vals
      })
    
    
      var box = new Vue({
          el:'#box',
          data:{
              price1:999,
              price2:0
          }
      })
      var vm = new Vue({
          el:'#app',
          data:{
              price1:99,
              price2:0
          },
          filters:{
              // mingzi:function(){}
              yuan:function(vals){
                  if(vals == 0)
                  {
                      return vals
                  }
                  return vals +'元'
              }
          }
      })
      script>
    body>
    html>

组件简介:

  • 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树 :

Vue框架-基础知识(vue指令、实例生命周期、计算属性与监听属性、插槽理解、组件介绍、数据交互、ES6语法等)_第2张图片

  • 组件(Component)是Vue.js最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。

    组件的创建和注册

  • 基本步骤:

    • Vue.js的组建的使用有3个步骤:1.创建组件构造器 2.注册组件 3.使用组件。

    • 调用Vue.extend()方法创建组件构造器。

    • 调用Vue.compoent()方法注册组件。
    • Vue实例的作用范围内使用组件。
    • 下面举一个栗子:
    
    <html>
      <body>
          <div id="app">
              
              <my-component>my-component>
          div>
      body>
      <script src="js/vue.js">script>
      <script>
    
          // 1.创建一个组件构造器  模板是div标签组成的
          var myComponent = Vue.extend({
              template: '
    This is my first component!
    '
    }) // 2.注册组件,并指定组件的标签,组件的HTML标签为 Vue.component('my-component', myComponent) new Vue({ el: '#app' });
    script> html>

理解组件的创建和注册

  • 接下来我们用以下几个步骤来理解组件的创建和注册:

    • 1.vue.extend()是Vue构造器的扩展,调用vue.extend创建一个组件构造器。
    • 2.vue.extend()构造器有一个选项对象,选项对象的template属性用于定义组件要渲染的HTML。
    • 3.使用Vue.component()注册组件时,需要提供2个参数,第1个参数是组件的标签,第2个参数是组件构造器。
    • 4.组件应该挂载到某个Vue实例下,否则它不会生效。
    
    <html>
      <body>
          <div id="app1">
              <my-component>my-component>
          div>
    
          <div id="app2">
              <my-component>my-component>
          div>
    
          
          <my-component>my-component>
      body>
      <script src="js/vue.js">script>
      <script>
          var myComponent = Vue.extend({
              template: '
    This is a component!
    '
    }) Vue.component('my-component', myComponent) var app1 = new Vue({ el: '#app1' }); var app2 = new Vue({ el: '#app2' })
    script> html>

给组件绑定原生事件:

  • 在子组件中绑定原生事件:@click.native="handleClick"

    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>给组件绑定原生事件title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="root">
      <child @click.native="handleClick">child>
    div>
    <script>
      Vue.component('child',{
          template: '
    Child
    div>'
    }) var vm = new Vue({ el:'#root', methods:{ handleClick:function () { alert('handleClick') } } })
    script> body> html>

非父子组件间的传值:

  • .bus

    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>非父子组件间传值(Bus/总线/发布订阅者模式/观察者模式)title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="root">
      <child content="Fe">child>
      <child content="cow">child>
    
    div>
    <script>
      Vue.prototype.bus = new Vue()
    
      Vue.component('child',{
          // 进行赋值
          data: function() {
            return {
                selfCountent: this.content
            }
          },
          // 把父组件传递过来的参数 进行校验
          props: {
              content: String
          },
          template: '
    {{selfCountent}}
    div>'
    , // 点击子组件触发的事件 methods:{ handleClick: function () { this.bus.$emit('change', this.selfCountent) } }, mounted: function () { var this_ = this this.bus.$on('change', function (msg) { this_.selfCountent = msg }) } }) var vm = new Vue({ el:'#root' })
    script> body> html>

Vue中的插槽:

  • 子组件中,引入新的标签,可以在标签中引入slot='head'属性,然后在子组件的template:给插槽占位。

    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Vue中的插槽title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="app">
      <body-comtent>
          <div class="head" slot="head">headdiv>
          <div class="footer" slot="footer">footerdiv>
      body-comtent>
    div>
    <script>
      Vue.component('body-comtent', {
          template:'
    ' + '' + '
    content
    '
    + '' + '
    '
    }) var vm = new Vue({ el:'#app' })
    script> body> html>

Vue中的插槽的作用域:

  • 应用场景:在子组件中需要使用循环时,父组件控制子组件:

    • 1:在子组件中使用循环遍历的时候在slot标签中定义 :item=item将数据传递给父组件。
    • 2:父组件通过slot-scope="props"它应该定义在tempalte标签中。
    • 3:父组件在使用的时候{{props.item}}就可以将子组件中的循环数据,传递到父组件中。
    
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Vue中的插槽作用域title>
      <script src="js/vue.js">script>
    head>
    <body>
    <div id="app">
      <body-comtent>
          <template slot-scope="props">
              <h1>{{props.item}}h1>
          template>
      body-comtent>
    div>
    <script>
      Vue.component('body-comtent', {
          data:function(){
              return{
                  list: [1,2,3,4]
              }
          },
          template:'
    '
    }) var vm = new Vue({ el:'#app' })
    script> body> html>

data 必须是函数:

  • 组件就是vue的实例,所有vue实例中属性和方法,组件中也可以用,但是data属性必须是一个函数,因为组件会重复使用在多个地方,为了使用在多个地方的组件数据相对独立,data属性需要用一个函数来返回值。

    // 定义组件
    Vue.component('simple-counter', {
    template: '<button v-on:click="counter += 1">{{ counter }}button>',
    data: function () {
          return {
          counter: 0
        }
    }
    })
    
    // 使用组件
    <div id="example-2">
    <simple-counter>simple-counter>
    <simple-counter>simple-counter>
    <simple-counter>simple-counter>
    div>
    ......
    new Vue({
    el: '#example-2'
    })

组件中< style>标签中 scoped:

  • css: scoped 表示是接下来的css只针对这个组件生效。

  • 记住单文组件写js,必须是模块导出的形式:export default{ }

  • @符:就是src文件夹。

全局注册和局部注册

  • 调用vue.component()注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。

  • 如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components属性实现局部注册

    
    <html>
      <body>
          <div id="app">
              
              <my-component>my-component>
          div>
      body>
      <script src="js/vue.js">script>
      <script>
          // 1.创建一个组件构造器
          var myComponent = Vue.extend({
              template: '
    This is my first component!
    '
    }) new Vue({ el: '#app', components: { // 2. 将myComponent组件注册到Vue实例下 'my-component' : myComponent } });
    script> html>

父组件和子组件

  • 我们可以在组件中定义并使用其他组件,这就构成了父子组件的关系。

    
    <html>
      <body>
          <div id="app">
              <parent-component>
              parent-component>
          div>
      body>
      <script src="js/vue.js">script>
      <script>
    
          var Child = Vue.extend({
              template: '

    This is a child component!

    '
    }) var Parent = Vue.extend({ // 在Parent组件内使用标签 template :'

    This is a Parent component

    '
    , components: { // 局部注册Child组件,该组件只能在Parent组件内使用 'child-component': Child } }) // 全局注册Parent组件 Vue.component('parent-component', Parent) new Vue({ el: '#app' })
    script> html>
  • 分析一下代码:

    • 1.var Child = Vue.extend(...)定义一了个Child组件构造器。
    • 2.var Parent = Vue.extend(...)定义一个Parent组件构造器。
    • 3.components: { 'child-component': Child },将Child组件注册到Parent组件,并将Child组件的标签设置为child-component
    • 4.template :'

      This is a Parent component

      '
      ,在Parent组件内以标签的形式使用Child组件。
    • 5.Vue.component('parent-component', Parent)全局注册Parent组件。
    • 6.在页面中使用标签渲染Parent组件的内容,同时Child组件的内容也被渲染出来。
  • Child组件是在Parent组件中注册的,它只能在Parent组件中使用,确切地说:子组件只能在父组件的template中使用。

  • 举两个错误的栗子:

    • 以子标签的形式在父组件中使用:
    • 因为当子组件注册到父组件时,Vue.js会编译好父组件的模板,模板的内容也决定了父组件将要渲染的HTML。
    • 相当于运行时,它的一些子标签只会被当作普通的HTML来执行。
    • 不是标准的HTML标签,会被浏览器直接忽视掉。
    • 在父组件标签外使用子组件
    <div id="app">
      <parent-component>
      parent-component>
      <child-component>
      child-component>
    div>
    

组件注册语法糖

  • 以上组件注册的方式有些繁琐,Vue.js为了简化这个过程,提供了注册语法糖。

  • 使用Vue.component()直接创建和注册组件:

    // 全局注册,my-component1是标签名称
    Vue.component('my-component1',{
      template: '
    This is the first component!
    '
    }) var vm1 = new Vue({ el: '#app1' })
  • Vue.component()的第1个参数是标签名称,第2个参数是一个选项对象,使用选项对象的template属性定义组件模板。使用这种方式,Vue在背后会自动地调用Vue.extend()

  • 在选项对象的components属性中实现局部注册:

    var vm2 = new Vue({
      el: '#app2',
      components: {
          // 局部注册,my-component2是标签名称
          'my-component2': {
              template: '
    This is the second component!
    '
    }, // 局部注册,my-component3是标签名称 'my-component3': { template: '
    This is the third component!
    '
    } } })

使用scrip或template标签:

  • 尽管语法糖简化了组件注册,但在template选项中拼接HTML元素比较麻烦,这也导致了HTML和JavaScript的高耦合性。 庆幸的是,Vue.js提供了两种方式将定义在JavaScript中的HTML模板分离出来。
  • 使用< script>标签

<html>
    <body>
        <div id="app">
            <my-component>my-component>
        div>

        <script type="text/x-template" id="myComponent">
            
This is a component!div> script> body> <script src="js/vue.js">script> <script> // 相当于给template模板定义了scrpt标签,通过id进行一个绑定 Vue.component('my-component',{ template: '#myComponent' }) new Vue({ el: '#app' }) // template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译 script> html>
  • 使用< script>标签时,type指定为text/x-template,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略< script>标签内定义的内容。

  • 使用< template>标签

  • 如果使用