vue.js 学习笔记

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

核心思想是:数据驱动、组件系统。

 

MVC和MVVM的区别?
  
  MVVM即Model-View-ViewModel的简写。即模型-视图-视图模型。模型(Model)指的是后端传递的数据。视图(View)指的是所看到的页面。视图模型(ViewModel)是mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将模型(Model)转化成视图(View),即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将视图(View)转化成模型(Model),即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。

  MVC是Model-View- Controller的简写。即模型-视图-控制器。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑。使用MVC的目的就是将M和V的代码分离。MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。MVC和MVVM的区别并不是VM完全取代了C,只是在MVC的基础上增加了一层VM,只不过是弱化了C的概念,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用,使开发更高效,结构更清晰,增加代码的复用性。
 
vue双向绑定原理?
  vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
var obj = {};
var demo = document.querySelector('#demo')
var inp = document.querySelector('#inp')
Object.defineProperty(obj, 'name', {
    get: function () {
        return val;
    },
    set: function (newVal) { //当该属性被赋值的时候触发
        inp.value = newVal;
        demo.innerHTML = newVal;
    }
})
inp.addEventListener('input', function (e) {
    // 给obj的name属性赋值,进而触发该属性的set方法
    obj.name = e.target.value;
});
obj.name = 'fei'; //在给obj设置name属性的时候,触发了set这个方法

 

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

 
Object.defineProperty(obj, prop, descriptor)

obj要在其上定义属性的对象。
prop要定义或修改的属性的名称。
descriptor将被定义或修改的属性描述符。

 

 

11个生命周期函数 

beforecreated:el 和 data 并未初始化 -------------在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

created:完成了 data 数据的初始化,el没有 -----------在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

beforeMount:完成了 el 和 data 初始化 --------在挂载开始之前被调用:相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。

mounted :完成挂载--------el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted:
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
该钩子在服务器端渲染期间不被调用。 

beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。 

updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。注意 updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated:
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}
该钩子在服务器端渲染期间不被调用。

activated:keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用。 

deactivated:keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用。 

beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。 

destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

errorCaptured:2.50版本新增 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数: 错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

 

vue-cli 主要目录结构:
  index.html:一般只定义一个空的根节点,在main.js里面定义的实例将挂载在#app节点下,内容通过vue组件填充。
  src/ App.vue:是项目主组件,也是项目所有组件和路由的出口,之后它会被渲染到项目根目录的 index.html 中显示出来,我们可以在这里写一些适合全局的css样式。
  src/ main.js:入口文件,引入了vue模块和app.vue组件以及路由router,我们需要在全局使用的一些东西也可以定义在这里面。
  src/router index.js:路由配置文件。

 

指令:
v-bind 属性的绑定 简写 " : "
v-if 控制一个元素是否显示(会对DOM进行创建和删除操作 有较高的切换性能消耗)
v-show 控制一个元素是否显示(切换了元素的display:none/block;样式,有较高的初始渲染消耗)
v-for 数据循环
v-on 事件绑定 简写 " @ "
v-model 数据的双向绑定

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>计算器</title>
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    </head>
    <body>
        <div id="app">
            <input type="text"  v-model="first" />
            <select v-model="opt">
                <option value="+">+</option>
                <option value="-">-</option>
                <option value="*">*</option>
                <option value="/">/</option>
            </select>
            <input type="text" v-model="last" />
            <input type="button" value="=" @click="add"/>
            <input type="text" v-model="result" />
        </div>
    </body>
</html>
<script type="text/javascript">
    var Vue = new Vue({
        el:"#app",
        data:{
            first:0,
            last:0,
            result:0,
            opt:"+"
        },
        methods:{
            add(){
                var jieguo = "parseInt(this.first)"+ this.opt + "parseInt(this.last)";
                this.result= eval(jieguo);
            }
        }
    })
</script>

 

v-cloak 使用v-cloak 能够解决插值表达式闪烁的问题
  [v-cloak] { display:none;}


v-on @ 事件修饰符:
  .stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡
  .prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)
  .capture:与事件冒泡的方向相反,事件捕获由外到内
  .self:只会触发自己范围内的事件,不包含子元素
  .once:只会触发一次

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>vue跑马灯</title>
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    </head>
    <body>
        <div id="app">
            <input type="button" value="" @click="love"/>
            <input type="button" value="不爱" @click="anlove" />
            <h4>{{msg}}</h4>
        </div>
    </body>
</html>
<script type="text/javascript">
    var Vue = new Vue({
        el:"#app",
        data:{
            msg:"爱你一万年!!!",
            setId:null
        },
        methods:{
            love(){
                if(this.setId != null){
                    return false;
                }
                this.setId = setInterval(() => {
                    var str = this.msg.substring(0,1);
                    var str2 = this.msg.substring(1);
                    this.msg = str2 + str;
                }, 200) 
            },
            anlove(){
                clearInterval(this.setId);
                this.setId = null;
            }
        }
    })
</script>

 

 


v-for:如果用v-for迭代数字的话,前面的count值从1开始
  <p v-for = "count in 10">这是第{{ count }} 次循环</p>

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>添加删除</title>
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>
        <style type="text/css">
        *{padding:0;margin:0;border:0;-webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
                box-sizing: border-box;}
        .add{padding:50px;}
        .add input{width:100px;border:1px #eee solid;height:40px;line-height:40px;text-align: center;}
        .biao{width:500px;margin-left:50px;}
            .biao ul li{overflow: hidden;border:1px #eee solid;line-height: 40px;}
            .biao ul li+li{border-top:none;}
            .biao ul li span{float: left;width:33.33%;text-align: center;cursor:pointer;}
            .biao ul li span+span{border-left:1px #eee solid;}
        </style>
    </head>
    <body>
        <div id="app">
            <div class="add">
                <input type="text" v-model="id"/>
                <input type="text" v-model="name"/>
                <input type="button" value="添加" @click="add"/>
            </div>
            <div class="biao">
                <ul>
                    <li v-for="item in list" :key="item.id">
                        <span>{{item.id}}</span>
                        <span>{{item.name}}</span>
                        <span @click="del(item.id)">删除</span>
                    </li>
                </ul>
            </div>
        </div>
    </body>
</html>
<script type="text/javascript">
    var Vue = new Vue({
        el:"#app",
        data:{
            id:"",
            name:"",
            list:[
                {id: 1, name: '天籁' },
                {id: 2, name: '雅阁' },
                {id: 3, name: '帕萨特'}
            ]
        },
        methods:{
            add(){
                var arr = {id:this.id,name:this.name}
                this.list.push(arr);
            },
            del(id){
                // console.log("aa");
                this.list.some((item,i)=>{
                    if(item.id == id){
                        this.list.splice(i,1);
                    }
                    return true;
                })
            }
        }
    })
</script>

 

 

组件化实例
  <div id="app">
    <app-nav></app-nav>
    <app-view>
      <app-sidebar></app-sidebar>
      <app-content></app-content>
    </app-view>
  </div>

 

在子组件中定义data ,data必须是个函数而不能是个对象
data:function(){
  return {
    content: "xiaozhong"
  }
}

 

在vue中我们可以通过ref="zjz"获取DOM节点  this.$refs.zjz.      ,进而来操作DOM

vue中单向数据流概念:子组件中只能使用父组件中传过来的值,而不能更改,如需更改需克隆一份修改父组件通过属性的方式向子组件传值,子组件通过事件触发的方式向父组件传值

vue组件的属性使用和不使用冒号的区别:加冒号的,说明后面的是一个变量或者表达式;没加冒号的后面就是对应的字符串字面量!

非父子组件间的传值:{
  1.vuex
  2.发布订阅模式---总线机制---Bus---观察者模式 not_father_son.html
}

插槽(slot):具名插槽,作用域插槽

 

使用animate.css :只要在需要动画的标签外的transition标签里添加对应属性,比如enter-active-class=“animated swing”,leave-active-class=“animated shake”即可

js动画效果:注意事件函数中所传递的参数及某些事件函数返回的函数
  1. 进入动画钩子:before-enter; enter; after-enter
  2. 离开动画钩子:before-leave; leave; after-leave
  3. 在enter钩子中的函数调用done()告诉VUE js动画完成
  4. 使用velocity.js动画库实现动画:Velocity(el,{样式属性},{duration:1000,complete:done})
  5. 中文文档:http://www.mrfront.com/docs/velocity.js/index.html

 

posted @ 2019-07-01 16:58  张小中  阅读(456)  评论(0编辑  收藏  举报