VUE(二)-options的五个大类

486 阅读7分钟

vue实例

  • 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例 开始的:当创建一个 Vue 实例时,你可以传入一个选项对象
  • const vm = new Vue(options)根据options里的内容返回一个vue实例(对象)命名为vm
  • 这个vm对象封装了对视图的所有操作,包括数据读写、事件绑定、DOM更新
  • vue是视图层的框架,没有包含网络层(ajax)
  • vm的构造函数是Vue,按照ES6的说法,vm所属的类是Vue
  • options(一个对象)是new Vue的参数,一般称之为选项或构造选项(构造函数后面的选项)


组件

  • 组件被vue实例使用

  • 组件可以由一个vue文件生成,也可以我们声明一个组件(内容和options一模一样,除了data必须用函数)

  • 组件名开头大写

options的五类属性

数据

  • data 内部数据
  • props 外部数据,也叫属性
  • propsData 用不着学
  • computed 倍计算出来的
  • methods 面向对象的函数,也就是使用时要obj.sayHi()(普通函数sayHi()
  • watch

DOM

  • el 挂载点
  • template 在完整版里的视图
  • render 在非完整版里的视图,用不着学
  • renderError 在非完整版里的视图失败了

生命周期钩子:

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • activated
  • deactivated
  • beforeDestroy
  • destroyed
  • errorCaptured 先不看,用到再查文档

资源

  • directives 指令
  • filters 过滤器(不要用了),用methods代替
  • components 组件,如Demo.vue

组合

  • parent 先不看,用到再查文档
  • mixins 混入
  • extends 扩展
  • provide
  • inject 注入

el--挂载点

你的组件、你的实例的挂载点。(index.html文件提供)

new Vue({
  el: "#app"
});

new Vue({}).$mount('#app')

提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

在实例挂载之后,元素可以用 vm.$el 访问。

如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount()手动开启编译。

提供的元素只能作为挂载点。不同于 Vue 1.x,所有的挂载元素会被 Vue 生成的 DOM 替换。因此不推荐挂载 root 实例到 <html> 或者 <body> 上。一般情况下el里面的内容是不会被看到的,除非网速特别慢

如果 render 函数和 template 属性都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板,此时,必须使用 Runtime + Compiler 构建的 Vue 库。

data -- 内部数据

两个用法:对象和函数(函数里返回对象就行了,优先使用函数
new Vue({
  data() {
    return {
      n: 0,
      array:[1,2,3]
    }
  }
}).$mount("#app");

如果你的data是写在组件中的,那么你的data必须是函数。

当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!vue在遇到data是个函数时,会先调用data来获取真正的data。每次调用data得到的对象是不一样的。

var vm = new Vue({
  data: { a: 1 }
})

var Component = new vue({
  data: function () {
    return { a: 1 }
  }
})

Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。原型上的属性会被忽略。data 应该只能是数据 - 不推荐观察拥有状态行为的对象。

实例创建之后,可以通过 vm.$data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.a 等价于访问 vm.$data.a


methods -方法

  1. 两个用法
  • 事件处理函数
  • 普通函数(直接在视图里调用,每一次更新渲染都会调用一次)
import Vue from "vue";
Vue.config.productionTip = false;

new Vue({
  data() {
    return {
      n: 0,
      array: [1, 2, 3, 4, 5, 6, 7, 8]
    };
  },
  template: `
  <div class=red>
  {{n}}
  <button @click="add">+1</button>  //事件处理函数
  <hr>
  {{filter()}}   //普通函数(直接在视图里调用,每一次更新渲染都会调用一次)
  </div>
  `,
  methods: {
    add() {
      this.n += 1;  //事件处理函数
    },
    filter() {
      return this.array.filter(i => i % 2 === 0);  //普通函数
    }
  }
}).$mount("#app");

methods:

methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。又因为vue实例代理了data里的属性,所有this.n指的就是data里的n。而{{n}}会把n渲染上去

箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。所以method不能用箭头函数


components--Vue组件

组件就是可复用的 Vue 实例,且带有一个名字,我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:


方法一:推荐使用,很模块化

  1. 新建一个vue文件Demo.vue,这个vue文件就是一个组件
  2. 在main.js中引入这个vue文件
  3. 在vue实例的components中声明这是我要用的组件,并且命名为Demo1
  4. 这样在这个Vue实例的template中就可以直接使用这个组件<Demo1/>
import Vue from "vue";
import Demo from "./Demo.vue";  //引入这个vue文件
Vue.config.productionTip = false;

new Vue({
  components: {
    Demo1: Demo  //在vue实例的components中声明这是我要用的组件,并且命名为Demo1
    //如果组件名就叫Demo,即Demo:Demo,那就写Demo
    //components: {Demo},
  },
  data() {
    return {
      n: 0
    };
  },
  template: `
  <div class=red>
  {{n}}
  <button @click="add">+1</button>
  <Demo1/>   //这样在这个Vue实例的template中就可以直接使用这个组件`<Demo1/>`
  </div>
  `,
  methods: {
    add() {
      this.n += 1;
    },
  }
}).$mount("#app");

复制代码

方法二:全局

  1. 在main.js里直接写一个全局组件,写组件名字和内容(内容和options一模一样,除了data必须用函数)
  2. 直接在任何Vue实例的template中就可以使用这个组件<Demo2/>
import Vue from "vue";
Vue.config.productionTip = false;

Vue.components('Demo2,{template:`<div>Demo2</div>`}') //在main.js里直接写一个全局组件,写组件名字和内容
new Vue({
  data() {
    return {
      n: 0
    };
  },
  template: `
  <div class=red>
  {{n}}
  <button @click="add">+1</button>
  <Demo2/>   //直接在任何Vue实例的template中就可以使用这个组件`<Demo2/>`
  </div>
  `,
  methods: {
    add() {
      this.n += 1;
    }
  }
}).$mount("#app");

复制代码

方法三:上面结合

在vue实例的components中写这个vue实例要用的组件,组件名为Demo3,内容为和options一模一样,除了data必须用函数

import Vue from "vue";
Vue.config.productionTip = false;

new Vue({
  components: {
    Demo3: { template: `<div>Demo2</div>` }  //在vue实例的components中写这个vue实例要用的组件,组件名为Demo3,内容和options一模一样,除了data必须用函数
  },
  data() {
    return {
      n: 0
    };
  },
  template: `
  <div class=red>
  {{n}}
  <button @click="add">+1</button>
  <Demo3/>   //直接在这个Vue实例的template中就可以使用这个组件`<Demo3/>`
  </div>
  `,
  methods: {
    add() {
      this.n += 1;
    }
  }
}).$mount("#app");

四个钩子

  1. created -- 实例出现在内存中后触发
  2. mounted-- 实例出现在页面中(挂载了)后触发
  3. updated -- 实例更新了后触发
  4. destroyed -- 实例从页面和内存中消亡了后触发
  5. 所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算。写在options里面,注意不是method里面

mouted就是append到页面中,而created是create到内存中,在潜意识里父组件先created,然后子组件created,其实顺序可以是不固定的,

一般情况下是父组件创建,子组件创建,子组件挂靠,父组件挂靠

结论:如果一个组件挂靠了,那么它的所有子孙组件都已经挂靠好了

利用这个结论我们可以在父组件mounted的时候,使用$children访问子组件进行数据绑定,此时子组件已经全部挂靠好(children不是响应式的,且没有顺序)

mounted() {
    this.$children.forEach(vm=>{
        vm.gutter = this.gutter
    })
  }

props-外部数据、属性

props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。


  • message="n"传入字符串
  • :message="n"传入vue实例的this.n数据
  • :fn="add"传入vue实例的this.add函数

一个组件的props指 属性名是我定义在我自己里面,我的template也用到了这些属性,但是属性值是从外面传给我的,上面代码的后两个中的双引号不是js代码的一部分

(所以我自己不能改这个属性值的,属性值是从外面来的,所以我自己就算改了,外面的改了之后我的属性值还是得跟着外面的来。我就是想要修改!请看最下面)

外面咋传给我?外面的Vue实例在引用我这个组件的时候传给我。

Demo.vue

<template>
  <div class="red">
    这是Demo内部
    {{message}} //我要用message
    <button @click="fn">点我</button> //我要用fn
  </div>
</template>

<script>
export default {
  props: ["message", "fn"] 
  //表示本组件可以接受一个参数message和fn,但是message和fn的值不是从我这里传入的,是外面传给我的。
  //所以message和fn就是Demo的外部数据(属性名是我定义在我自己里面,我的template也用到了这些属性,
  //但是属性值是从外面传给我的)
};
</script>

<style scoped>
.red{
    color: :red;
}
</style>

在main.js里

import Vue from "vue";
import Demo from "./Demo.vue";
Vue.config.productionTip = false;

new Vue({
  components: { Demo },
  data() {
    return { n: 0 };
  },
  template: `
    <div>
      <Demo message="n"/>      //在引用Demo组件时把他要用的message的值传入,值就为一个字符串n
      <Demo :message="n"/>      //在引用Demo组件时把他要用的message的值传入,值为这个Vue实例的data里的n
      <Demo :fn="f1"/>        //在引用Demo组件时把他要用的fn的值传入,值为这个Vue实例的methods里的f1
      </div>
  `,
  methods: {
    f1() {
      console.log("Hi");
    }
  }
}).$mount("#app");

props传递的是外部将要传进来的值(另一个组件套用这个组件时传的值),不同于data是内部自己定义的值,在options里面定义好props后,需要在外面(另一个组件)传值

例子(非完整版Vue)

代码

  1. 组件不可以修改props只能是外部给组件的

  2. 组件就是想要改它的一个props:money,也就是外部(父组件)给我total

  3. 可以!你通知外部你想咋改,外部来改,你不也就同时被改了吗

  4. 怎么通知?eventBus!但在Vue里面是

  • 儿子用$emit

    触发
    updata:money事件(同时传参数);

    {{money}}<button @click="$emit('update:money', money-100)">
  • 爸爸在引用儿子的时候用v-on监听updata:money事件,可以用$event获得那个参数,所以事件处理函数就为把参数给自己的total

    <Child :money="total" v-on:updata:money="total= $event"/>

    注意,完全等同于<Child :money.sync="total"/>(同步)(语法糖)

  1. 父亲data的total传给儿子props的money

  2. 儿子想咋改,写在$emit的第二个参数里;爸爸就会从v-on里用$event获取$emit的那个参数就知道儿子是想咋改的,爸爸就会把这个结果给自己的total。

  3. 当点击的时候,儿子触发'update:money'事件,此时父亲监听到'update:money'事件,调用"total= $event"代码,修改了total

  4. 爸爸的total改了,儿子的money不就给改了??!!成功

  5. 逻辑@click="$emit('update:money', money-100)"  写着行代码时就相当于发布了一个update:money事件,当你点击时触发事件,父亲监听到事件

  6. $emit传的参数可以由$event拿到

写一个(子)组件Child.vue

<template>
  <div class="child">
    {{money}}          //儿子这里要显示钱
    <button @click="$emit('update:money', money-100)">  
    //儿子每次点击按钮就是想花钱,可是钱是爸爸给的自己花不了。
    //那就每次花钱的时候触发花钱事件update:money,这个事件会把爸爸给的钱-100,也就是儿子想怎么把这个钱花掉
      <span>花钱</span>
    </button>
  </div>
</template>

<script>
export default {
  props: ["money"]  //儿子需要父亲给钱money
};
</script>


<style>
.child {
  border: 3px solid green;
}
</style>
复制代码

写一个(父)组件App.vue ,这就是非完整版要用的vue文件

<template>
  <div class="app">
    App.vue 我现在有 {{total}}
    <hr>
    <Child :money="total"  v-on:updata:money="total= $event"/>
    //爸爸在引用儿子的时候,先把自己的钱total给儿子money,在监听儿子的花钱事件updata:money,只要儿子花钱了,就把自己现在的钱total的金额=儿子想怎么花掉这钱$event。爸爸的total变了,儿子的money也变了
    //爸爸把total给儿子当他的money,要是儿子想改money就通知爸爸改爸爸的total
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  data() {
    return { total: 10000 };
  },
  components: { Child: Child }
};
</script>

<style>
.app {
  border: 3px solid red;
  padding: 10px;
}
</style>

总结:vue的修饰符sync的功能是:当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定的。sync是个语法糖。他是尤雨溪为我们写的<Child :money="total" v-on:updata:money="total= $event"/>的简写形式。