Vue基础

一、概述

1、简介

  • Vue是一套构建用户界面的渐进式框架
  • Vue是一个构建数据驱动的 web 界面的库,其目标是通过简单的 API 实现 响应的数据绑定 和 组合的视图组件
  • Vue只聚焦于视图层,更像是一个视图模版引擎,但是也能作为一个框架使用,提供了完备的支持

2、说明

  • 声明式渲染:就是直接告诉需要怎么渲染什么,具体怎么渲染由框架的底层来实现,而命令式的话就是需要一步一步告知如何实现;
  • 渐进式:简单理解就是比较自由,代码的侵入性比较小;
  • 响应式:数据发生变化,视图自动更新;
  • 可复用的组件系统:方便构建完整的大型应用;

二、Vue实例

1、创建一个 vue 实例

  • 创建一个 vue 实例
    var vm  = new Vue({.....})
  • vue组件的本质还是一个 vue的实例,一个 todo 应用的组件树可以是这样的:
    复制代码
    根实例
    └─ TodoList
       ├─ TodoItem
       │  ├─ DeleteTodoButton
       │  └─ EditTodoButton
       └─ TodoListFooter
          ├─ ClearTodosButton
          └─ TodoListStatistics
    复制代码

2、数据与方法

  • vue 实例 data 对象的属性改变会触发视图的更新;
  • 响应式只对创建实例时候加入的 data 属性有效,对后面添加的属性是无效的,对于后面可能用到属性但又不确定初始值的,最好创建实例的时候加入到data属性,赋值为空即可;
  • Object.freeze()会阻止修改现有的属性,也意味着响应系统无法再追踪变化;
    复制代码
    var obj = {
      foo: 'bar'
    }
    Object.freeze(obj)
    new Vue({
      el: '#app',
      data: obj
    })
    复制代码
  • vue 内置的实例属性和方法用 $ 符号标记;
    复制代码
    var data = { a: 1 }
    var vm = new Vue({
      el: '#example',
      data: data
    })
    
    vm.$data === data // => true
    vm.$el === document.getElementById('example') // => true
    
    // $watch 是一个实例方法
    vm.$watch('a', function (newValue, oldValue) {
      // 这个回调将在 `vm.a` 改变后调用
    })
    复制代码

3、生命周期钩子

  • 每个 Vue 实例在被创建时都要经过设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等一系列的初始化过程;
  • 同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会,简单来说这个钩子就是在vue实例的生命周期到某一阶段的时候会触发一个函数;
  • 常见的钩子有:created、mounted、updated、destroyed,具体的示例如下:
    复制代码
    new Vue({
      data: {
        a: 1
      },
      created: function () {
        // `this` 指向 vm 实例
        console.log('a is: ' + this.a)
      }
    })
    // => "a is: 1"
    复制代码

4、生命周期图示

 三、模版语法

1、插值

  • 插入文本:使用 v-once 指令后只能执行一次性插值,后面这个值就不会变化了
    <span>Message: {{ msg }}</span>
    <span v-once>这个将不会改变: {{ msg }}</span>
  • 插入原始 html:直接使用双重的花括号会把 html 直接当普通文本解析,要用 v-html 才能正确识别
    <p>Using mustaches: {{ rawHtml }}</p>
    <p>Using v-html directive: <span v-html="rawHtml"></span></p>
  • 插入特性:实现了一个动态的特性,将特性的值和data属性进行了绑定
    <div v-bind:id="dynamicId"></div>
  • 使用简单 js 表达式:简单的意思就是最好只用来作计算,使用三元操作之类,同时只能是一个表达式,还有就是表达式中不要访问自定义全局变量
    复制代码
    {{ number + 1 }}
    
    {{ ok ? 'YES' : 'NO' }}
    
    {{ message.split('').reverse().join('') }}
    
    <div v-bind:id="'list-' + id"></div>
    复制代码

2、指令

  • 指令简介
    • 指令 (Directives) 是带有 v- 前缀的特殊属性
    • 指令特性的值预期是单个 JS 表达式 (v-for 是例外情况)
    • 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
  • 指令参数
    • v-bind:href 这个冒号后面的href 就是指令参数,用于指定指令的作用对象
    • v-bind:[attrName] 可以实现动态参数,这个参数的表达式比建议写的太复杂,复杂的话直接用计算属性更好,中括号里的字符串表达式最好都小写
  • 指令修饰符:其作用就是指定以某种特殊的方式进行绑定,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
    <form v-on:submit.prevent="onSubmit">...</form>
  • 指令缩写:v-bind缩写就是只留一个冒号即可,v-on使用@符号代替
    <a :href="url">...</a>
    <a @click="doSomething">...</a>

     

四、计算属性与侦听器

1、计算属性

  • 什么时候用计算属性:模板内的表达式是用于简单运算的,对于任何复杂逻辑,应当使用计算属性
    <div id="example">
      <p>Original message: "{{ message }}"</p>
      <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </div>
    复制代码
    var vm = new Vue({
      el: '#example',
      data: {
        message: 'Hello'
      },
      computed: {
        // 计算属性的 getter
        reversedMessage: function () {
          // `this` 指向 vm 实例
          return this.message.split('').reverse().join('')
        }
      }
    })
    复制代码
  • 计算属性和方法:二者的区别在于计算属性是有缓存的,源数据没有发生改变的情况下不会再次进行计算,直接使用缓存,但是 method 每次使用都会调用方法逻辑
    <p>Reversed message: "{{ reversedMessage() }}"</p>
    复制代码
    // 在组件中
    methods: {
      reversedMessage: function () {
        return this.message.split('').reverse().join('')
      }
    }
    computed: {
      now: function () {
        return Date.now()
      }
    }
    复制代码
  • 计算属性和侦听属性:某些情况侦听属性会比计算属性有更加繁杂的代码和逻辑
    <div id="demo">{{ fullName }}</div>
    复制代码
    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar',
        fullName: 'Foo Bar'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName
        },
        lastName: function (val) {
          this.fullName = this.firstName + ' ' + val
        }
      }
    })
    
    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })
    复制代码
  • 计算属性的 setter:计算属性默认只有 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]
        }
      }
    }
    // ...
    复制代码

2、侦听器

  • 侦听器 watch 选项提供了一个更通用的方法,来响应数据的变化
  • 当需要在数据变化时执行异步开销较大的操作时,使用 watch 比较好,示例代码

 

五、class 和 style 绑定

1、绑定 class

  • 说明:二者的本质都是用 v-bind 绑定属性,不过鉴于特殊性,进行了增强,表达式结果的类型除了字符串之外,还可以是对象或数组
  • 对象语法:和原有的 class 可以共存;绑定的数据对象不一定非要写在模板里,可以在 data 里定义或者用计算属性返回一个数据对象
    <div
      class="static"
      v-bind:class="{ active: isActive, 'text-danger': hasError }"
    ></div>
    复制代码
    data: {
      isActive: true,
      hasError: false
    }
    
    computed: {
      classObject: function () {
        return {
          active: this.isActive && !this.error,
          'text-danger': this.error && this.error.type === 'fatal'
        }
      }
    }
    data: {
      classObject: {
        active: true,
        'text-danger': false
      }
    }
    复制代码

 

  • 数组语法:数组语法支持三元表达式,支持对象语法嵌套
    <div v-bind:class="[activeClass, errorClass]"></div>
    ----------------------------------------------------
    <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
    <div v-bind:class="[{ active: isActive }, errorClass]"></div>
    data: {
      activeClass: 'active',
      errorClass: 'text-danger'
    }
  • 用在组件上:模版中的 class 和元素中的 class 不会相互覆盖
    <my-component class="baz boo"></my-component>
    <my-component v-bind:class="{ active: isActive }"></my-component>
    Vue.component('my-component', {
      template: '<p class="foo bar">Hi</p>'
    })

     

2、绑定 style

  • 对象语法:基本来说和 class 是差不多的用法
    data: {
      activeColor: 'red',
      fontSize: 30
    }
    ------------
    data: {
      styleObject: {
        color: 'red',
        fontSize: '13px'
      }
    }
    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
    ------------------------------
    <div v-bind:style="styleObject"></div>
  • 数组语法:其中的 baseStyles 等是一个样式的对象
    <div v-bind:style="[baseStyles, overridingStyles]"></div>
  • 自动添加前缀:当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀
  • 多重值
    • 从 2.3.0 版本起可以为 style 绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值
    • 这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex
      <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

       

六、条件渲染

1、v-if

  • 指令表达式返回值为 truthy 时,该元素会进行渲染,否则不会渲染;
  • v-if 可以和 v-else-if  v-else 合用
    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>
  • 在 <template> 元素上使用 v-if 条件渲染分组,这里的template 事件上是作为一个容器来使用
    <template v-if="ok">
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </template>

 

  • 用 key 管理可复用的元素

    • 什么时候会有元素的复用:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染,如下的实例中 label 和 input 元素在切换的时候都会被复用,只是略作修改
      <template v-if="loginType === 'username'">
        <label>Username</label>
        <input placeholder="Enter your username">
      </template>
      <template v-else>
        <label>Email</label>
        <input placeholder="Enter your email address">
      </template>
    • 怎么避免 Vue 对元素的复用:只需给不想复用的元素添加一个具有唯一值的 key 属性即可,这里的label没有添加 key,依然会被复用
      <template v-if="loginType === 'username'">
        <label>Username</label>
        <input placeholder="Enter your username" key="username-input">
      </template>
      <template v-else>
        <label>Email</label>
        <input placeholder="Enter your email address" key="email-input">
      </template>

2、v-show

  • v-show 的本质就是修改元素的 display 属性来决定这个元素是否显示;
  • v-show 和 v-if 比较
    • v-if 是真正的条件渲染,不满足条件的话是不会渲染元素的;
    • v-if具有惰性,初始条件为假的话就不会渲染条件块,知道第一次为真的时候才会渲染;
    • v-show 不管初始条件是什么都会进行渲染;v-show 不支持 template;
    • 最后的总结:切换多的话用 v-show,切换不频繁的话用 v-if 可以减少初始渲染;

3、v-if 和 v-for 一同使用

  • 不推荐二者同时使用,但一定要用的话需要注意 v-for 的优先级是高于 v-if 的(用在同一个元素上的时候);
  • 有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 或 <template>上;

 

七、列表渲染

1、用 v-for迭代数组

  • 在 v-for 块中,我们拥有对父作用域属性的完全访问权限
  • v-for 还支持一个可选的第二个参数为当前项的索引
    <ul id="example-2">
      <li v-for="(item, index) in items">
        {{ parentMessage }} - {{ index }} - {{ item.message }}
      </li>
    </ul>
    var example2 = new Vue({
      el: '#example-2',
      data: {
        parentMessage: 'Parent',
        items: [
          { message: 'Foo' },
          { message: 'Bar' }
        ]
      }
    })

     

2、用 v-for迭代对象(属性)

  • 这里可以有三个参数,分别是:索引、属性名、属性值;在遍历对象时,是按 Object.keys() 的结果遍历;
    <div v-for="(value, name, index) in object">
      {{ index }}. {{ name }}: {{ value }}
    </div>
    new Vue({
      el: '#v-for-object',
      data: {
        object: {
          title: 'How to do lists in Vue',
          author: 'Jane Doe',
          publishedAt: '2016-04-10'
        }
      }
    })

     

3、v-for 中的元素复用

  • 和 v-if 类似,用 v-for 来更新已渲染过的列表时也会存在就地复用的情况;
  • 这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出;说白了最好不要让他复用,可能出现问题;
  • 阻止默认复用的方法和 v-if 一样还是设置一个唯一的key值,这个key最好就是数值或者字符串,不要其他花样
    <div v-for="item in items" v-bind:key="item.id">
      <!-- 内容 -->
    </div>

     

4、数组更新检测

  • 变异方法(数组操作方法):pop、push、shift、unshift、splice(删除)、sort、reverse;这些方法会改变原来的数组;
  • 替换数组:
    • 非变异方法如:filter()concat() 和 slice()截取 不会改变原始数组,总是返回一个新数组;
    • 当使用非变异方法时,可以用新数组替换旧数组,这样的替换是非常高效的,不会影响性能;
      example1.items = example1.items.filter(function (item) {
        return item.message.match(/Foo/)
      })
  • 注意事项
    • 以下的两种操作 vue 是无法检测数组的变动的
      vm.items[indexOfItem] = newValue;
      vm.items.length = newLength;
    • 怎么让vue 能够检查到数组的这两种变动呢?第一种给指定索引项设置值可以采取如下方法
      // Vue.set
      Vue.set(vm.items, indexOfItem, newValue)
      vm.$set(vm.items, indexOfItem, newValue)
      // Array.prototype.splice
      vm.items.splice(indexOfItem, 1, newValue)
    • 第二种改变数组长度可以使用如下的操作
      vm.items.splice(newLength)

       

5、对象更改检测注意事项

  • 局限性:对于已经创建的实例,Vue 不能动态添加根级别的响应式属性
    var vm = new Vue({
      data: {
        a: 1
      }
    })
    // `vm.a` 现在是响应式的
    
    vm.b = 2
    // `vm.b` 不是响应式的
  • 添加单个响应式属性:
    Vue.set(vm.userProfile, 'age', 27);
    -------------------
    vm.$set(vm.userProfile, 'age', 27);
  • 添加多个响应式属性:为已有对象赋予多个新属性,应该用两个对象的属性创建一个新的对象
    vm.userProfile = Object.assign({}, vm.userProfile, {
      age: 27,
      favoriteColor: 'Vue Green'
    })

     

6、数组显示过滤排序结果

  • 想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据,可以创建返回过滤或排序数组的计算属性
    <li v-for="n in evenNumbers">{{ n }}</li>
    --------------------
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
      evenNumbers: function () {
        return this.numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
  • 在计算属性不适用的情况下 (在嵌套 v-for 循环中) ,可以使用一个 method 方法来实现同样的功能
    <li v-for="n in even(numbers)">{{ n }}</li>
    --------------------
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    methods: {
      even: function (numbers) {
        return numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }

     

7、v-for 其他使用细节

  • 一段取值范围的 v-for
    <div>
      <span v-for="n in 10">{{ n }} </span>
    </div>
  • v-for on a <template>:就是template 作为容器渲染多个元素

    <ul>
      <template v-for="item in items">
        <li>{{ item.msg }}</li>
        <li class="divider" role="presentation"></li>
      </template>
    </ul>

     

8、一个组件的 v-for

  • 组件可以像普通元素一样使用 v-for,为了保证高版本的兼容性,使用时最好带上 key 属性,保证不会出现元素复用的情况;
  • 任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域,为了把迭代数据传递到组件里,我们要用 props(有点类似于方法传参的意思)
    <div id="todo-list-example">
      <form v-on:submit.prevent="addNewTodo">
        <label for="new-todo">Add a todo</label>
        <input
          v-model="newTodoText"
          id="new-todo"
          placeholder="E.g. Feed the cat"
        >
        <button>Add</button>
      </form>
      <ul>
        <li
          is="todo-item"
          v-for="(todo, index) in todos"
          v-bind:key="todo.id"
          v-bind:title="todo.title"
          v-on:remove="todos.splice(index, 1)"
        ></li>
      </ul>
    </div>
    Vue.component('todo-item', {
      template: '\
        <li>\
          {{ title }}\
          <button v-on:click="$emit(\'remove\')">Remove</button>\
        </li>\
      ',
      props: ['title']
    })
    
    new Vue({
      el: '#todo-list-example',
      data: {
        newTodoText: '',
        todos: [
          {
            id: 1,
            title: 'Do the dishes',
          },
          {
            id: 2,
            title: 'Take out the trash',
          },
          {
            id: 3,
            title: 'Mow the lawn'
          }
        ],
        nextTodoId: 4
      },
      methods: {
        addNewTodo: function () {
          this.todos.push({
            id: this.nextTodoId++,
            title: this.newTodoText
          })
          this.newTodoText = ''
        }
      }
    })

 

八、事件处理

1、事件监听示例

  • 没有参数的时候指令表达式可以没有括号;
  • 指令表达式调用方法可以传递一个 $event 对象来访问原生的事件对象;
    <button v-on:click="warn('Form cannot be submitted yet.', $event)">
      Submit
    </button>
    --------------------
    methods: {
      warn: function (message, event) {
        // 现在我们可以访问原生事件对象
        if (event) event.preventDefault()
        alert(message)
      }
    }

     

2、事件修饰符

  • 事件修饰符的作用就是处理默认行为、事件冒泡等细节,让方法里只有纯粹的数据逻辑,而不用在意这些细节;
  • 常见的修饰符:stop、prevent、capture、self、once、passive
    <!-- 阻止单击事件继续传播 -->
    <a v-on:click.stop="doThis"></a>
    
    <!-- 提交事件不再重载页面 -->
    <form v-on:submit.prevent="onSubmit"></form>
    
    <!-- 修饰符可以串联 -->
    <a v-on:click.stop.prevent="doThat"></a>
    
    <!-- 只有修饰符 -->
    <form v-on:submit.prevent></form>
    
    <!-- 添加事件监听器时使用事件捕获模式 -->
    <!-- 作用是捕获事件冒泡,被修饰的会按从外向内的顺序先执行,然后才按照默认的从内向外的顺序执行 -->
    <div v-on:click.capture="doThis">...</div>
    
    <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
    <!-- 即事件不是从内部元素触发的 不是事件的冒泡行为触发的-->
    <div v-on:click.self="doThat">...</div>
    
    <!-- 点击事件将只会触发一次 -->
    <a v-on:click.once="doThis"></a>
    
    <!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发而不会等待 `onScroll` 完成--> 
    <div v-on:scroll.passive="onScroll">...</div>
  • 使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生
    v-on:click.prevent.self //会阻止所有的点击,
    v-on:click.self.prevent // 只会阻止对元素自身的点击
  • 不要把 .passive 和 .prevent 一起使用,二者是矛盾的,passive有不阻止默认行为的意思

3、按键修饰符

  • 在监听键盘事件时,需要检查详细的按键,keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持,最好的方法是使用按键别名也就是按键修饰符;
  • 常用的按键修饰符:.enter .tab .delete .esc .space .up .down .left .right(当然按键码目前还是支持的)
    <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
    <input v-on:keyup.enter="submit">
    ------------------
    <input v-on:keyup.13="submit">
  • vue 支持自定义按键的别名
    // 可以使用 `v-on:keyup.f1`
    Vue.config.keyCodes.f1 = 112

     

4、系统修饰键

  • 实现仅在按下相应按键时才触发鼠标或键盘事件的监听器的修饰符:ctrl、alt、shift、meta(win开始键)
    <!-- Alt + C -->
    <input @keyup.alt.67="clear">
    
    <!-- Ctrl + Click -->
    <div @click.ctrl="doSomething">Do something</div>
  • .exact 修饰符允许你控制由精确的系统修饰符组合触发的事件,减少误操作的可能
    <!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
    <button @click.ctrl="onClick">A</button>
    
    <!-- 有且只有 Ctrl 被按下的时候才触发 -->
    <button @click.ctrl.exact="onCtrlClick">A</button>
    
    <!-- 没有任何系统修饰符被按下的时候才触发 -->
    <button @click.exact="onClick">A</button>
  • 鼠标按键修饰符:left、right、middle

九、表单输入绑定(v-model)

1、基础用法

  • v-model 的基本介绍:
    • v-model 指令在表单 元素上创建双向数据绑定,根据控件类型自动选取正确的方法来更新元素;
    • v-model 会忽略所有表单元素的 valuecheckedselected 初始值而总是将 Vue 实例的数据作为数据来源;
  • 文本(text)和多行文本(textarea):
    • text 和 textarea 元素将v-model 表达式和 value属性绑定,使用input事件来触发数据更新;
    • textarea 使用文本插值无效,只能使用 v-model
      <input v-model="message" placeholder="edit me">
      <p>Message is: {{ message }}</p>
      ------------
      <span>Multiline message is:</span>
      <p style="white-space: pre-line;">{{ message }}</p>
      <br>
      <textarea v-model="message" placeholder="add multiple lines"></textarea>
  • 复选框(checkbox):单复选框绑定到布尔值,多复选框绑定到数组
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
    ----------------
    <div id='example-3'>
      <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
      <label for="jack">Jack</label>
      <input type="checkbox" id="john" value="John" v-model="checkedNames">
      <label for="john">John</label>
      <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
      <label for="mike">Mike</label>
      <br>
      <span>Checked names: {{ checkedNames }}</span>
    </div>
    ----------
    new Vue({
      el: '#example-3',
      data: {
        checkedNames: []
      }
    })
  • 单选按钮(radio):指令表达式还是和 value 绑定了
  • 选择框(select):多选还是绑定到一个数组,为提高IOS的兼容性可以增加一个禁用的空值选项
    <div id="example-5">
      <select v-model="selected">
        <option disabled value="">请选择</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <span>Selected: {{ selected }}</span>
    </div>

     

2、值绑定

3、修饰符

  • v-model有三个修饰符:
    • lazy(数据自动更新的触发事件由input变成了change)
    • number(将输入值转换为数值类型,无法转换的返回原始类型)
    • trim(自动过滤用户输入首尾的空白)

4、组件使用v-model

 

十、组件基础(自定义元素&属性&事件)

1、组件示例

  • 组件的本质是可复用的 Vue 实例,且带有一个名字;
  • 在 new Vue 创建的 Vue 根实例中,可以把这个组件作为自定义元素来使用;
    <div id="components-demo">
      <button-counter></button-counter>
    </div>
    --------------
    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
      data: function () {
        return {
          count: 0
        }
      },
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
    
    new Vue({ el: '#components-demo' })

2、组件复用 & 组织

  • 复用:
    • 定义的组件可以无数次的复用,每用一次都会有一个新的实例被创建
    • data里直接提供一个对象,这个对象会被所有的组件实例共享
    • 一个组件的 data 选项必须是一个函数,每个实例可以维护一份被返回对象的独立的拷贝,说白了函数返回的话就能互不影响
      data: {
        count: 0
      }
      ---------
      data: function () {
        return {
          count: 0
        }
      }
  • 组织(局部注册?)
    • 一个页面用 vue 来构建的话可以分割成很多的组件,这些组件通过相应的层次构成组件树;
    • 组件的注册分为全局注册和局部注册,vue.component 的方法是全局注册的方法,注册后的主键可以在根实例及其子组件的模版中使用;

3、通过 prop向子组件传递数据

  • 这种向子组件传递数据的方法类似于方法传参;还可以通过使用 v-bind 来动态绑定prop
    <blog-post title="My journey with Vue"></blog-post>
    <blog-post title="Blogging with Vue"></blog-post>
    <blog-post title="Why Vue is so fun"></blog-post>
    ------------------
    Vue.component('blog-post', {
      props: ['title'],
      template: '<h3>{{ title }}</h3>'
    })

     

4、单个根元素

  • 每个组件必须只有一个根元素,通常的做法就是使用一个容器(div)将所有的元素包裹起来;
  • props里的属性不宜定义得过多,会造成代码的可读性变差,通常使用一个对象将这些属性包装起来使用;
    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
    ></blog-post>
    ------------
    Vue.component('blog-post', {
      props: ['post'],
      template: `
        <div class="blog-post">
          <h3>{{ post.title }}</h3>
          <div v-html="post.content"></div>
        </div>
      `
    })
  • js 中多行字符串的实现方法:直接使用+号拼接;使用续行符 \;使用反引号(`)

5、监听子组件事件

  • 基础使用:父组件定义一个自定的事件,子组件通过 $emit 方法触发父组件的自定义事件
    <blog-post
      ...
      v-on:enlarge-text="postFontSize += 0.1"
    ></blog-post>
    -------------------
    <button v-on:click="$emit('enlarge-text')">
      Enlarge text
    </button>
  • 抛出一个值:使用事件抛出一个值可以作为方法参数
    <button v-on:click="$emit('enlarge-text', 0.1)">
      Enlarge text
    </button>
    -------------
    <blog-post
      ...
      v-on:enlarge-text="postFontSize += $event"
    ></blog-post>
  • 组件使用 v-model:v-model的基本原理就是将 vue示例的属性和input value属性绑定,通过input(change)事件来触发数据更新
    <custom-input v-model="searchText"></custom-input>
    ------------
    Vue.component('custom-input', {
            props: ['value'],
            template:
        '<input\
          v-bind:value="value"\
          v-on:input="$emit(\'input\', $event.target.value)">'
        });
        new Vue({el:'#input2',
            data:{
                searchText:''
            },
            methods:{
                input:function (val) {
                    this.searchText = val;
                }
            }
        });

     

6、插槽分发内容 & 动态组件

  • slot 分发内容:slot 给 alert-box 组件内的文本预留了插入的空间
    <div id="slot2">
        <alert-box>
            Something bad happened.
        </alert-box>
    </div>
    --------------
    Vue.component('alert-box', {
      template: `
        <div class="demo-alert-box">
          <strong>Error!</strong>
          <slot></slot>
        </div>
      `
    })
  • 动态组件:
  • 有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里,可以通过 Vue 的 <component> 元素加一个特殊的 is 特性来实现
  • 在示例中,currentTabComponent 可以包括:已注册组件的名字、一个组件的选项对象???
    <!-- 组件会在 `currentTabComponent` 改变时改变 -->
    <component v-bind:is="currentTabComponent"></component>

     

7、解析 DOM 模板时的注意事项

  •  <ul><ol><table> 、<select>等元素对于哪些元素可以出现在其内部是有严格限制的;实例中上面的会渲染出错,下面的利用 is 才是正解
    <table>
      <blog-post-row></blog-post-row>
    </table>
    -----------
    <table>
      <tr is="blog-post-row"></tr>
    </table>
  • 如果我们从以下来源使用模板的话,这条限制是不存在的:字符串 (例如:template: '...');单文件组件 (.vue);<script type="text/x-template">

 

****************参考***************

转载于:https://www.cnblogs.com/stanwuc/p/10873774.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值