vue基础指令与组件通信

基础语法

vue应用结构

  • 根实例

    1
    2
    <div id="app"></div>
    new Vue({ el: '#app'})
  • 组件vue实例

    1
    2
    3
    4
    5
    6
    7
    8
    <div id="app">
    <btn-component></btn-component>
    </div>
    Vue.component('btn-component', {
    data: function () {
    return: { count: 0 }
    }
    })

指令

1
2
3
4
5
6
<!--动态参数-->
<a v-bind:[attributeName]="url"></a>
<!--修饰符-->
<form v-on:submit.prevent="onSubmit"></form>
<!--缩写-->
<a :href="url"></a><a @click="eventname"></a>
  • v-for

    • 列表类型

      1
      2
      3
      4
      5
      6
      7
      8
      <!--数组-->
      <li v-for="(todo, index) in todos" :key="todo.id">
      {{ index }}: {{ todo.text }}
      </li>
      <!--对象-->
      <li v-for="(value, key, index) in objs">
      {{ index }}. {{ key }}: {{ value }}
      </li>
    • 列表响应

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      /********* 数组 *********/
      /**
      * 变异数组
      * push pop shift unshift splice sort reverse
      */
      this.todos.push({text: 'str', id: '111'})
      /**
      * 非变异数组
      * 返回新数组,会复用dom替换原来的数组
      * filter concat
      */
      this.todos.filter(function(item) {
      return item.text === 'str'
      })
      // 利用索引设置
      this.$set(this.todos, index, newValue)
      this.todos.splice(index, 1, newValue)
      // this.todos[1] = 'x' // 不是响应性的
      // 设置数组长度
      this.todos.splice(newLength)
      // this.todos.length = 2 // 不是响应性的
      /********* 对象 *********/
      // 响应式对象属性需要在data中添加和删除
      var vm = new Vue({
      data: {
      userProfile: {
      name: 'Anika'
      }
      }
      })
      // 修改对象属性
      this.$set(this.obj, 'name', 'str')
  • v-model

    1
    <input v-model="message">
  • v-on

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <button v-on:click="reverseMessage">Reverse Message</button>
    <!--按键修饰符-->
    <button v-on:keyup.enter="reverseMessage">Reverse Message</button>
    <!--事件修饰符-->
    <!-- stop prevent capture self once passive -->
    <button v-on:click.stop="reverseMessage">Reverse Message</button>

    <!--鼠标按键修饰符 left right middle-->
    <!-- Alt + C -->
    <input @keyup.alt.67="clear">
    <!-- Ctrl + Click -->
    <div @click.ctrl="doSomething">Do something</div>
    <!-- 有且只有 Ctrl 被按下的时候才触发 -->
    <button @click.ctrl.exact="onCtrlClick">A</button>
  • v-once

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

    1
    2
    3
    <span>{{ commonString }}<span>
    <!--注意防止xss攻击,只对可信内容使用html插值,或进行xss过滤-->
    <span v-html="htmlString"></span>
  • v-if

    1
    2
    3
    <div v-if="type === 'A'"> A </div>
    <div v-else-if="type === 'B'"> B </div>
    <div v-else> C </div>
  • 属性指令

    1
    2
    3
    <img :src="url">
    <a :title="string"></a>
    <a v-bind:title="string"></a>
  • 样式,自动添加前缀

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    data {
    isActive: true,
    isNext: false,
    activeClass: 'active',
    activeColor: 'red',
    fontSize: 30
    }
    <!--对象-->
    <div :class="{ active: isActive, 'next': isNext }"
    :style="{ fontSize: fontSize + 'px', color: activeColor, display: ['-webkit-box', '-ms-flexbox', 'flex'] }">
    <!--多重值,用于设置多前缀属性-->
    </div>
    <!--数组-->
    <div :class="[isActive ? activeClass : '', nextClass]"
    :style="[{color: activeColor}, {fontSize: fontSize + 'px'}]">
    </div>

实例

数据属性

  • data对象 -> 属性
  • 属性值改变,视图响应
  • 组件的data必须是个函数,使组件实例管理独立的数据

计算属性

  • computed对象
  • get、set

实例属性

  • $el、$data、$props、$refs
  • $root、$children、$parent
  • $options 自定义选项、$isServer、$listeners、$attrs

实例方法

  • 数据 $watch、$set、$delete
    • Vue.set() / this.$set()
    • $watch 自定义监听器 监听属性变化并异步执行
  • 事件 $on、$once、$off、$emit
  • 生命周期 $mount、$forceUpdate、$nextTick、$destroy
    • $forceUpdate 迫使实例重新渲染
    • $nextTick 将回调延迟到下次dom更新之后执行
      1
      2
      3
      4
      5
      6
      7
      //请求成功后 数据赋值
      this.goods = res.data

      // vue 在这个阶段才会把获取到的数据渲染完成到dom里,然后进行 dom 操作
      this.$nextTick(() => {
      ...
      })

生命周期钩子

  • created、beforeCreate
  • mounted、beforeMount
  • updated、beforeUpdate // data change
  • destroyed、beforeDestroy

组件

组件之间的数据传递

父传子 propsprops定义尽量详细

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vue.component('todo-item', {
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
},
template: '<li>这是个待办项</li>'
})
1
2
3
4
5
6
<ol>
<todo-item v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>

子传父v-on,$emit,监听子组件事件

1
2
3
4
5
6
7
// 父组件监听
<blog-post
v-for="..."
v-on:update:fontSize="postFontSize = $event"
></blog-post>
// 子组件blog-post按钮
<button v-on:click="$emit('update:fontSize', 0.1)"> btn </button>

.sync修饰符也可以实现

1
2
<!--.sync用在字面量对象-->
<blog-post v-bind:title.sync="postFontSize">

改变另一个组件的实例内部 vuex [大型应用]

其他情况

  • 访问根实例、父实例
    • $root、$parent // 小型
  • 访问子组件实例或子元素 ref
  • 依赖注入,与任意后代组件的属性传递
    • provide 指定提供给后代组件的数据/方法
    • inject 接收父代组件提供的指定属性

组件加载

缓存组件 keep-alive

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

异步加载

1
2
3
4
5
6
7
8
9
10
Vue.component('async-webpack-example', function (resolve) {  
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包,这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve) })


Vue.component( 'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component') )

单文件组件

  • 完整的语法高亮
  • commonJs 模块化管理
  • 组件作用域的css
  • 自动化构建步骤,使用预处理器

提高复用性

混入对象 minxis

  • Vue.minxin 全局混入
  • 添加组件选项:new Vue({minxis: […]}) / Vue.extend({minxis: […]})

自定义指令

  • Vue.directive(‘string’, {})
  • 钩子函数
    • bind
      • (el, binding, vnode, oldVnode) 参数只读
      • 共享数据 dataset —— data-*
    • inserted
    • update
    • componentUpdated
    • unbind

渲染

  • dom 节点树
  • 虚拟dom
    • 对真实dom的变化保持追踪
    • 虚拟节点Vnode

插件

插件类型

  • 全局方法/属性
  • 全局资源:自定义指令、自定义过滤器、过渡
  • mixin方法添加组件选项、Vue.extend()
  • Vue实例方法 Vue.prototype
  • 引入库

插件使用

  • 全局方法 Vue.use()

    1
    2
    3
    4
    5
    6
    Vue.use(MyPlugins)

    // 引入并调用vue-router
    var Vue = require('vue')
    var VueRouter = require('vue-router')
    Vue.use(VueRouter)
  • 开发插件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 引入单文件组件
    const warnTpl = require('./warnTpl.vue');
    // 定义插件对象
    const MyPlugins = {};
    MyPlugins.install = function (Vue, options) {
    ...
    // 注入组件
    const warnComp = Vue.extend(warnTpl)
    // 添加全局方法、实例方法
    Vue.$warn = Vue.prototype.$warn = (msg, time = 1000) => {
    new warnComp({ // 动态组件
    propsData: {
    msg,
    time
    }
    }).$mount()
    }
    }