vue

Vue2.0+VUEX开发PO项目

Vue2.0+VUEX开发PO项目

Posted by BY Devin on November 1, 2018

简介

vuex : Vue组件中每個data变量,它就是一个状态,当应用程序足够庞大时,如果将这些状态集中管理就会非常方便,于是Vuex便应运而生

axios : src/utils/http.js 用于封装axios异步GET/POST/DELETE等方式获取数据

基于实践开发项目sst-PO system初步搭建:(vue-cli + vuex + axios)

npm install -g vue-cli

npm install axios vuex

MVVM

MVVM由Model,View,ViewModel 三部分构成,Model层代表数据模型(也可以在Model中定义数据修改和操作的业务逻辑),View代表视图层,负责将数据模型转化在页面展示,ViewModel是一个同步View和Model的对象。

在MVVM架构下,View和Model之间并没有直接联系,而是通过ViewModel进行交互,Model和ViewModel之间的交互是双向的, 因此View数据的变化会同步到Model中,而Model数据的变化也会立即反应到View 上。

ViewModel通过双向数据绑定把View层和Model层连接了起来,而View和 Model之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

VUEX

仅需要checkbox/radio等单一值改变情况下,使用VUEX是动态获取数据且改变时需要$set/$forceUpdate/$nextTick,单一改变时显得累赘, 使用以下方式定义函数生成静态数据,这样checkbox/radio只需要v-model改变值;

async ajaxTest(){
    // $api代表VUEX的modules文件夹,并非api文件夹
    let {data} = await this.$api.systemAutoRule.getData(); 
    conosle.log(data)
}

Model层(数据)改变而视图层(UI)没同步三种处理方式:

// First Kind
let test = 1;
this.$forceUpdate() // 强制深入层级重绘

// Second Kind
// 回调函数延迟到下次 DOM 更新循环之后执行
this.$nextTick([callback])

// Third Kind
this.$set(object,index,value); // 对象重绘(object:对象,index:索引,value:改成的值)

自定义组件Component

native:父组件绑定的事件跟子组件绑定的自定义事件名称相同时可用.native修饰符执行父组件原生事件:

组件HTML调用

// 特别注意是ref如需循环必须添加唯一的ref;
<test ref="testForm" my-message="hello" :myObject="{name:'Devin'}" :isShow="true" > 
    <div slot="title">
        <button> BUTTON </button>
    </div>
    <div> OTHER </div>
</test>

* 组件引用 

<template>
    <div>
        <div class="main">
            <slot name="title"></slot> // slot插槽使用:通过name对应特定内容
            <slot></slot>              // slot插槽使用:放置内容(除去特定)
        </div>
    <div>
</template>

<script>
import Test from '@/components/test'
export default{

    components: { Test } ,
    name      : "test" ,
    // 父级数据通信到子级
    props:{                                               
        myMessage:{ type : String , default : ''     },  
        myObject : { type : Object , default : ()=>{} },  // 注意类型为数组/对象的默认值需要函数返回,否则报错
    },
    watch:{
        isShow(val){ }                                    // 侦听父组件isShow变化而触发,注意像myMessage如果是API数据是无法侦听变化
    }
    
}

</script>

// 父级/祖级/同级调用子级组件函数

this.$refa["testForm"].toXX();

// 子级数据通信到父级


this.$emit()     触发事件 : 相对于JS调用函数 => toEvent(object)
this.$on         绑定事件 : 相对于JS定义函数 => function toEvent(object){ ... } 

// 两个组件之间需要进行通信,但是它们彼此不是父子组件
var bus = new Vue();

bus.$emit('say-hello', 'world')                          // 在组件 A 的 methods 方法中触发事件

bus.$on('say-hello', function (arg) {                    // 在组件 B 的 created 钩子函数中监听事件
  console.log('hello ' + arg); // hello world
})

自定义指令

尽管Vue推崇数据驱动视图的理念,有的情况下仍需要对普通DOM元素进行底层操作,自定义指令就是一种有效的补充和扩展,且自定义指令需要钩子函数;

// INPUT自动获取焦点

export default {
  update: function (el,binding) {
    if(binding.value.isShowList) el.querySelector('input').focus();
  }
}

// 比如VUE中使用jQuery插件:

<table id="testTable">
  <tr v-for="(el, lineIndex) in lines" v-line-inserted="lineIndex" >
   <td> <input name="bindSelect2" /> <td>
  </tr>
</table>

function renderLines(el, lineIndex){
  $("testTable tr").eq(lineIndex).select2({...});
}
 
Vue.directive('line-inserted', {
  inserted: function (el, binding) {
   var lineIndex = binding.value;
   renderLines(el, lineIndex);
  }
});

Computed 与 Watch使用与区别

computed是计算属性,依赖其它的属性计算得出最后的第三方值(自动侦听依赖其它的值改变而触发)

watch是去监听本身值的变化,然后执行相对应的函数( 侦听指定值改变而触发 )注意:computed中无法获取到API的数据,唯有使用watch

// computed页面加载时触发或关联数据改变时触发
computed:{
    num : function(val){
        return this.i * 2 ;   //必须要return返回;
    }
},

// 当data改变而自身随之改变
watch:{
    data:{
        deep:true,      // 深度监听,一般用于json属性某值改变
        immediate: true, // 用于首次即可执行(常用初始化获取API数据后父组件传递到子组件)
        handler:function(newVal,oldVal){
        }
    }
}

v-bind 动态绑定属性

特殊属性class

方法1. :class='[red,blue]'

方法2. :class='{ red:false , blue:true }';

特殊属性style

:style='json'( json:{ color:'red',backgroundColor:'blue' } json代表controller内的数据);

Event

element 事件默认参数 -> $event

阻止事件冒泡 -> Vue简写:@click.stop='Func';

阻止默认事件 -> Vue简写: @click.prevent='Func';

触发捕获事件 -> Vue简写: @click.capture='Func';

原生事件触发 -> @click.native ( 组件中自定事件名与原生事件名一致,native即使区分原生事件,比如el-radio使用click事件 )

export default 和 export 区别

export与export default均可用于导出常量、函数、文件、模块等 (export、import可以有多个,export default仅有一个)

通过export方式导出,在导入时要加{},export default则不需要

生命周期 (实际项目理解)

由于VUE是写在onload中所以不存在jquery的onready & onload说法,仍存在VUE自身DOM/数据生命周期,一般文档时就载入用黑下划线的事件;

  • beforecreated DOM、Data未初始化

  • created Data已初始化、DOM并没生成,用于新增数据

  • beforeMount DOM、Data均初始化

  • mounted 后端返回数据配合路由钩子处理虚拟DOM;

  • beforeDestory 删除组件前;

获取API:

  • axios默认不启用跨域异步访问(Access-Control-Allow-Origin),需要服务器(后端)开启才能使用;

  • 封装Axios全局使用: 参考PO目录 src/utils/http.js(包含TOKEN验证配置 + Vue + Axios + Element Message)

BUG

Failed to mount component: template or render function not defined

  • 原因:主要时vue-loader版本问题,根据官方设置default即可 https://github.com/vuejs/vue-loader/releases/tag/v13.0.0