整理笔记:关于VUE基础篇

1、基础用法

MVVM模式:

MVVM是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对 View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变能够自动传递给 View,即所谓的数据双向绑定javascript

模板语法和指令

普一般用:

v-cloak //vue 未解析以前 通常配合用 [v-cloak] {display: none;}

v-bind 或者缩写 <img :src="src" alt="" />
v-on   或者缩写 <button @click="greet">Greet</button>  

v-text  <span v-text="msg"></span> || <span>{{msg}}</span>
//v-text 权重比{{}}高

v-html  <div v-html="html"></div>

v-show  <div v-show="show"></div>
//显不显示

v-if  v-else-if v-else  //条件 存不存在
        <div v-if="status"></div>

v-model  //表单元素,双向绑定
        <input type="text" v-model="mess"/>

v-pre //不编译,当字符串输出
        <span v-pre>{{mess}}</span>

v-once  //内容解析一次,当改变值再改变也不映射修改
         <span v-once>{{mess}}</span>

循环v-for Array | Object | Number | Stringhtml

这个单独拿出来写 更清晰:
通常jsfor in是遍历key,而for of遍历value
一类:
data = {
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10'
}
data = [{},{},{}]
<div v-for="(value, index) in data">
    <span>{{value}}</span>
    <span>{{index}}</span>
</div> 


二类:
data={
    "key1":{
        "aa":"1","bb":"2"
    },
    "key2":{
        "aa":"2","bb":"4"
    }
}
<div v-for="(item,key,index) of data">
    <span>{{item}}</span>
    <span>用of就能访问到 key1|key2 :{{key}}</span>
    <span>{{index}}</span>
</div>

样式绑定

绑定 class
对象:
<div :class="{classNam1: 1 == 1, className2: 1 == 2}"></div>
单个:
<div :class="classObject"></div>

数组:
<div :class="[class1, class2, 'className3', active ? 'className4' : '']"></div>
对应的data
data: {
    class1: 'className1',
    class2: 'className2',
    active: true
}

绑定再方法上:
 <div :class="classObjectComputed"></div>
computed: {
    classObjectComputed: function(){
        return{
            className1: true,
            className2: true
        }
    }
}
-----------------------------------------------------------------------


绑定style 

在对象当中,CSS 的属性名要用驼峰式表达:fontSize 解析成 font-size

对象:
 <div :style="{color: color, fontSize: fontSize, backgroundColor: '#ccc'}"></div>
data: {
    color: 'red',
    fontSize: '12px'
}


数组:
<div :style="[styleObject, {backgroundColor: '#ccc'}]"></div>
data: {
    styleObject: {
        color: 'red',
        fontSize: '12px'
    }
}

事件修饰符 .**

<!--阻止事件冒泡.stop-->
    <div id="div1" class="stop" @click.stop="event1(1)">
    
    <!--使用事件捕获模式.capture-->
    <div id="div4" class="stop" @click.capture="event1(4)">
    
    <!--事件只做用自己.self,相似于已阻止事件冒泡-->
    <div id="div7" class="stop" @click.self="event1(7)">
    
    <!--阻止浏览器默认行为.prevent-->
    <a href="https://m.baidu.com" target="_blank" @click.prevent="prevent">dk's github</a>
    
    <!--只做用一次.once-->
    <a href="https://m.baidu.com" target="_blank" @click.once="prevent">dk's github</a>
    
    <!--修饰符能够串联.click.prevent.once-->
    <a href="https://m.baidu.com" target="_blank" @click.prevent.once="prevent">dk's github</a>

2、Vue实例化时基本属性

实例元素 el

实例化在哪一个容器里 若是有多个相同的实例元素则只有第一个起效。前端

##挂载方式一:
<div id="app"></div>
var vm = new Vue({
    el:"#app" //挂载方式一
})

----------------

##挂载方式二:
<div id="app"></div>
vm.$mount("#app"); //挂载方式二: 手动进行挂载
console.log(vm.$el) // 能够经过实例获取实例元素

数据对象 data

M(Model) 数据模型层 映射到V层。vue

关于视图不更新

方法一: vm.set()
对象用法:vm.$set(Object, key, value)
数组用法:vm.$set(Array, index, Value)

1.对于对象,若是要给对象添加新的属性,数据变化 视图没变化。java

Vue在初始化实例时进行双向数据绑定,使用Object.defineProperty()对属性遍历添加 getter/setter 方法,因此setter属性必须在 data 对象上存在时才能进行setter过程,触发视图响应。此时须要用到$set
#视图不更新:this.dataform.username = '123'; // 直接赋值 在视图上不显示

#视图更新:this.$set(this.dataform, 'username', '123'); //改用 $set 更新能够在视图上显示

2.对于数组,因为 JavaScript 的限制,Vue不能检测如下变更的数组。node

//如下两操做均没法触发视图更新。其他操做正常,另外若是用到splice删除后引发长度变化 注意
#视图不更新:this.arr[index] = val; 
#视图更新:this.$set(this.arr, index, val);

#视图不更新:this.arr.length = 2;
#视图更新:this.arr.splice(2);

//对于清空数组推荐
this.arr = [];
方法二:vm.forceUpdate()

但是若是咱们不想利用$set去设置,非要按照咱们第一种方式去写,能够实现么?答案是能够的,就是利用$forceUpdate了,由于你修改了数据,可是页面层没有变更,说明数据自己是被修改了,可是vue没有监听到而已,用$forceUpdate就至关于按照最新数据给渲染一下。git

change: function(index) {
    this.arr[index] = '9';
    this.$forceUpdate();
},
clearLen: function() {
    this.arr.length = 2;
    this.$forceUpdate();
}

事件处理器 methods

元素能够经过事件进行绑定事件github

计算属性 computed

主要是针对 data 的属性进行操做,this的指针默认指向实例vm。
能够像绑定普通属性同样在模板中绑定计算属性api

<div id="example">
  <p>本来值: "{{ basicNum }}"</p>
  <p>计算后的值: "{{ countNum }}"</p>
</div>
<script>
  var vm = new Vue({
  el: '#example',
  data: {
    basicNum: 0
  },
  computed: {
    // 计算属性的 getter
    countNum: function () {
      return Math.floor(this.basicNum*999/100);
    }
  }
})
</script>
// 设basicNum = 3  >> countNum = 29
// 设countNum = 28 报错 由于计算属性默认状况下不支持set设值

默认只有getter没有setting,只能读取不能修改。 须要支持修改的话 要手动加上去 like this:数组

<div id="app">
    <!--fullName.get 只被调用一次-->
    <p>{{fullName}}</p>
    <p>{{fullName}}</p>
    <p>{{fullName}}</p>
    <!--每次点击都会调用 changeName-->
    <input type="button" value="changeName" @click="changeName('Vue')">
</div>
<script>
var vm = new Vue({
    el: '#app',
    data: {
        firstName:'DK',
        lastName: 'Lan',
        newName: ''
    },
    computed: {
        fullName:{
            get: function(){
                return this.firstName + '.' + this.lastName
            },
            set: function(newValue){
                this.firstName = newValue
            }
        }
    },
    methods: {
        changeName: function(txt){
            this.newName = txt;
            //若是在这里改变 this.fullName 的值,则会再次自动触发对应的 getter
        }
    }
})
</script>

监听器 watch

当该属性发生改变的时候,自动触发,此项使用不当会影响性能,慎用

<div id="example">
  <p>输入的值: <input v-model="basicNum"></p>
  <p>计算后的值: "{{ countNum }}"</p>
  
</div>
<script>
  var vm = new Vue({
  el: '#example',
  data: {
    basicNum: 0
  },
  watch: {
    // 侦听 data属性 这个属性一旦变化 
    basicNum: function () {
      return Math.floor(this.basicNum*999/100);
    }
  }
})
//补充 computer 和 watch 还都支持对象的写法。
vm.$watch('obj', {
    // 深度遍历
    deep: true,
    // 当即触发
    immediate: true,
    // 执行的函数
    handler: function(val, oldVal) {}
})
</script>
computed与watch区别
  • 相同:
    computed和watch都起到监听/依赖一个数据,并进行处理的做用
  • 不一样:
    1.computed 建立新的属性, watch 监听 data 已有的属性
    2.computed 会产生依赖缓存
    3.当 watch 监听 computed 时,watch 在这种状况下无效,仅会触发 computed.setter

    {
        computed: {
            a: {
                get: function(){
                    return '';
                },
                set: function(newVal){
                    //会触发此项
                    console.log('set val %s', newVal);
                }
            }                 
        },
        watch: {
            a: function(){
                //不会被触发
                console.log('watch');
            }
        }    
    }

因此通常来讲须要依赖别的属性来动态得到值的时候可使用computed,对于监听到值的变化须要作一些复杂业务逻辑的状况可使用watch

过滤器 filters

<div id="app"> 
    <!-- 用法一:在双花括号中 -->
    {{ money | monerFilter }}
    <!-- 用法二:在表达式中  版本要求2.1.0+ -->
    <div v-bind:id="rawId | formatId"></div>
</div>

<script>
//定义方法一:vue选项中定义本地的过滤器
    var vm = new Vue({
        el: '#example',
        filters: {
          capitalize: function (value) {
            return "¥"+ value 
          }
        }
    })
//定义方法二:在vue实例化以前全局定义过滤器
    Vue.filter('formatId', function (value) {
      return value + "_total"
    })

    new Vue({
      // ...
    })
</script>

自定义指令 directives

除了默认内置的指令 (v-modelv-show),Vue容许注册自定义指令,可分全局指令和局部指令。

全局指令

<div id="app">
    <!--使用自定义的指令 v-myGlobalDir-->
    <input type="text" value="" v-myGlobalDir />
</div>
<script>
// 注册指令名称不用写前缀 v-
// 参数 element:使用指令的元素
Vue.directive('myGlobalDir',  function(element){
    //默认触发钩子函数的 inserted
    element.value = "世界和平";
    element.focus();
})

var vm = new Vue({
    el: '#app'
})
</script>

局部指令

<div id="app">
    <!--使用自定义的指令 v-privateDir-->
    <input type="text" value="" v-privateDir />
</div>
<script>
var vm = new Vue({
    el: '#app',
    directives: {
        //注册指令名称不用写前缀 v-
        // 参数 element:使用指令的元素
        privateDir: function(element){ 
            element.style.background = '#ccc';
            element.value = "世界和平";
        }
    }
})
</script>

指令的钩子函数

钩子函数能够理解成是指令的生命周期

  • bind:指令第一次绑定到元素时调用。可用于初始化。
  • inserted:被绑定元素插入父节点时调用
  • update:被绑定元素所在的模板更新时调用。
  • componentUpdated:指令所在组件完成一次更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

详细参数点击跳转官网

<div id="app">
    <!--使用自定义的指令 v-demo-->
    <input type="text" v-model="text" v-demo="{color:'red'}">
</div>

<script>
Vue.directive('demo', {
    //先于 inserted 触发,只调用一次 可用于初始化
    bind: function(element, binding, vnode){
        console.log('bind');
        element.style.color = binding.value.color
    },
    //被绑定元素插入父节点时调用 后于 bind 触发 
    //参数 element: 使用指令的元素; 参数 binding: 使用指令的属性对象; 参数 vnode: 整个 Vue 实例
    inserted: function(element, binding, vnode){
        console.log('inserted');
    },
    //被绑定元素所在的模板更新时调用,而不论绑定值是否变化
    update: function(element, binding, vnode){
        console.log('update');
    },
    //被绑定元素所在模板完成一次更新周期时调用。
    componentUpdated: function(element, binding, vnode){
        console.log('componentUpdated');
    }
})

var vm = new Vue({
    el: '#app',
    data:{
        text: '钩子函数'
    }
})
</script>

案例:自定义日期控件

<div id="app">
    <!--直接在 jQuery 环境下使用 datepicker 插件-->
    <input type="text" id="datepicker" data-date-format="yyyy-mm-dd"/>
    <!--使用 Vue 自定义指令 v-datepicker-->
    <input type="text" v-datepicker data-date-format="yyyy-mm-dd"/>
    <input type="button" value="保存" @click="save">
    <span>{{dataform.birthday}}</span>
</div>

//在没有使用 Vue 前,datepicker 插件在 jQuery 的环境下是这样使用
$('#datepicker').datepicker();

//使用 Vue 自定义指令 v-datepicker
Vue.directive('datepicker', function(element, binding, vnode){
    // data = dataform.birthday
    $(element).datepicker({
        language: 'zh-CN',
        pickTime: false,
        todayBtn: true,
        autoclose: true
    }).on('changeDate', function(){
        //因为不是手动在 input 输入值,因此双向绑定 v-model 无效
        //因此须要手动改变实例的数据模型
        var data = $(element).data('model');
        if(data){
            // datas = ['dataform', 'birthday']
            var datas = data.split('.');
            //context = vm
            var context = vnode.context;
            //循环属性自动添加
            datas.map((ele, idx) => {
                //最后一个属性就直接赋值
                if(idx == datas.length - 1){
                    context[ele] = element.value
                } else {
                    //动态添加属性
                    context = context[ele]
                }
            })
        }
    })
})

var vm = new Vue({
    el: '#app',
    data: {
        dataform: {}
    },
    methods: {
        save: function(){
            //使用 $set 更新 dataform
            //更多 $set 的使用在下面继续介绍
            this.$set(this.dataform)
        }
    }
})

3、 组件

组件source:
https://github.com/Wscats/vue...

组件注册使用

1.组件命名两个选择:
(1)短横线分隔命名 eg:<my-component-name>;
(2)驼峰命名 eg:<MyComponentName>;
2.组件data必须是个函数并return返回,强迫建立一个独立做用域,就算组件屡次复用不相互影响。

局部组件

<div id="app">
    <!--组件的使用-->
    <private-component></private-component>
</div>
//组件的定义 Vue.component(组件名称, {template})
var vm = new Vue({
    el: '#app',
    components:{
        'private-component': {
            template: '<h1>局部组件</h1>'
        }
    }
})

最终渲染的效果

<div id="app">
    <h1>局部组件</h1>
</div>

插槽

Vue 组件默认是覆盖渲染,为了解决这一问题,Vue 提出了 slot 分发内容,留给父组件注入内容。

//父组件
<div id="app">
    <component1>
        <h1>Sam</h1>
        <h1>Lucy</h1>
    </component1>
</div>

//组件留有slot
Vue.component('component1', {
    template: `
        <div>
            <h1>Tom</h1>
            <slot></slot>
        </div>`
})

>>渲染出来效果
<div id="app">
    <component1>
        <h1>Tom</h1>
        <h1>Sam</h1> //注入
        <h1>Lucy</h1> //注入
    </component1>
</div>
具名slot

若是要将组件里面不一样的子元素放到不一样的地方,那就为子元素加上一个属性 slot="名称",而后在组件定义的时候用名称对应位置 ,其它没有 slot 属性的子元素将统一分发到 里面

//父组件
<h1 slot="lucy">Lucy</h1> //在名字为lucy的slot注入内容


//组件内部
<slot name="lucy"></slot>
缩写

(v-slot:) 替换为字符#。例如v-slot:header能够被重写为#header

动态和异步组件

1.动态组件 is

<div id="app" style="display: none;">
    //切换动态组件
    <input type="button" value="changeLight" @click="changeLight" /> 
    <br/>
    //渲染读取动态组件
    <p :is="show"></p>
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            show: 'red',
        },
        methods:{
            changeLight: function(){
                this.show = this.show == 'red' ? 'green' : 'red';
            }
        },
        components: {
            red: {
                template: '<h1>Red</h1>'
            },
            green: {
                template: '<h1>Green</h1>'
            }
        }
    })
</script>
  • <keep-alive> 组件实例在第一次建立的时候被缓存下来

    <!-- 失活的组件将会被缓存!-->
    <keep-alive>
      <component v-bind:is="currentTabComponent"></component>
    </keep-alive>

2.异步组件
Vue.component('async-example', function (resolve, reject)
resolve 加载成功
reject 加载失败

<template>
<div>
    组件一 延迟300毫秒,从服务器加载
    组件二 不延迟从服务器加载
    <template v-if="loadComponent">
        <child></child>
        <child2></child2>
    </template>
    <button @click="toggle">点击异步加载组件</button>
</div>
</template>
<script>
import Vue from 'vue';
const child = Vue.component('child', function (resolve) {
    setTimeout(function () {
        require(['./child.vue'], resolve)
    }, 3000);
});
const child2 = Vue.component('child2', function (resolve) {
    require(['./child2.vue'], resolve)
});
export default{
    data: function () {
        return {
            loadComponent: false
        };
    },
    components: {
        child,
        child2,
    },
    methods: {
        toggle:function () {
            this.loadComponent = !this.loadComponent;
        }
    }
}
</script>

组件间的通信

1.父传子

父组件在引入子组件时上带属性过去,子组件props接收。
image.png

2.子传父

父组件在引入子组件时v-on订阅监听对应的数据,子组件经过$.emit数据发送给父
image.png

3.兄弟传兄弟

引入公共bus文件
image.png

4.引入插件vueX托管状态

动画和过分效果


参考资料:
官网:https://cn.vuejs.org/
学习笔记: https://github.com/Wscats/vue...

相关文章
相关标签/搜索