Vue学习笔记

Vue学习笔记

一切Vue项目都从一个vue实例开始

var vm = new Vue()

<body>
    <div id="app">
      {{ message }} {{ date }}
    </div>
  </body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: "#app",
      data() {
        return {
          message: 'Hello Imooc !'
        }
      }
    })
  </script>

1.指令都带有 v- 前缀

<div v-text="message"></div>
var vm = new Vue({
	el: '#app',
  data: {
  	message: "Hello!"
  },
})

<div v-html="message"></div>
var vm = new Vue({
    el: '#app',
    data: {
    	message: "<div>您好,我是小慕!</div>",
    }
  })

v-bind后面是 :属性名=[变量名]。例如:v-bind:title="message"

v-bind 的简写方式,可以直接通过:属性名的方式

<div>
      <img :src="src"/>
    </div>

v-for 对数组

<ul>
      <li v-for="item in music">{{item.name}}</li>
 </ul>

  • v-for="(value, name, index) in object"

    value为值,name为key,index为索引

    为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute:

    <div v-for="item in items" v-bind:key="item.id">
      <!-- 内容 -->
    </div>
    

    建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

    从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数:

    <!--
    注意,参数表达式的写法存在一些约束,如之后的“对动态参数表达式的约束”章节所述。
    -->
    <a v-bind:[attributeName]="url"> ... </a>
    

    <a v-bind:[someAttr]="value"> ...


    vue提供了v-ifv-show两个指令来控制页面元素的显示和隐藏

    不同点v-if:根据表达式的值在 DOM 中生成或移除一个元素。

    v-show:根据表达式的值通过样式的改变来显示或者隐藏 HTML 元素。


    <div v-if="number === 1">
          A
    </div>
    <div v-else-if="number === 2">
          B
    </div>
    <div v-else>
         C
    </div>
    

    vue 中提供了指令 v-on 来进行事件的绑定。用法:v-on:事件名="方法",例如:v-on:click=“alert”。

     <button v-on:click="hello">hello</button>
    

    v-on提供了简写方式,只需要通过@事件类型的方式就可以了。例如:@click="hello"

    可一次执行多个方法

    @click="add,delete"


    vue通过了指令v-model来实现数据的双向绑定

     <div id="app">
        <div>
          <label>年龄:</label>
          <input v-model="age"/>
        </div>
        <div>当前输入的年龄是: {{age}}</div>
        <button @click="add">加一岁</button>
        <button @click="alertYear">弹出年龄</button>
      </div>
    
    var vm = new Vue({
    	el: '#app',
      data: {
      	age: 10
      },
      methods: {
        add(){
        	this.age = this.age + 1;
        },
        alertYear() {
        	alert(this.age)
        }
      }
    })
    

    使用 Object.freeze(),这会阻止修改现有的 property,也意味着响应系统无法再追踪变化。

    v-pre

    该指令会跳过所在元素和它的子元素的编译过程,也就是把这个节点及其子节点当作一个静态节点来处理,

    也就是说不进行Vue的分析,只是单纯的html语句

    <div v-pre>当前输入的年龄是: {{age}}</div>
    <div>当前输入的年龄是: {{age}}</div>
    

    当前输入的年龄是: {{age}}
    当前输入的年龄是: 10


    v-once

    模板只会在第一次更新时显示数据,此后再次更新该DOM里面引用的数据时,内容不会自动更新

    通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:

    <span v-once>这个将不会改变: {{ msg }}</span>
    

    通过传给 v-bind:class 一个对象,以动态地切换 class:

    <div v-bind:class="{ show: isShow }"></div>
    

    show 这个 class 存在与否将取决于数据属性 isShow 是否为真值。

    与angular类似

    <div [ngClass]="{'active': isActive, 'primary': isFocus}">ngClass</div>
    

    2.样式绑定

    逗号分隔

    <div v-bind:style="{ backgroundColor: backgroundColor,  width + 'px' }"></div>
    
    <div v-bind:style="[stylesA, stylesB]"></div>
    
    stylesA: {
          "background-color": 'red',
           '300px'
        },
        stylesB: {
          color: '#fff',
          height: '300px'
        }
    

    3.计算属性

    每一个计算属性都包含一个 getter 和一个 setter

    计算属性默认只有 getter,不过在需要时你也可以提供一个 setter

    当手动修改计算属性的值就像修改一个普通数据那样时,就会触发 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]
        }
      }
    }
    // ...
    

    既然 methods 同样可以解决模板中复杂逻辑计算的问题,那么为什么还需要使用计算属性呢?

    原因就是:计算属性是基于它的依赖缓存的。前面我们介绍过,计算属性的改变取决于其所依赖数据的变化,所以只要依赖数据不发生改变,计算属性就不会更新。当我们重复获取计算属性时它也不会重复计算,只会获取缓存的值。而我们每次调用 methods 都会重新计算一遍,这样将会消耗一部分性能。当然,如何你不希望对数据进行缓存,那么可以用方法来代替。

     <h1>商品总价:{{totalPrice()}} 元</h1> 
     methods: {
      	totalPrice() {
      		return this.count * this.unitPrice
      	}
      }
    
    <h1>商品总价:{{totalPrice}} 元</h1> 
     computed: {
      	totalPrice() {
      		return this.count * this.unitPrice
      	}
      }
    

    4.实例 property 与方法

    Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 $,以便与用户定义的 property 区分开来。例如:

    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` 改变后调用
    })
    

    5.监听器

    var vm = new Vue({
      el: '#app',
      data() {
        return {
          count: 0
        }
      },
      watch: {
        count: function(newVal, oldVal) {
          // 具体处理逻辑
        },
      }
    })
    
    <div>商品名称:<input v-model="product.name"/></div>
    
    watch: {
            product: function(newValue){
              console.log(newValue)
            }
          }
    

    或者使用handle处理

     watch: {
    	      name: {
    	        handler(newVal, oldVal) {
    	          console.log(newVal)
    	        }
    	      }
    	    }
    

    在侦听器最初绑定的时候就触发一次

    watch: {
            name: {
              handler(newVal, oldVal) {
                console.log(newVal)
              },
              // 代表在wacth里声明了name这个方法之后立即先去执行一次handler方法
              immediate: true
            }
          }
    

    deep 属性代表是否深度监听,默认值是 false。当设置为 true 时,会对对象里面的每个属性进行侦听。

     watch: {
            product: {
              handler: function(newVal) {
                console.log(newVal)
              },
              deep: true
            }
          }
    

    监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,修改对象里面任何一个属性都会触发这个监听器里的 handler。

    通常更好的做法是使用计算属性而不是命令式的 watch 回调

    事件修饰符

    Vue 提供了以下事件修饰符:

    1. .stop: 阻止单击事件继续传播;例如内部button点击触发事件,不会传播给父按钮

    2. .prevent: 只有修饰符,提交事件不再重载页面。

    3. .capture: 添加事件监听器时使用事件捕获模式,即元素自身触发的事件先在自身处理,然后交由内部元素进行处理;子按钮点击,先出触发父元素的点击事件,再触发子按钮的点击事件

    4. .self: 只有在event.target是当前元素自身时触发处理函数,即事件不是从内部元素触发的;

    5. .once: 点击事件将只在最开始时触发一次

    6. .passive: 滚动事件会立即触发,不会等待其他串联事件。即prevent会失效。

      使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

      不要把 .passive.prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。

    按键修饰符

    在监听键盘事件时,我们经常需要检查详细的按键

    <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
    <input @keyup.enter="submit" />
    

    Vue 为最常用的键提供了别名:

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

    系统修饰键

    可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

    • .ctrl
    • .alt
    • .shift
    • .meta

    .exact 修饰符

    .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

    这些修饰符会限制处理函数仅响应特定的鼠标按钮。

    2.动画

    图片描述

    <style>
        .fade-enter-active, .fade-leave-active {
          transition: opacity 3s
        }
        .fade-enter, .fade-leave-to {
          opacity: 0
        }
    </style>
    
     <transition name="fade">
          <p v-show = "show" >hello !</p>
        </transition>
    

    3.生命周期

    图片描述

    • beforeCreate(创建前)
    • created(创建后)
    • beforeMount(载入前)
    • mounted(载入后)
    • beforeUpdate(更新前)
    • updated(更新后)
    • beforeDestroy(销毁前)
    • destroyed(销毁后)

    3.1. 创建前(beforeCreate)

    在实例初始化之后,此时的数据观察和事件机制都未形成,不能获得 DOM节点。

    3.2. 创建后(created)

    实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始。

    3.3. 载入前(beforeMount)

    在挂载开始之前被调用:这个过程是在模版已经在内存中编译完成, render 函数首次被调用,此时完成了虚拟 DOM 的构建,但并未被渲染

    3.4. 载入后(mounted)

    这个过程在模版挂载之后被调用,页面完成渲染,在这之后所以我们可以操作和访问 DOM 元素

    3.5. 更新前(beforeUpdate)

    当数据更新时调用,在这一阶段 DOM 会和更改过的内容同步

    3.6. 更新后(updated)

    由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

    当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。

    3.7. 销毁前(beforeDestroy)

    实例销毁之前调用。在这一步,实例仍然完全可用。

    3.8. 销毁后(destroyed)

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

    例子

    <body>
    {{ name }}
    </body>

    4.组件

    全局注册

      <div id="app">
        <my-component></my-component>
        <my-component /> 
      </div>
    
    <script type="text/javascript">
      Vue.component('myComponent', {
        template: '<div>Hello !</div>'
      })
      var vm = new Vue({
        el: '#app',
        data() {
        	return {}
        }
      }
    </script>
    

    3.0版本

    const app = Vue.createApp({})
    
    app.component('component-a', {
      /* ... */
    })
    

    局部注册

    可以通过一个普通的 JavaScript 对象来定义组件:

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

    然后在 components 选项中定义你想要使用的组件:

    const app = Vue.createApp({
      components: {
        'component-a': ComponentA,
        'component-b': ComponentB
      }
    })
    

    真实情况:

    image-20201125163048530

    <template>
      <img alt="Vue logo" src="./assets/logo.png">
      <HelloWorld msg="Welcome to Your Vue.js App"/>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld.vue'
    
    export default {
      name: 'App',
      components: {//引入组件
        HelloWorld
      }
    }
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    

    5.父组件传值给子组件

    1.通过 props 传递数据给子组件(单向)

    父组件通过 props 属性向子组件传递数据。子组件利用组件实例的 props 属性定义组件需要接收的参数,在使用组件时通过 attribute的方式传入参数,也可以直接将整个父组件传入子组件

    // 在子组件内定义组件接收一个参数 name
    {
      props: ['name',"home"]
    }
    // 父组件使用组件时传递参数 name
    <child :name="name" :home="this"></child>
    
    props: {
          name: {
            type: String,
            default: '句号'
          }
        }
    

    2.parent获取父组件数据(可以修改子组件的数据)

    this.$parent.属性/方法
    

    6.子组件传值给父组件

    1.通过 $emit 传递数据给父组件

    子组件通过 $emit 传递事件给父组件,父组件通过 $on 监听事件:

    // 子组件定义事件
    this.$emit('事件名称', '传递的参数') //例: this.$emit('add', 111)
    
    // 父组件监听事件的触发
    <child  @事件名称="事件触发的方法"/>//<child  @add="change"/>  change(number){this.a+=number}
        //<child  @add="a+=$event"/>
    

    或者 父级组件可以像处理 native DOM 事件一样通过 v-on@ 监听子组件实例的任意事件:

    1.1验证抛出的事件

    要添加验证,将为事件分配一个函数,该函数接收传递给 $emit 调用的参数,并返回一个布尔值以指示事件是否有效。

    注意:验证是否有效并不能阻止子组件将数据传入父组件

    app.component('custom-form', {
      emits: {
        // 没有验证
        click: null,
    
        // 验证submit 事件
        submit: ({ email, password }) => {
          if (email && password) {
            return true
          } else {
            console.warn('Invalid submit event payload!')
            return false
          }
        }
      },
      methods: {
        submitForm() {
          this.$emit('submit', { email, password })
        }
      }
    })
    

    2.调用子组件时通过ref(可以修改父组件的数据)

    <componenta ref="a"><componenta />
    

    父组件获取

    this.$refs.a.属性/方法
    

    3.v-model在组件上的使用

    app.component('custom-input', {
      props: ['modelValue'],
      template: `
        <input
          :value="modelValue"
          @input="$emit('update:modelValue', $event.target.value)"
        >
      `
    })
    
    <custom-input v-model="searchText"></custom-input>
    
    const app = Vue.createApp({})
    
    app.component('my-component', {
      props: {
        foo: String
      },
      template: `
        <input 
          type="text"
          :value="foo"
          @input="$emit('update:foo', $event.target.value)">
      `
    })
    
    <my-component v-model:foo="bar"></my-component>
    

    7.非父子组件间数据传递

    • 对于兄弟组件的数据通信:它们有共同的父组件,我们可以通过父组件传递的方式实现数据通信。

    • 对于子孙组件的数据通信:可以通过 props 的方式向下逐层传递下去,也可以通过 $emit 将事件向上逐层传递。

    • 对于非关系组件的数据通信:通过使用一个空的Vue实例作为中央事件总线。

    // 定义事件总线
    let bus = new Vue()
    Vue.prototype.bus = bus
    
    // 定义发送事件
    this.bus.$emit('事件名称', data)
    
    // 定义接收事件 并在回调中接收参数
    this.bus.$on('事件名称', (data) => {      
    })
    
    

    8.动态组件如何使用

    通过使用保留的 <component> 元素,动态地把组件名称绑定到它的 is 特性,可以实现动态组件:

    <component :is="currentView"></component>
    <button @click="changeView('A')">切换到A</button>
    <button @click="changeView('B')">切换到B</button>
    <button @click="changeView('C')">切换到C</button>
    

    keep-alive

    keep-aliveVue 提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在页面渲染完毕后不会被渲染成一个 DOM 元素。被 keep-alive 缓存的组件只有在初次渲染时才会被创建(若该组件是第一次渲染,会触发 created 事件,当再次切换显示该组件时,created 事件不会再次触发。),并且当组件切换时不会被销毁(通过修改 currentView 切换组件时,组件的 beforeDestroy 事件不会触发)。

     <keep-alive>
          <component :is="currentView"></component>
    </keep-alive>
    

    activated 和 deactivated 生命周期

    activated 和 deactivated 和我们之学习的生命周期函数一样,也是组件的生命周期函数。不过, activateddeactivated 只在 <keep-alive> 内的所有嵌套组件中触发。activated:进入组件时触发。deactivated:退出组件时触发。

    include 和 exclude

    includeexclude 是 keep-alive 的两个属性,允许组件有条件地缓存。
    include: 可以是字符串或正则表达式,用来表示只有名称匹配的组件会被缓存
    exclude: 可以是字符串或正则表达式,用来表示名称匹配的组件不会被缓存

    <keep-alive include="ComponentA,ComponentB">
          <component :is="currentView"></component>
    </keep-alive>
    

    9.key管理复用元素

    Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key attribute 即可:

    <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>
    

    现在,每次切换时,输入框都将被重新渲染

    VUE3

    1.创建

    const App = {
      data() {
        return {
          groceryList: [
            { id: 0, text: 'Vegetables' },
            { id: 1, text: 'Cheese' },
            { id: 2, text: 'Whatever else humans are supposed to eat' }
          ]
        }
      }
    }
    
    const app = Vue.createApp(App)//创建vue实例
    //添加组件
    app.component('todo-item', {
      props: ['todo'],
      template: `<li>{{ todo.text }}</li>`
    })
    
    const vm=app.mount('#components-app')//返回的是 根组件实例
    

    2.防抖

    可以在生命周期钩子的 created 里添加该防抖函数:

    app.component('save-button', {
      created() {
        // 用 Lodash 的防抖函数
        this.debouncedClick = _.debounce(this.click, 500)
      },
      unmounted() {
        // 移除组件时,取消定时器
        this.debouncedClick.cancel()
      },
      methods: {
        click() {
          // ... 响应点击 ...
        }
      },
      template: `
        <button @click="debouncedClick">
          Save
        </button>
      `
    })
    

    3.数组更新检测

    #变更方法

    Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

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

    你可以打开控制台,然后对前面例子的 items 数组尝试调用变更方法。比如 example1.items.push({ message: 'Baz' })

    #替换数组

    变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()concat()slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:

    example1.items = example1.items.filter(item => item.message.match(/Foo/))
    

    你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

    4.v-for

    方法

    在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:

    <ul v-for="numbers in sets">
      <li v-for="n in even(numbers)">{{ n }}</li>
    </ul>
    
    data() {
      return {
        sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
      }
    },
    methods: {
      even(numbers) {
        return numbers.filter(number => number % 2 === 0)
      }
    }
    

    v-for 里使用值的范围

    v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

    <div id="range" class="demo">
      <span v-for="n in 10">{{ n }} </span>
    </div>
    

    v-forv-if 一同使用

    当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里的变量

    多事件处理器

    事件处理程序中可以有多个方法,这些方法由逗号运算符分隔:

    <!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
    <button @click="one($event), two($event)">
      Submit
    </button>
    

    5.表单输入绑定

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

    • text 和 textarea 元素使用 value property 和 input 事件;
    • checkbox 和 radio 使用 checked property 和 change 事件;
    • select 字段将 value 作为 prop 并将 change 作为事件。

    在文本区域插值不起作用,应该使用 v-model 来代替。

    <!-- bad -->
    <textarea>{{ text }}</textarea>
    
    <!-- good -->
    <textarea v-model="text"></textarea>
    

    修饰符

    #.lazy

    在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组织文字时)。你可以添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步:

    <!-- 在“change”时而非“input”时更新 -->
    <input v-model.lazy="msg" />
    

    #.number

    如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

    <input v-model.number="age" type="number" />
    

    这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

    #.trim

    如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

    <input v-model.trim="msg" />
    

    6.Props传值

    给 prop 传入一个静态的值:

    <blog-post title="My journey with Vue"></blog-post>
    

    通过 v-bind 或简写 : 动态赋值(JavaScript表达式),例如:

    <!-- 动态赋予一个变量的值 -->
    <blog-post :title="post.title"></blog-post>
    
    <!-- 动态赋予一个复杂表达式的值 -->
    <blog-post :title="post.title + ' by ' + post.author.name"></blog-post>
    

    7.Prop 验证

    app.component('my-component', {
      props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function() {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function(value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        },
        // 具有默认值的函数
        propG: {
          type: Function,
          // 与对象或数组默认值不同,这不是一个工厂函数 —— 这是一个用作默认值的函数
          default: function() {
            return 'Default function'
          }
        }
      }
    })
    

    type 可以是下列原生构造函数中的一个:

    • String
    • Number
    • Boolean
    • Array
    • Object
    • Date
    • Function
    • Symbol

    type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认

     author: Person
    

    8.自定义处理 v-model 修饰符

    添加到组件 v-model 的修饰符将通过 modelModifiers prop 提供给组件

    v-model.capitalize="myText"自动分配到input元素的text上

    <div id="app">
      <my-component v-model.capitalize="myText">
        </my-component>
      {{ myText }}
    </div>
    
    const app = Vue.createApp({
      data() {
        return {
          myText: ''
        }
      }
    })
    
    app.component('my-component', {
      props: {
        modelValue: String,
        modelModifiers: {
          default: () => ({})
        }
      },
      methods: {
        emitValue(e) {
          let value = e.target.value
          if (this.modelModifiers.capitalize) {
            value = value.charAt(0).toUpperCase() + value.slice(1)
          }
          this.$emit('update:modelValue', value)
        }
      },
      template: `<input
        type="text"
        :value="modelValue"
        @input="emitValue">`
    })
    
    app.mount('#app')
    

    对于带参数的 v-model 绑定,生成的 prop 名称将为 arg + "Modifiers"

    <my-component v-model:foo.capitalize="bar"></my-component>
    

    9.获取DOM节点

    js方法

    var usernameObject= document.querySelector("#username");
    

    Vue方法

    <p ref="pa">huhu<p>
        
        
    console.log(this.$refs.pa.value);
    

    10.支持sass

    安装sass-loader node-loader

    node install -D sass-loader node-sass
    

    配置

    <style lang ="scss" scoped>
    </style>
    

    如果不添加scoped,则所定义的样式会被所有组件使用

    11.setup函数以及ref函数

    <script lang="ts">
    import { defineComponent, ref } from "vue";
    export default defineComponent({
      name: "App",
      setup() {
        const girls = ref(["大脚", "刘英", "晓红"]);
        const selectGirl = ref("");
        const selectGirlFun = (index: number) => {
          selectGirl.value = girls.value[index];
        };
        //因为在模板中这些变量和方法都需要条用,所以需要return出去。
        return {
          girls,
          selectGirl,
          selectGirlFun,
        };
      },
    });
    </script>
    
    <template>
      <img alt="Vue logo" src="./assets/logo.png" />
      <div>
        <h2>欢迎光临红浪漫洗浴中心</h2>
        <div>请选择一位美女为你服务</div>
      </div>
      <div>
        <button
          v-for="(item, index) in girls"
          v-bind:key="index"
          @click="selectGirlFun(index)"
        >
          {{ index }} : {{ item }}
        </button>
      </div>
      <div>你选择了【{{ selectGirl }}】为你服务</div>
    </template>
    
    • setup 函数的用法,可以代替 Vue2 中的 date 和 methods 属性,直接把逻辑卸载 setup 里就可以
    • ref 函数的使用,它是一个神奇的函数,我们这节只是初次相遇,要在template中使用的变量,必须用ref包装一下。
    • return出去的数据和方法,在模板中才可以使用,这样可以精准的控制暴漏的变量和方法。

    12.reactive函数

     setup() {
        const data = reactive({ //对比ref()函数
          girls: ["大脚", "刘英", "晓红"],
          selectGirl: "",
          selectGirlFun: (index: number) => {
            data.selectGirl = data.girls[index];
          },
        });
    
        return {
          data,
        };
      },
    

    修改完成<script>部分的代码后,还需要修改template部分的代码,因为我们这时候返回的只有data,所以模板部分的字面量前要加入data

    <div>
        <button
          v-for="(item, index) in data.girls"
          v-bind:key="index"
          @click="data.selectGirlFun(index)"
        >
          {{ index }} : {{ item }}
        </button>
      </div>
      <div>你选择了【{{ data.selectGirl }}】为你服务</div>
    
    

    13.Vue3 的生命周期

    Vue3 的生命周期比较多,我们需要一个个给大家讲。

    • setup() :开始创建组件之前,在beforeCreatecreated之前执行。创建的是datamethod
    • onBeforeMount() : 组件挂载到节点上之前执行的函数。
    • onMounted() : 组件挂载完成后执行的函数。
    • onBeforeUpdate(): 组件更新之前执行的函数。
    • onUpdated(): 组件更新完成之后执行的函数。
    • onBeforeUnmount(): 组件卸载之前执行的函数。
    • onUnmounted(): 组件卸载完成后执行的函数
    • onActivated(): 被包含在<keep-alive>中的组件,会多出两个生命周期钩子函数。被激活时执行。
    • onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
    • onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展现)。

    注:使用<keep-alive>组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用<keep-alive>组件解决。

    image-20201127100527097

  • 由于无法解释的神圣旨意,我们徒然地到处找你;你就是孤独,你就是神秘,比恒河或者日落还要遥远。。。。。。
    原文地址:https://www.cnblogs.com/momoli/p/14212227.html