vue初识-基础篇


vue初识-基础篇

世事忙忙如水流,休将名利挂心头。粗茶淡饭随缘过,富贵荣华莫强求


1.介绍

是什么?

vue官网文档

  • 构建用户界面,只需关心view层
  • 简单易学,轻量快速
  • 渐进式框架

核心?

  • 响应式的数据绑定:当数据发生改变,视图可以自动更新,可以不用关心dom操作,而专心做数据操作
  • 可组合的视图组件:把视图按照功能切分成若干基本单元,组件可以一级一级再组合成整个应用形成倒置组件树,可维护,可重用,可测试

2.基本使用

安装

  • <script> 标签引入

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  • npm安装

    # 最新稳定版
    $ npm install vue

第一个程序

  • html

    <div id="app">
        {{ message }}
    </div>
    
    <script type="text/javascript">
        var app = new Vue({
            el: '#app',             //绑定上面标签的id
            data: {
                message: 'Hello Vue!'      //绑定标签里的message
            }
            })
    </script>

    运行后,修改message的值,页面也会跟着变

3.vue实例

对象Vue()

每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的

var vm = new Vue({
  // 选项
})

数据与方法

var app = new Vue({
    el: '#app',         //绑定主标签id
    data: {            //添加多个数据
        message: 'Hello Vue!', 
        word:'athink'                
    },
    methods:{        //添加多个方法
           change:function(){
            this.message="",  //通过this.数据名 来获取数据
            this.word=""this.change()     //通过this.方法() 来获取方法
        }
    }
})

console.log(app) //查看所有数据

计算属性

<div id="app">
    {{  reversedMessage }} //reversedMessage 属性可以直接使用
</div>

var app = new Vue({
    el: '#app',         //绑定主标签id
    data: {            //添加多个数据
        message: 'Hello Vue!', 
        word:'athink'                
    },
    computed: { // 计算属性  相当于重新进行逻辑运算后的data
        reversedMessage: function () {  
          return this.message.split('').reverse().join('')  // `this` 指向 vm 实例
        }
      },
    methods:{        //添加多个方法
           change:function(){
            this.message="",  //通过this.数据名 来获取数据
            this.word=""this.change()     //通过this.方法() 来获取方法
        }
    }
})

侦听器

 watch: { //侦听器方法watch
    message: function (newVal, oldVal) { // 如果 message 发生改变,这个函数就会运行
      console.log("这个值改变了.."+newVal)
    }
  }

生命周期

beforeCreate() //在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created()    //在实例创建完成后被立即调用
beforeMount() //在挂载开始之前被调用:相关的 render 函数首次被调用
mounted()    //实例被挂载后调用
beforeUpdate() //数据更新时调用
updated()    //由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子
beforeDestroy()    //实例销毁之前调用。在这一步,实例仍然完全可用
destroyed()    //实例销毁后调用

生命周期图示

4.模板语法

插值

  • 文本

    {{ message }}  //双括号括起来 输出为纯文本
  • 原始 HTML

     <span v-html="rawHtml"></span>  //使用v-html输出带标签的值
  • 属性

    <div v-bind:id="dynamicId" id=""></div>   //使用 v-bind:属性  输出变量属性的值  使用原始属性则为字符串
  • JavaScript 表达式

    {{ number + 1 }}  //支持直接写单行的JavaScript表达式代码

指令

  • v-bind (缩写 : )

    用于绑定变量属性

    <!-- 完整语法 -->
    <a v-bind:href="url">...</a>
    
    <!-- 缩写 -->
    <a :href="url">...</a>
    
    <!-- 动态参数的缩写 (2.6.0+) -->
    <a :[key]="url"> ... </a>
  • v-on(缩写 @ )

    用于绑定事件

    <!-- 完整语法 -->
    <a v-on:click="doSomething">...</a>
    
    <!-- 缩写 -->
    <a @click="doSomething">...</a>
    
    <!-- 动态参数的缩写 (2.6.0+) -->
    <a @[event]="doSomething"> ... </a>

条件渲染

  • v-if

    v-if 指令用于条件性地渲染一块内容,注意是v-if 是“真正”的条件渲染

    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else>
      Not A/B/C
    </div>
  • v-show

    v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的display进行切换

    <h1 v-show="ok">Hello!</h1> //ok是变量,可能为true或false

循环渲染

  • v-for

    v-for 指令基于一个数组来渲染一个列表。

    v-for 指令需要使用 item,index in items 形式,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名,index是当前索引值

    <ul id="v-for-object" class="demo">
      <li v-for="item,index in object" :key='index'>  //key为了标识每个标签是唯一的
        {{ item }}
      </li>
    </ul>
    
    new Vue({
      el: '#v-for-object',
      data: {
        object: ["1","2","3"]
      }
    })
    

事件处理

可以用 v-on或@ 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

  • 基本

    <div id="example-3">
      <button v-on:click="say('hi',$event)">Say hi</button> //触发点击事件 第一个为传入的参数值,第二个为原始DOM事件
      <button v-on:click="say('what',$event)">Say what</button>
    </div>
    
    new Vue({
      el: '#example-3',
      methods: {
        say: function (message, event) { //第一个为传入的参数值,第二个为原始DOM事件
          alert(message)
        }
      }
    })
  • 事件修饰符

    • .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` 完成  -->
    <!-- 这其中包含 `event.preventDefault()` 的情况 -->
    <div v-on:scroll.passive="onScroll">...</div>
  • 按键修饰符

    监听键盘事件时,默认了很多按键属性

    • .enter
    • .tab
    • .delete (捕获“删除”和“退格”键)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right
    • .ctrl
    • .alt
    • .shift
    • .meta
    • .exact
    • .left
    • .right
    • .middle
    <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
    <input v-on:keyup.enter="submit">
    
    <!-- Alt + C -->
    <input v-on:keyup.alt.67="clear">
    
    <!-- Ctrl + Click -->
    <div v-on:click.ctrl="doSomething">Do something</div>
    
    <!-- 有且只有 Ctrl 被按下的时候才触发 -->
    <button v-on:click.ctrl.exact="onCtrlClick">A</button>
    
    <!-- 没有任何系统修饰符被按下的时候才触发 -->
    <button v-on:click.exact="onClick">A</button>
    
    // 可以使用 `v-on:keyup.f1`
    Vue.config.keyCodes.f1 = 112

表单绑定

  • v-model

    v-model 指令在表单 <input><textarea><select> 元素上创建双向数据绑定

    v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理

    v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

    • text 和 textarea 元素使用 value property 和 input 事件;
    • checkbox 和 radio 使用 checked property 和 change 事件;
    • select 字段将 value 作为 prop 并将 change 作为事件。
    <!-- 输入框输入值时,message值也会改变,同理,反过来也是 -->
    <input v-model="message" placeholder="edit me">  
    <p>Message is: {{ message }}</p>
    
    <!--多行文本 -->
    <textarea v-model="message" placeholder="add multiple lines"></textarea>
    
    <!--单个复选框,绑定到布尔值 -->
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
  • 修饰符

    • .lazy 默认input 事件触发后将输入框的值与数据进行同步 ,添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步

    • .number 自动将用户的输入值转为数值类型

    • .trim 自动过滤用户输入的首尾空白字符

    <!-- 在“change”时而非“input”时更新 -->
    <input v-model.lazy="msg">
    
    <!-- 转为数字 -->
    <input v-model.number="age" type="number">
    
    <!-- 过滤首尾空白字符 -->
    <input v-model.trim="msg">

过渡动画

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。

Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件。

  • 单元素过度

      <transition name="fade">
        <p v-if="show">hello</p>
      </transition>
    .fade-enter-active, .fade-leave-active {
      transition: opacity .5s;
    }
    .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
      opacity: 0;
    }
  • 过渡类名

    • v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
    • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
    • v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
    • v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
    • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
    • v-leave-to:定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
  • 列表过度

      <transition-group name="list" tag="p">
        <span v-for="item in items" v-bind:key="item" class="list-item">
          {{ item }}
        </span>
      </transition-group>
  • 配置animate使用

    <!-- 引用animate库-->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet" type="text/css">
    
    <!-- enter-active-class进入动画,leave-active-class动画,:duration动画时间-->
    <transition-group name="todoTransition" enter-active-class=" animate__animated animate__bounceIn"
    leave-active-class="animate__animated animate__fadeOutRight" :duration="{ enter: 500, leave: 400 }">
        <li v-for="item,index in todoList" :key="'todo'+index">
        <input type="radio" @click.prevent.stop="checkDone(item)" :checked="item.isDone" />
        <span>{{item.val}}</span>
        <a href="#1" @click="removeInfo(index.id)">-</a>
        </li>
    </transition-group>

5.复用性

混入

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

  • 通过mixins

    // 定义一个混入对象
    var myMixin = {
      created: function () {
        this.hello()
      },
      methods: {
        hello: function () {
          console.log('hello from mixin!')
        }
      }
    }
    
    // 定义一个使用混入对象的组件
    var Component = Vue.extend({
      mixins: [myMixin]
    })
    
    var component = new Component() // => "hello from mixin!"

自定义命令

  • 全局添加

    自定义命令在任何地方可使用

    // 注册一个全局自定义指令 `v-focus`
    Vue.directive('focus', {
      // 当被绑定的元素插入到 DOM 中时……  
      inserted: function (el) { //inserted 为钩子函数,下面有介绍更多定义的
        // 聚焦元素
        el.focus()
      }
    })
    
    <!-- 在标签上即可使用 -->
    <input v-focus>  
  • 局部添加

    directives: {
      focus: {
        // 指令的定义
        inserted: function (el) {
          el.focus()
        }
      }
    }
    
    <!-- 在标签上即可使用 -->
    <input v-focus>  
  • 钩子函数

    • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
    • componentUpdated:指令所在组件的 VNode 及其子 VNode全部更新后调用。
    • unbind:只调用一次,指令与元素解绑时调用。
  • 钩子函数参数 -> (钩子函数会被传入以下参数)

    • el:指令所绑定的元素,可以用来直接操作 DOM。
    • binding:一个对象,包含以下 property:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
      • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
      • 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:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。

插件

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:

  1. 添加全局方法或者属性
  2. 添加全局资源:指令/过滤器/过渡等.
  3. 通过全局混入来添加一些组件选项.
  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现.
  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能.
  • 使用组件

    var Vue = require('vue')
    var VueRouter = require('vue-router')
    
    // 不要忘了调用此方法
    Vue.use(VueRouter)
  • 开发插件

    暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象

    MyPlugin.install = function (Vue, options) {
      // 1. 添加全局方法或 property
      Vue.myGlobalMethod = function () {
        // 逻辑...
      }
    
      // 2. 添加全局资源
      Vue.directive('my-directive', {
        bind (el, binding, vnode, oldVnode) {
          // 逻辑...
        }
        ...
      })
    
      // 3. 注入组件选项
      Vue.mixin({
        created: function () {
          // 逻辑...
        }
        ...
      })
    
      // 4. 添加实例方法
      Vue.prototype.$myMethod = function (methodOptions) {
        // 逻辑...
      }
    }

过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。

过滤器可以用在两个地方:双花括号插值v-bind 表达式 。

通过 变量 |过滤器 使用。

  • 定义本地的过滤器

    //在组件的选项中定义本地的过滤器
    filters: {
      capitalize: function (value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
      }
    }
    
    //全局过滤器
    Vue.filter('capitalize', function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    })
    
  • 使用过滤器

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

6.组件

定义组件

// 定义一个名为 button-counter 的新组件
Vue.component('com1', {
  props: ['name'],     //自定义由组件外传进来的值
  data: function () { //组件内的data为方法并返回一个对象
    return {
      age: 18
    }
   },
    methods: {
        comEven: function() {
            this.$emit("getage", this.age)  //向外触发事件
        }
    }
  template: '<div>组件1: <slot></slot></div>'  //<slot></slot>为插槽,指组件外调用html标签
})
<div id="components-demo">
    <!-- 在需要的地方直接使用组件名调用,name为传进组件内的值, @getage 为捕捉事件 里面可以写js语句或写方法名 -->
  <com1 :name="Athink" @getage="age+$event">{{age}}</com1>  
</div>

new Vue({ el: '#components-demo' },data:{age:0})

动态组件

在不同组件之间进行动态切换

<!-- 组件会在currentComponent改变时改变 ,例如currentComponent="com1" 即为显示com1组件 -->
<component v-bind:is="currentComponent"></component>  

使用keep-alive标签,缓存组件,减少性能开销

<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

全局组件

//这样即为全局组件,任何地方都可以直接使用
Vue.component('my-component-name', {
  // ... 选项 ...
})

局部组件

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,  //这样的组件只能再id为#app标签里使用
    'component-b': ComponentB
  }
})

模块系统

import/require 使用一个模块系统,后续直接使用vue-cli脚手架会经常使用

import ComponentA from './ComponentA'  //引入一个组件
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

异步组件

//全局组件
Vue.component(
  'async-webpack-example',
  () => import('./my-async-component')  // 这个动态导入会返回一个 `Promise` 对象。
)

new Vue({
  // 局部组件
  components: {
    'my-component': () => import('./my-async-component')
  }
})

组件边界

  • $root 获取根组件

    // 获取根组件的数据
    this.$root.foo
    
    // 访问根组件的计算属性
    this.$root.bar
    
    // 调用根组件的方法
    this.$root.baz()
  • $parent 获取父组件

    this.$parent.foo
  • $refs 为事先绑定的标签提供虚拟dom引用

    <!-- ref为绑定名usernameInput的引用 ,:ref 为绑定变量为usernameInput的引用-->
    <base-input ref="usernameInput"></base-input>
    
    this.$refs.usernameInput //获取这个指定元素的访问

7.其他

目测一般vue使用好像都是通过vue-cli脚手架来创建单文件组件开发的。

掌握基本语法和命令,使用起来还是挺简单的样子..

下篇将记录通过小案例去熟悉使用vue -> vue初始-基础应用

下下篇文章将记录如何使用vue-cli脚手架来创建单文件组件开发。


文章作者: Athink
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Athink !
评论
  目录