您的位置:首页 > Web前端 > Vue.js

吐血整理-Vue学习笔记

2020-06-03 04:57 375 查看

学习一个新内容时,最好的方式就是跟随官方文档来进行学习。
以下的学习也是基于Vue的官方文档:https://cn.vuejs.org/v2/guide/

文章目录

概述

现在说到前端三大框架,一般都是指这三个:

Angular
React
Vue

其中,
Angular
是一整套的前端解决方法,相比
React
Vue
要厚重得多,所以相对来说学习成本也就更高。但熟悉了之后的
Angula
仍是很多大型前端的很好的一个选择。
React
Vue
,相对来说,
React
更接近原生、更易于理解。
Vue
相对而言封装了更多的方法,提供了更便捷的使用。而且
Vue
的学习曲线相对于这三大框架来说,可以说是最简单的。这可能与
Vue
是国内作者开发,更加贴近国人使用习惯也有一定关系吧。

注:
Angular是Google开发
React是FaceBook开发

之前项目用到了Vue,当时学习Vue的时候做了笔记并进行了分享,故现将当时的笔记稍微整理一下发上来回顾一下,互相学习。

1、引入

<script src="https://unpkg.com/vue"></script>

2、基本使用

界面上定义标签

<div id="app">
{{ message }}
</div>

js里定义Vue,以操作vue实体的方式操纵页面元素。

var app = new Vue({
el: '#app', //用字段代表页面标签
data: { //数据实体,以下数据直接通过{{}}引用
message: 'Hello Vue!', //对应界面上的{{message}}
seen: true,
test1: 1,
todos: [{a:1,b:2},{a:1,b:2},{a:1,b:2}],
isActive: true,
hasError: false,
activeClass: 'active',
errorClass: 'text-danger'
},
method: {  //方法体
reverseMessage: function () {
this.message = this.message.split('').reverse().join('');
}
},
computed: { //计算属性,可以作为根实体属性一样引用
active: function(){
return true;
},
message2: function(){
return this.message + "_2";
}
},
watch: { //监控实体元素的值变动 val当前新值, oldVal 改变前的值
message: function (val, oldVal) {
this.clearData();
this.refresh();
}
}

});

3、vue的页面标签

  • v-bind:title="message"
    :绑定标签的title事件,message即为上面定义的message,此种方式可以直接引用。无法这么使用:
    title={{message}}
  • v-if="[表达式]"
    :vue的if 语句,直接替换[表达式]即可,如:
    v-if="seen"
    v-if="test1 == 1"
    , 表达式通过,则显示该标签,否则不显示
  • v-for="todo in todos"
    :循环,使用如下:
    <li v-for="todo in todos">{{ todo.a }}</li>
    :带上了for所在的标签进行循环
  • <template v-for="item in listData"><li>{{ todo.a }}</li></template>
    :循环template内的内容
  • v-on
    :绑定一个事件监听器, 如
    <button v-on:click="reverseMessage">逆转消息</button>
  • v-model
    :实现表单输入和应用状态之间的双向绑定,如:
    <p>{{ message }}</p>
    <input v-model="message">
    (修改input内的值,对应message的值就修改,于是
    <p>
    内容就会改变)
  • v-once
    :一次性地插值,当数据改变时,插值处的内容不会更新, 如:
    <p v-once>{{ message }}</p>
  • v-html
    :直接替换html,而不是数据值,如:
    <div v-html="rawHtml"></div>
  • 4、组件

    组件是可复用的 Vue 实例,且带有一个名字。在这个例子中是

    <button-counter>

    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
    data: function () {
    return {
    count: 0
    }
    },
    template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
    语法为:Vue.component([组件名], [组件参数], template),其中 template 即为组件的内容填充模板。

    我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用,且与 new Vue 接收相同的选项:

    <!-- 界面上调用组件 -->
    <div id="components-demo">
    <button-counter></button-counter>
    </div>
    调用<button-counter>标签,就会自动写入上面定义里模板template里的内容
    //js中使用自定义组件
    new Vue({ el: '#components-demo' })

    注:

    • 组件可以复用,产生多个实例
    • data
      必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。(即组件设置的值是全局的,通过方法返回的,则可以生成多个副本)

    5、实例属性与方法

    vue 实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀

    $
    ,以便与代理的
    data
    属性区分。
    如:
    app.$el
    :获取Vue实例关联的页面标签元素(详情参照步骤2)。
    app.$el === document.getElementById('app')
    (输出结果为:true)

    //示例代码:
    var app = new Vue({
    el: '#app', //用字段代表页面标签
    data: { //数据实体,以下数据直接通过{{}}引用
    message: 'Hello Vue!', //对应界面上的{{message}}
    }
    });

    6、生命周期-主要有几个周期相关的方法

    beforeCreate
    : 初始化标签、方法前
    在实例初始化之后,数据观测(data observer)和event/watcher 事件配置之前调用
    created
    : 初始化标签、方法后
    实例已经创建完成之后被调用,在这一步,实例已经完成以下的配置:数据观测(data observer)、属性和方法运算、watch/event 事件回调
    beforeMount
    : 创建了vue实体的el标签前
    在挂载开始之前被调用,相关的 render 函数首次被调用
    mounted

    el
    被新创建的
    vm.$el
    替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当 mounted 被调用时
    vm.$el
    也在文档内。
    beforeUpdate

    (数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。)
    updated

    (由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。)
    activated
    : (keep-alive 组件激活时调用。)
    deactivated
    : (keep-alive 组件激活时调用。)
    beforeDestroy
    :vm.$destroy()调用前
    (实例销毁之前调用。在这一步,实例仍然完全可用)
    destroyed

    (Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。)

    7、模板语法

    1. 绑定数据:任意位置使用
      {{}}
      , 如
      <p>{{message}}</p>
      :将数据解释为纯文本
    2. 输出真正的 HTML,如:
      <div v-html="rawHtml"></div>
      :div的内容会被替换成为rawHtml,直接作为HTML。注意,你不能使用
      v-html
      来复合局部模板
    3. 标签属性绑定,如:
      <div v-bind:id="dynamicId"></div>
      即为:
      <div id="dynamicId"></div>

      <a v-bind:href="url"></a>
      即为:
      <a href="url"></a>

      等等
    4. 正常的JavaScript表达式都可以,如:
      {{ message.split('').reverse().join('') }}

      等。
      有个限制就是,每个绑定都只能包含单个表达式:
      {{ if (ok) { return message } }}
      不会生效,
      {{ok ? message : ""}}
      才可以
    5. 缩写:
      v-bind:id="1"
      -->
      :id="1"
      v-on:click="test"
      -->
      @click="test"

    8、计算属性

    就是调用一个有返回值的方法,将这个方法名当为一个参数来使用。这个方法名的使用,就是计算属性。
    如:

    {{message}}
    是直接用
    data
    绑定的一个值,但假设现在
    message
    需要通过一些实时计算等,来生成最终值,那就可以用到计算属性。
    计算属性关键字为:
    computed

    写法为:在声明Vue的时候进行定义,每个计算属性,都用写方法的方式进行定义,如下:
    message2
    在界面上类似
    message
    的方式进行调用:
    {{message2}}
    ,这个message2会实时根据message的变化而变化。)

    //示例代码:
    var app = new Vue({
    el: '#app', //用字段代表页面标签
    data: { //数据实体,以下数据直接通过{{}}引用
    message: 'Hello Vue!', //对应界面上的{{message}}
    },
    computed: { //计算属性,可以作为根实体属性一样引用
    active: function(){
    return true;
    },
    message2: function(){
    return this.message + "_2";
    }
    },
    });

    9、对象语法

    • v-bind:class
      : 通过
      [class名]:[true/false]
      ,动态添加class。
      :
      前的class根据
      :
      后的true/false决定是否加载, 还可以与前面的正常class并存,如:
      <div class="static" v-bind:class="{ active: true, 'text-danger': false }"></div>

      等同于
      <div class="static" v-bind:class="static active"></div>

      (注:active是数据值,也可以是计算属性)
    • <div v-bind:class="[activeClass, errorClass]">
      :语法数组,
      v-bind:class=""
      里面可以通过一个式子带入多个class
    • 组件-例子:(参考4)
      Vue.component('my-component', {template: '<p class="foo bar">Hi</p>'})

      component
      声明,第一个参数
      my-component
      为模板上的标签名,第二个参数里的
      template
      字段,代表需要替换上模板里的具体内容,且替换后原本模板上的属性也会保留,如class等。
      示例:
    //界面上
    <my-component class="baz boo"></my-component>
    
    //js里
    Vue.component('my-component', {
    template: '<p class="foo bar">Hi</p>'
    })
    
    //最终界面被渲染为
    <p class="foo bar baz boo">Hi</p>
    • v-bind:style
      :绑定style, 类似class。且,使用需要特定前缀的 CSS 属性时,如
      transform
      ,Vue.js 会自动侦测并添加。
      可以使用data绑定,也可以使用计算属性,都是直接写入就可以,不需要带上
      {{}}

      示例:
    <!-- activeColor、fontSize 是data绑定数据 -->
    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
    
    <!-- styleObject 是计算属性绑定数据 -->
    <div v-bind:style="styleObject"></div>`

    10、条件渲染

    • v-if
      :用法如下:
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>
    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else>Not A/B/C</div>

    注:

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

    • key
      管理可复用元素:
      如下,只显示其中一个
      template
      ,但对于
      input
      已输入的值,不管切换显示哪个
      template
      ,已经输入的
      input
      的值都会传承下来,只会替换
      input
      placeholder
      值。
      换句话说,就是
      template
      里面相同的标签不会重新渲染,只会相应的替换掉里面的不同。
      key
      的作用,就是给Vue去区分两个
      template
      input
      是不是同一个。这样,切换
      template
      的时候,不同的
      input
      就会重新渲染,即删除了原来的
      input
      ,重新写了一个
      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>
    
    <!-- 改后:  -->
    <template v-if="loginType === 'username'">
    <label>Username</label>
    <input placeholder="Enter your username" key="t1">
    </template>
    
    <template v-else>
    <label>Email</label>
    <input placeholder="Enter your email address" key="t2">
    </template>
    • v-show
      :类似
      v-if
      ,通过条件控制后面内容显不显示。
      v-show=false
      ,是将控件设置为
      display:none

      v-if=false
      ,是直接不执行那一块的代码了。
      所以:
      v-if
      有更高的切换开销,因为每切换一次,就得渲染 / 删除一次元素。
      v-show
      有更高的初始渲染开销,即初始化的时候就已经渲染好了元素,只是根据
      v-show
      的结果来设置
      display
      而已,此后的切换,也只是修改
      display
      值。
      因此:
      如果需要非常频繁地切换,则使用
      v-show
      较好;
      如果在运行时条件不太可能改变,则使用
      v-if
      较好。

    • v-for
      :具有比
      v-if
      更高的优先级

    11、列表渲染

    • v-for="(item, index) in items"
      item
      是当前元素,
      index
      是当前序号,
      items
      是列表内容,也可以是计算属性,还可以是带返回值的方法.
    • 同前面所说的,直接标签内含
      v-for
      ,标签本身也一起循环,如:
      <p v-for="item in items">{{item.a}}</p>

      使用
      template
      ,则里面的内容才进行循环,如:
      <template v-for="item in items"><p>{{item.a}}</p></template>
    • <li v-for="todo in todos" v-if="!todo.isComplete">{{ todo }}</li>
      for
      if
      可以在同一标签内使用,且
      for
      优先级高于
      if
    • key
      值: 用
      v-for
      正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。
      为了给 Vue 一个提示,以便它能跟踪每个节点的身份,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有唯一 id。
      示例:
    <div v-for="item in items" :key="item.id">
    <!-- 内容 -->
    </div>
    • 由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
      1、当你利用索引直接修改一个值时,例如:

      vm.items[indexOfItem] = newValue

      2、当你直接修改数组的长度时,例如:
      vm.items.length = newLength

      为了解决第一类问题,以下两种方式都可以实现和
      vm.items[indexOfItem] = newValue
      相同的效果, 同时也将触发状态更新:

      Vue.set
      方法:
      Vue.set(items, indexOfItem, newValue)
    • Array.prototype.splice
      方法:
      items.splice(indexOfItem, 1, newValue)

    为了解决第二类问题,你可以使用

    • splice
      方法:
      items.splice(newLength)

    12、监听事件

    • click
      :直接在引号中可以书写方法,如:
      <button v-on:click="counter += 1">增加1</button>
    • $event
      :当前事件,类似
      this
      的使用。如:
      <button v-on:click="warn('Form cannot be submitted yet.', $event)">
    • 一些其他的事件监听:
      keyup.enter
      keyup.tab
      keyup.esc

      写法示例:
      <input v-on:keyup.13="submit">

    13、表单控件绑定

    使用

    v-model
    在元素上指定,可以与其他地方创建数据绑定,即修改一个地方的值,其他地方也对应会更新最新值。

    • 单个勾选框,绑定字段为:
      checked
      。根据勾选状态,
      checked
      值对应为
      true/false
      ,在
      label
      里面,对应显示
      true/false
      。示例如下:
    <input mtype="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked}}</label>
    • 如果是多个复选框之类的,
      v-model=[数组]
      ,如:
      checkedNames
      是数组,勾选返回为
      checkBox
      的value
    <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>
    • 下拉: 返回value,如果没有显式设置value,返回text
    <select v-model="selected">
    <option disabled value="1">请选择</option>
    <option value="11">A</option>
    <option value="12">B</option>
    <option value="13">C</option>
    </select>
    • 动态选项,用
      v-for
      渲染option选项,数组设置好value和text, selected为当前选中值
    <select v-model="selected">
    <option v-for="option in options" v-bind:value="option.value">{{ option.text }}</option>
    </select>
    <span>Selected: {{ selected }}</span>
    new Vue({
    el: '...',
    data: {
    selected: 'A',
    options: [
    { text: 'One', value: 'A' },
    { text: 'Two', value: 'B' },
    { text: 'Three', value: 'C' }
    ]
    }
    });
    • 通过
      v-bind
      绑定动态值到标签下:
    <!-- 勾选框,只会返回true/false,但v-bind:true/false后,可以根据true/false返回其他 -->
    <!-- 如以下,true返回a,false返回b -->
    <input type="checkbox" -model="toggle" v-bind:true-value="a" v-bind:false-value="b">
    • 修饰符:
      lazy
      number
      msg
      ,例:(
      msg
      为绑定的字段)
      v-model.lazy="msg"
      :在 “change” 事件时更新
      msg
      值,而不是平时跟着"input" 填写内容而更新
      v-model.number="msg
      :自动将
      msg
      值转为 Number 类型
      v-model.trim="msg"
      :自动过滤
      msg
      值的首尾空格

    14、深入原理

    • 把一个普通 JavaScript 对象传给 Vue 实例的
      data
      选项,Vue 将遍历此对象所有的属性,并把这些属性全部转为
      getter/setter
    • 每个组件实例都有相应的
      watcher
      实例对象,当依赖项的
      setter
      被调用时,会通知
      watcher
      重新计算
    • Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行
      getter/setter
      转化过程,所以属性必须在
      data
      对象上存在才能让 Vue转换它,这样才能让它是响应的
    var vm = new Vue({
    data:{a:1}
    })
    vm.b = 2; //可行的
    vm.data.b=2; //是不行的
    Vue.set(vm.someObject, 'b', 2); //但可以调用:Vue.set(object, key, value)
    this.$set(this.someObject,'b',2); //或调用:this.$set(object, key, value)
    • 异步DOM更新:如果同一个
      watcher
      被多次触发,只会一次推入到队列中。
      如果你想在 DOM 状态更新后做点什么,可以在数据变化之后立即使用
      Vue.nextTick(callback)
      。这样回调函数在 DOM 更新完成后就会调用。
    //组件内使用 vm.$nextTick()
    Vue.nextTick(function () {
    vm.$el.textContent === 'new message'; // true
    })

    15、注册自定义指令

    • 除了核心功能默认内置的指令 (
      v-model
      v-show
      ),Vue 也允许注册自定义指令。
      可以为全局指令,也可以为局部指令,如:
    //局部指令
    directives: {
    focus: {
    // 指令的定义。例:
    //钩子函数:当绑定元素插入到 DOM 中。
    inserted: function (el) {
    el.focus()
    }
    }
    }
    
    //全局指令
    Vue.directive('focus', {
    // 钩子函数:当绑定元素插入到 DOM 中。
    inserted: function (el) {
    // 聚焦元素
    el.focus()
    }
    })
    //使用的语法为:v-focus property
    <input v-focus>
    • 自定义指令的时候,有几个钩子函数可选:
      bind
      :只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
      inserted
      :被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
      update
      :所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。
      componentUpdated
      :指令所在组件的 VNode 及其子 VNode 全部更新后调用。
      unbind
      :只调用一次,指令与元素解绑时调用。
      :VNode简单来说,就是Vue需要渲染的界面上的节点及其子节点,称为虚拟节点(virtual node),简称VNode。

    示例:(效果:在div中输出钩子函数的一些参数值)

    <div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
    Vue.directive('demo', {
    bind: function (el, binding, vnode) {
    var s = JSON.stringify;
    el.innerHTML =
    'name: '       + s(binding.name) + '<br>' +
    'value: '      + s(binding.value) + '<br>' +
    'expression: ' + s(binding.expression) + '<br>' +
    'argument: '   + s(binding.arg) + '<br>' +
    'modifiers: '  + s(binding.modifiers) + '<br>' +
    'vnode keys: ' + Object.keys(vnode).join(', ');
    }
    })
    
    new Vue({
    el: '#hook-arguments-example',
    data: {
    message: 'hello!'
    }
    })

    示例解析:
    指令钩子函数会被传入以下参数:

    • el
      :指令所绑定的元素,可以用来直接操作 DOM。
    • binding
      :一个对象,包含以下 property:
      name
      :指令名,不包括
      v-
      前缀。
    • value
      :指令的绑定值,
      例如:
      v-my-directive="1 + 1"
      中,绑定值为 2。
    • oldValue
      :指令绑定的前一个值,仅在
      update
      componentUpdated
      钩子中可用。无论值是否改变都可用。
    • expression
      :字符串形式的指令表达式,
      例如
      v-my-directive="1 + 1"
      中,表达式为
      "1 + 1"
    • arg
      :传给指令的参数,可选,
      例如
      v-my-directive:foo
      中,参数为
      "foo"
    • modifiers
      :一个包含修饰符的对象。例如:
      v-my-directive.foo.bar
      中,修饰符对象为
      { foo: true, bar: true }
  • vnode
    :Vue 编译生成的虚拟节点。
  • oldVnode
    :上一个虚拟节点,仅在
    update
    componentUpdated
    钩子中可用。
  • :除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的

    dataset
    来进行。

    待续

    以上是整理出来的一部分内容,结合官方文档,可学习初步进行vue的使用了。
    之后会再整理出路由等更加深入一些的内容进行分享。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: