Vue的学习

VUE的理解

vue是一个前端JS库,用MVVM模式实现;

主要作用是动态构建用户界面

重要技术包括:模版与数据绑定(angular),组件与虚拟DOM(react),其中,模版就是HTML中套JS。表现形式就是:大括号表达式或者绑定指令。即模版里面的JS从哪读数据呢,则就需要从data里面读数据。实现静态页面变成动态页面,则就需要用到数据绑定技术。数据绑定分为两个方面,一个是页面能根据数据来显示,另一个最重要,即:只要我更新了数据,则页面就会发生变化。或者说我想让页面发生变化,那我就去更新数据。

而MVVM则是:M是model,即模型,也就是个数据对象,包含数据的对象,而包含的数据对象在VUE中就是data

V是view,即视图,在VUE中对应的就是模版页面,模版页面最终经过编译以后,生成的就是真实的DOM,当然在这个中间也会产生一些虚拟的DOM,最终显示给用户,展现在页面上

VM是ViewModel,即视图模型,在VUE对应的就是VUE的实例,不是VUE,是VUE的实例,这点需要搞清楚。而在VM中又包括两个东西,其中VM是 View 和 Model 之间的桥梁,用户在意的是视图,但是我们在编码操作的时候往往不是直接编码操作视图,而是去操作数据,然后让视图自动发生变化,或者说我在页面中输入一个内容,而内容能不能自动跑到数据里面去呢?也就是Model中。这都要靠VM,也就是ViewModel,即VUE的实例,简称VM。

在VM中,有两个方面,一个是Data Bindings ,翻译过来叫数据绑定,它能够让数据data从model中流向视图view中;另一个方面,是有DOM监听,即DOM Listeners,利用DOM监听,来让数据,从页面View流向Model中去,这主要体现在 v-model 指令上,即在输入框内输入一些内容,而此时输入框有 v-model 的话,则数据会自动跑到Model的data里面去。

为什么能跑到Model中去呢?

因为在输入框input上面绑定了一个监听,这个监听就是输入改变的监听,绑定监听则必然指定了回调函数,也就是说,当输入改变的时候,这个回调函数在干什么呢?两个事情,第一:读取最新输入的值;第二步,将最新的值保存到对应的data属性上。而一旦保存到data属性上,下面就是数据绑定的流程了, 就没DOM监听什么事了。也就是说,在DOM事件监听这条线上,只负责绑定事件监听,并且在事件监听的回调函数中,将最新的数据保存到data上去。这就是双向数据绑定的过程,也就是数据有两个方向的流向。
Vue的学习_第1张图片

new Vue({
  el: '#app',
  components:{ APP },
  //template的作用:若有这个属性,则把 template: '' 当成一个模版去渲染解析, 而这个模版里面包含一个 App 的组件标签。其中在Vue中,定义一个组件以后,必须要去注册,如果不注册是不知道组件标签名的。而配置components就是用来注册组件的。
  //components的完整写法是:components: {App : App},其中右边是组件,而左边则是给它起的名称,而这名称就是组件的标签名
  template: ''
})

Vue的生命周期

  • beforeCreate:创建实例之前执行的钩子函数
  • created:创建实例之后执行的钩子函数
  • 是否有el选项,如果有就可以执行编译模版,也就是把data对象里面的数据和Vue语法声明的模版编译成浏览器可读的html。如果没有el,那就用vm.$mount()去挂载模版
  • beforeMount:将编译完成的html挂载到对应虚拟DOM时触发的钩子函数
  • 将编译完成的html替换el属性所指向的DOM
  • mounted:编译好的html挂载到页面完成后执行的事件钩子函数
  • 实时监控数据变化,并随之更新DOM
  • beforeUpdate:更新数据之前执行的钩子函数
  • updated:更新数据之后执行的钩子函数
  • 实例销毁
  • beforeDestroy:实例销毁之前执行的钩子函数
  • destroyed:实例销毁完成后执行的钩子函数

runtime-compiler和runtime-only的区别

Vue的学习_第2张图片

  • runtime-compiler中,用App的步骤:
    1. 先把App做一个注册
    2. 注册完成以后,在template中使用这个组件
  • runtime-only中,用App的方式:使用render属性,名称为渲染,是个函数,即其右边是一个箭头函数

Vue的运行过程:

Vue的学习_第3张图片

  1. template保存到Vue中的options
  2. 再把template进行解析parse,把template解析成ast,也即是抽象语法树(abstract syntax tree
  3. 然后再把抽象语法树经过compile编译,编译成render函数,其中render函数的核心是用了createElement方法,即创建一个元素
  4. 通过render函数把template最终翻译成虚拟DOM
  5. 把虚拟DOM渲染成真实的DOM,并显示在页面上

总结:runtime-only的性能更,代码更
注意:vue-loader是用来加载Vue文件,而解析Vue文件则是用vue-template-compiler,也就是将Vue中的template解析成render函数。

vm.$nextTick( [callback] )

用法:当你修改了data的值以后,如果想马上获取dom元素的值,是不获取不到更新后的值,所以就需要使用$nextTick这个回调,它是在下一次 DOM 更新循环之后,再去执行的回调函数。也就是让修改后的data值重新渲染更新到dom元素之后在获取。

keep-alive

  1. 用法:keep-alive标签用于包裹router-view标签,就可以保对应的证组件不会被频繁的销毁或者创建,即

    <keep-alive>
      <router-view>
    <keep-alive>
    
  2. 属性之exclude,作用是排除一些组件,即

    //注意:这里不用加空格,其次,Profile,User是组件里面的name属性值
    <keep-alive exclude = "Profile,User">
      <router-view>
    <keep-alive>
    

默认路由的写法

正确写法:

{
  	path: '',
    redirect: '/home'
},

错误示范:

{
  	path: '',
    redirect: Home
},

Vue的过滤器

定义全局过滤器

//定义全局过滤器
Vue.filter('toUpper', function(value) {
    return value.toUpperCase()
})

//使用:既可以在  双花括号插值  中使用,又可以用在  v-bind 表达式
<h2>{{message | toUpper}}</h2>

定义局部过滤器

new Vue({
        el: '#text',
        data: {
            message: 'fjsalfjla'
        },
        filters: {
            toUpper: (value) => {
                return value + '这又是一段拼接的字符串'
            }
        }
    })
//使用:当全局过滤器和局部过滤器重名时,会采用局部过滤器。
<h2>{{message | toUpper}}</h2>

作用:把要显示的数据进行格式化处理后再显示。即通过定义过滤器,实现一些常见的文本格式化
好处:因为定义的是全局过滤器,所以定义好之后可以全局使用,还可以反复使用。
注意:当全局过滤器和局部过滤器重名时,会采用局部过滤器。

所有指令的共性:所有指令都是用来操作指令属性所在的标签对象的,不管是内置的还是自定义的

自定义指令

1). 注册全局指令

//全局指令的 directive 没有 s 
Vue.directive('my-directive', function(el, binding){
	/*
	* el:这是个标签,是 指令属性 所在的 标签对象
	* binding:包含一些指令相关属性数据(value)的对象
	* 自定义指令和过滤器很像,第一个参数是指令的名字,第二个参数是个函数,作用是用来解析指令的
	*/
    el.innerHTML = binding.value.toUpperCase()
})

2). 注册局部指令

//局部指令的 directive 有 s 
directives : {
    'my-directive' : function(el, binding) {
        el.innerHTML = binding.value.toLowerCase()
    }
    //或者把 function 去掉
    'my-directive'(el, binding) {
        el.innerHTML = binding.value.toLowerCase()
    }
}

实例

Vue.directive('upper-text', function (el, binding) {
  	//toUpperCase():把value的值全部转化为大写
    el.textContent = binding.value.toUpperCase()
  })
new Vue({
    el: '#demo',
    data: {
      message: 'HA HA HA'
    }, 
    directives: { // 局部指令, 只能当前vm有效
      'lower-text'(el, binding){
        //toLowerCase():把value的值全部转化为小写
        el.innerText = binding.value.toLowerCase()
      }
    }
  })
new Vue({
    el: '#demo2',
    data: {
      message: 'HE HE HE HE'
    }
  })
//结构部分
<div id="demo">
  <p v-upper-text="message"></p>
  <p v-lower-text="message"></p>
</div>

<div id="demo2">
  <p v-upper-text="message"></p>
  <p v-lower-text="message"></p>
</div>

局部指令和全局指令的区别:局部指令只对当前Vue实例有效,而全局指令对所有Vue的实例有效

V-text、V-html、{{}}

Vue的学习_第4张图片
v-text插值语法的区别:

指令v-text是给 p 标签指定标签体文本,至于这个 p 标签里面以前有没有值,根本不关心,因为就算有值也不会显示,即拥有了(娶了)v-text指令以后,以后的全部重心都是v-text里面的值;而插值语法只是 p 这个文本标签节点的一个部分而已,跟(娶了小妾一样,即不是全部),也就是说用插值语法,则 p 标签里面还可以放其他内容,但是用了指令v-text,那么 p 标签里面,你就啥也不能放了。

v-textv-html的区别:

一个解析文本,一个解析HTML

计算属性和监视

  1. get是用来动态计算来产生值,而set是监视这个属性值的变化
  2. Vue控制的所有回调函数this都是vm/组件对象
  3. 视图view模版中,访问的变量或者表达式的值,访问的都是vm(Vue的实例)的属性,然后这些属性对应的get方法,可以去访问data对应的属性值。
computed: { // 计算属性
         fullName1() { // 相当于getter
             console.log('fullName1()')
             return this.firstName + '-' + this.lastName
         },

         fullName3: {
             get() {
                 return this.firstName + '-' + this.lastName
             },
             //计算属性set调用时机:当前属性的值发生改变
             set(value) {
                 console.log('fullName3 set()', value)
                 const names = value.split('-')
                 this.firstName = names[0]
                 this.lastName = names[1]
             }
         }
},
// 监视
watch: {
    // 监视firstName
    firstName(value) { // firstName的值变化了
        this.fullName2 = value + '-' + this.lastName
    }
}

// 监视lastName
vm.$watch('lastName', function(value) { // lastName的值变化了
    console.log('lastName', value)
    this.fullName2 = this.firstName + '-' + value
})

组件间通信

通信(至少有两个组件):通信是有方向的,假设A向B通信,即A向B中传递一个数据,注意这个数据是一般是属性,而不是函数,即是非函数数据,是可以显示的数据。当然了,也可以是B向A通信。总结:通信就是传递数据;通信有方向。

组件有组件之间的关系:父子关系,祖孙关系,兄弟关系或者其他(表侄关系)。

Props通信:通信双方最好是父子关系,可以是父向子,也可以是子向父,即可以是双向的。利用props什么时候是父向子通信呢?答:传递一般属性时,一般属性是指属性值不是函数的时候称为一般属性。如果想用props来向子向父通信呢?答:用传递函数的方法或者ref。

自定义事件

事件:1,绑定监听 2,触发(分发)事件

语法:

this.$emit('myevent',value)

其中myEvent是事件名称,value是需要传递的值,当然这个值也可以不写。

调用语法:

<my-component v-on:myevent="doSomething">my-component>

注意:这个绑定监听的操作必然发生在my-component组件所在的父组件里面。因为只有在父组件里面才有这个标签。有了标签以后,才能通过属性绑定自定义监听。

也就是绑定监听操作的代码要在父组件里面执行,而this.$emit('myevent',value)才在子组件里面执行。

vm.$on(event,callback)可以在父组件里面给子组件对象绑定监听,而在子组件内部分发事件,而事件监听的回调函数是定义在父组件身上的。

绑定监听的一方是收数据的,因为监听就有回调,回调就有形参,形参就能收数据

A向B发数据,则在A中写触发事件的代码,即用emit,而在B中写绑定监听的代码,即on

总线对象

用法:可以实现任意组件任意关系之间传递数据

核心:new一个bus作为总线对象,即var bus = new Vue();

或者在Vue的原型上做文章,即Vue.prototype.$globalEventBus = new Vue()

假设是A向B发信息,也就是发数据,或者称为发消息,则A中写触发事件的代码,在B中写绑定监听的代码。

在A中,bus.$emit("事件名称","要传递的数据")

在B中,bus.$on("事件名称", "需要调用的函数"),其中,"需要调用的函数"有两种写法,第一种是在B组件的methods中写好该函数,然后用this.写好的函数来完成该事件

第二种是直接写一个箭头函数出来,并且在箭头函数中处理传过来的数据

你可能感兴趣的:(javascript,vue.js)