Vue基本知识

Vue基本知识

MVVM

MVVM拆开来即为Model-View-ViewModel,有View,ViewModel,Model三部分组成。View层代表的是视图、模版,负责将数据模型转化为UI展现出来。Model层代表的是模型、数据,可以在Model层中定义数据修改和操作的业务逻辑。ViewModel层连接Model和View。
在这里插入图片描述
在这里插入图片描述
view对应dom元素,Vue对应VM,js数据对象对应Model
■View层:

视图层

在我们前端开发中,通常就是DOM层。

➢主要的作用是给用户展示各种信息。

■Model层 :

➢数据层

➢数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。

➢在我们计数器的案例中,就是后面抽取出来的obj, 当然,里面的数据可能没有这么简单。

■VueModel层:

➢视图模型层

视图模型层是View和Model沟通的桥梁。

➢–方面它实现了DataBinding,也就是数据绑定,将

Model的改变实时的反应到View中

➢另一方面它实现了DOM Listener, 也就是DOM监听,当DOM发生一.些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。

MVVM的原理

MVVM的原理: Vue框架是如何实现MVVM设计模式的
(1). new Vue()加载data对象
a. 将data对象打散,data内部的属性直接隶属于new Vue()对象
b. 将data中每个原始属性隐姓埋名,隐藏
c. 为data中每个属性请保镖:
1). Data中每个属性都有一对儿get/set方法
2). 今后只要想修改data中的变量都会自动触发set()
3). 在每个属性的set方法中,都自动植入一个notify()函数调用,只要试图修改data中的属性值时,都会自动调用set(),只要自动调用set()势必会自动notify()发出通知
(2). 加载虚拟DOM树:
a. 通过el属性值的选择器找到要监控区域的父元素
b. 创建虚拟DOM树
c. 扫描这个要监控的区域:
1). 每发现一个{{变量}}的元素,就将该元素的信息,记录进虚拟DOM树,同时首次用data中同名变量的值,代替页面中{{n}}的位置。
2). 每发现一个@事件名="函数名"的元素,就自动变为:
On事件名=“new Vue().函数名”
(3). 加载methods对象: methods对象中的所有方法,都会被打散,直接隶属于new Vue()和data中被打散的属性平级
所以,在methods中的方法中,想操作data中的属性,都可以写为"this.属性名"即可!
(4). 当触发事件时,自动调用new Vue()中methods中指定的函数,执行其中this.属性名的修改。修改会自动触发属性的set()方法,自动触发set()内部的notify函数:
a. 遍历虚拟DOM树,只找出受影响的个别元素
b. 利用虚拟DOM树提前封装好的DOM操作,只修改页面中受影响的个别元素!——效率高!
总结: MVVM的原理/Vue的绑定原理:
访问器属性+观察者模式+虚拟DOM树
什么是虚拟DOM树:
(1). 什么是虚拟DOM树: 仅保存可能发生变化的少量元素的精简版DOM树
(2). 优点:
a. 小, 遍历快!
b. 只更新受影响的元素,效率高!
c. 封装了DOM操作,无需我们程序员重复编码!

插值表达式{{}}

注意:差值表达式不会解析html元素

指令

v-on

注意:v-on指令事件绑定机制,缩写是@,在vue中,使用事件绑定机制,为元素指定事件处理机制,如果加了小括号,就可以给函数传参了

<div id="app">
        <input type="button" value="v-on指令" v-on:click="doit">
        <input type="button" value="v-on指令简写" @click="doit">

    </div>
  var app=new Vue({
        el:"#app",
        methods:{
            doit:function(){
                console.log('Do it');
            }
        }
    })

vue中如何获得事件对象 (vue中如何获得鼠标位置)
1). 如果事件处理函数不需要传入实参值时,则:
事件对象也是作为处理函数第一个参数值自动传入,也是在函数定义时,用一个形参e,就可接住——同DOM
示例: 使用e获得鼠标位置:

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
  div{
    width:300px; height:100px;
    margin:20px;
  }
  #d1{
    background-color:#aaf
  }
  #d2{
    background-color:#ffa
  }
  </style>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div id="d1" @click="doit">d1</div>
<div id="d2">d2</div>
</div>
<script>
var vm=new Vue({
  el:"#app",
  data:{
    
  },
  methods:{
    doit(e){//同DOM的e
      console.log(`点在d1的: x:${e.offsetX},y:${e.offsetY}`);
    }
  }
})
</script>
</body>

v-text

注意:v-text指令会直接覆盖元素内部的内容,而且没有闪烁问题

 <p v-text='messsge+"!!!!"'>哈哈哈</p>

v-html

可以解析html元素

  <p v-html="content"></p>
var app=new Vue({
        el:"#app",
        data:{
            content:'<a href="http://baidu.com">黑马程序员</a>'
        }
    })

v-cloak

防止用户短暂看到{{}}
问题: 因为vue代码是放在js文件中,所以,如果网速慢,vue代码暂时没有下载下来时,用户很可能短暂看到页面上的绑定语法,用户体验不好!
解决: 2个办法:

v-cloak
(1). 用v-cloak暂时隐藏带有{{}}内容的元素:
a. 2步:
1). 在包含绑定语法{{}}的元素上添加v-cloak属性
2). 在css中手动添加样式: [v-cloak]{ display:none }
b. 原理:
1). 用属性选择器查找所有带有v-cloak属性的元素,暂时隐藏
2). 当new Vue()渲染完成时,自动找到所有v-cloak属性,自动移除。
(2). 用v-text代替内容中{{}}语法,来绑定非HTML片段内容:
a. <元素 v-text=“原{{}}内容”></元素>
b. 原理:
1). 因为绑定语法写在了元素的属性里,所以,如果不是vue帮忙,用户无论如何是看不到元素属性中的内容的!
2). New Vue()读取到v-text时,会解析v-text的内容,替换元素开始标签和结束标签之间的内容
c. 强调:
1). 和v-html不同,v-text等效于{{}}等效于DOM中的textContent,所以如果v-text中包含HTML片段,是不会被编译,而是原样显示给人看!
2). v-text也是指令,所以v-text后的""中也可以写js表达式,比如字符串拼接!
3). 用了v-text,也不要在元素开始标签和结束标签直接写内容!因为会被v-text内容替换!

  <span v-cloak>{{msg}}</span>
  /* v-cloak能够解决插值表达式闪烁的问题*/
        [v-cloak]{
            display: none;
        }

v-if与v-show

v-show 和 v-if 对比
v-show 采用display:none方式隐藏元素,不改变DOM树,效率高!
当条件为false时,v-show只是给元素添加一个行内样式:display: none
v-if 采用添加删除元素方式控制元素显示隐藏,可能频繁修改DOM树,效率低!
当条件为false时,包含v-if指令的元素,根本就不会存在dom中
开发中如何选择:
当需要在显示与影藏之间切片很频繁时,使用v-show
当只有一次切换时,通过使用v-if

 <p v-if='isshow'>HHHHHHHHHHHHHHv-if</p>
      <p v-if='tel>=35'></p>>热死了</p>

v-if与v-else

控制两个元素二选一显示隐藏:
(1). <元素1 v-if=“条件”>
<元素2 v-else>
(2). 强调:
a. v-else后不要写条件!(同js程序中的else)
b. v-if 和 v-else之间必须连着写,不能插入任何其他元素
在这里插入图片描述

v-for指令

  <div id="app">
   <!--1.在遍历对象的过程中,如果只获取一个值,那么获取到的是value-->
  <ul>
    <li v-for="item in obj">{{item}}</li>
  </ul>
        <!-- 循环普通数组 -->
        <ul>
            <li v-for="(item,index) in arr">
                索引{{index}}
                值{{item}}
            </li>
        </ul>
        <!-- 循环对象数组 -->
        <h2 v-for="items in objarr">
            {{items.name}}{{items.id}}
        </h2>
        <!-- 循环对象 -->
        <p v-for="(val,key,i) in obj">
            键是{{key}} 值是{{val}} 索引是{{i}}
        </p>
    </div>
  var app = new Vue({
            el: "#app",
            data: {
                arr: ["北京", "上海", "深圳", "广州"],
                objarr: [{ name: "wyh", id: '1' },
                { name: "ldh", id: '2' }],
                obj:{
                    age:'19',
                    height:'183',
                    weight:'65kg'
                }
            }

        })

注意: v-for绑定key时key的值必须是字符串或者数字,保证数据的唯一性,key在使用中必须使用v-bind进行绑定
强调: v-for一定要放在那个要反复生成的元素上,而不是放在父元素上!
(5) 坑: 如果v-for遍历的是数组时,在程序中通过下标修改数组元素值,页面上的HTML元素不会自动更改!
比如: this.teachers[0]=“燕儿” 页面上是不会变的!
因为数组中的数字类型的下标012…无法添加访问器属性,也就不受监控!
解决: 今后,vue中修改数组中的元素值!必须用数组家函数!才能自动更新页面。因为函数都是受监控的。
比如: this.teachers.splice(0,1,“燕儿”)
删除0位置的1个元素,再在0位置放入"燕儿"
结果: 页面会自动变化!
key
笔试: 为什么v-for必须加:key
答: 因为v-for反复生成的多个元素,除了内容不同之外,从元素属性上来看多个元素毫无差别!每个反复生成的元素都是一样的。所以,如果将来修改了数组中一个元素时,v-for因为无法识别每个HTML元素,所以只能把所有的HTML元素重新生成一遍——效率低!
如果给每个元素都绑定:key="i"属性,则每个HTML元素上都有一个唯一的标识key=“0” key=“1” … 。当将来修改了数组中每个位置的元素时,只需要修改对应key的HTML元素即可,其他HTML元素保持不变!——效率高!
总结: 避免修改数组元素时,重新生成所有HTML元素,而是只更新其中一个HTML元素即可!提高修改效率!

获取v-for中的下标

注意:click绑定多哥事件中间用分号隔开

<div id="app">
        <ul>
            <li v-for="(item,index) in list" @click="change();getindex(index)">{{item}}</li>
        </ul>
    </div>

遍历三层数据

在这里插入图片描述

<table v-for="(table, index) in paramInfo.sizes"
           class="info-size" :key="index">
      <tr v-for="(tr, indey) in table" :key="indey">
        <td v-for="(td, indez) in tr" :key="indez">{{td}}</td>
      </tr>
    </table>

v-bind

注意:v-bind不支持驼峰命名法

v-bind是vue提供绑定属性的指令,相当于后面是解析表达式和变量了,v-bind指令可以被简写成一个:

  <div id="app">
        <img src="" alt="" v-bind:src=imgurl>
        <!-- 简写 -->
        <img src="" alt="" :src=imgurl>
        <!-- 点击加边框 -->
        <input type="button" @click="change" value="点击修改边框">
        <img src="" alt="" :src=imgurl :class="{border:flag}">
    </div>

v-model

v-model数据双向绑定,只能用于获取表单元素的值,数据实时更新

<input type="text" v-model="message">
 data: {message: "Clivan"},

在这里插入图片描述

属性绑定设置样式

style

 <div id='app'>
        <h1 :style="{color:'pink'}">这是一个H1标签</h1>
        <h1 :style="styleobj">这是一个H1标签</h1>
    </div>
  var app=new Vue({
            el:'#app',
            data:{
                styleobj:{
                    color:'pink'
                }
            },
        })

class

<style>
        .thin {
            font-weight: 200;
        }

        .italic {
            font-style: italic;
        }

        .active {
            color: red;
        }
    </style>
 <div id="app">
        <!-- 第一种方式,直接传入一个数组,用:绑定 -->
        <!-- flag==true?'active':''等同于{'active':flag},提高可读性 -->
        <h1 :class="['thin','italic',{'active':flag}]">这是一个很瘦并且倾斜的H1标签</h1>
        <!-- 第二种方式,传入一个对象,对象的属性是类名 -->
        <h1 :class="{thin:true,italic:true}">这是一个很瘦并且倾斜的H1标签</h1>
        <h1 :class="classobj">这是一个很瘦并且倾斜的H1标签</h1>
    </div>
 var app = new Vue({
            el: '#app',
            data: {
                flag: true,
                classobj: { thin: true, italic: true }
            },
            methods: {}
        })

组件

强调: 因为HTML标签名不区分大小写,所组件名如果包含多个单词,绝对不能用驼峰命名!必须用-分割多个单词。
比如: myCounter,错的。因为myCounter可能被转换为全大写或全消息的标签名,使用时会有歧义。

创建组件的方式

全局注册组件
Vue.component(‘Mycomp’, coml)

<div id="app">
        <!-- 如果要使用组件,直接把组件的名称以标签的形式写入即可 -->
        <Mycomp></Mycomp>
    </div>
   var coml = Vue.extend({
            /* template属性展示了组件的html结构 */
            template: ' <h3>这是使用Vue.extend创建的组件</h3>'
        })
        /*Vue.component(组件的名称,创建出来的组件模板对象) */
        //如果使用Vue.component定义全局组件的时候,组件名称使用了驼峰命名,则在引用组件的时候,
        //需要把大写的驼峰改为小写的字母,同时,两个单词之前,使用-链接
        Vue.component('Mycomp', coml)
        var app = new Vue({
            el: '#app',
            data: {},
        })

注意:组件有且只有一个根元素,在被控制的#app元素外部,使用template元素定义组件的html结构
注意:组件不能直接访问vue实例上data的数据

局部注册组件

 <div id="app">
        <login></login>
    </div>
    <template id="tml">
        <div>
            <h1>这是通过template元素定义的组件结构</h1>
        </div>
    </template>
var app = new Vue({
            el: '#app',
            components: {
                //定义实例内部私有组件
               login: {
                    template: "#tml"
                }
            }
        })

组件中的data为什么是一个函数?

因为如果多次使用同个组件,并操作其数据时,为了保证每个组件都有自己独立的数据,需要用函数return数据,这样每次得到的数据不变,但是内存地址不同。

父子组件传值

我们知到了子组件是不能弓|用父组件或者Vue实例的数据的。但是,在开发中,往往一些数据确实需要从上层传递到下层:比如在一个页面中,我们从服务器请求到了很多的数据。
其中一部分数据 ,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
这个时候,并不会让子组件再次发送一个网络请求 ,而是直接让大组件(父组件)将数据传递给小组件(子组件)。

父子组件访问件

1.父组件访问子组件用$chilidren和 $refs, $children是子组件构成的数组
2.子组件访问父组件用 $parent /* 是访问最近的父组件 */

父组件向子组件传值

父组件可以在引用子组件的的时候通过属性绑定v-bind的形式,把需要传递给子组件的数据定义

props也可以写成对象,里面写数据对应的类型,默认值

 <div id="app">
        <coml v-bind:parentmsg='msg'></coml>
    </div>
 var app=new Vue({
            el:'#app',
            data:{
                msg:'这是父组件的数据'
            },
            components:{
                /* 默认子组件无法访问到父组件中data的数据和methods中的方法 */
                coml:{
                    template: ' <h1>这是子组件,{{parentmsg}}</h1>',
                    /* 只有在props数组中定义才能使用,props里面的数据都是只读的,不能被修改 */
                    props:['parentmsg']
                }
            }
           
        })

父组件向子组件传递方法

父组件向子组件传递方法使用的是事件绑定机制

  <div id="app">
        <coml @fun='show'></coml>
    </div>
    <template id="tml">
        <div>
            <h1>这是子组件</h1>
            <input type="button" value="点击我触发父组件的fun方法" @click='cli'>
        </div>
    </template>
 var coml = {
            template: '#tml',
            data() {
                return {
                    sonmsg: '数据'
                }
            },
            methods: {
                cli() {
                    // 通过this.$emit触发,后面还可以传参
                    this.$emit('fun', 123, this.sonmsg)
                }
            }
        }
        var app = new Vue({
            el: '#app',
            data: {
                fathermsg: null
            },
            methods: {
                show(data1, data2) {
                    console.log('调用了父组件的show方法' + data1 + data2);
                    this.fathermsg = data2;
                    console.log(this.fathermsg);
                }
            },
            components: {
                coml
            }
        })

计算属性 computed

 <div id="app">
        firstname<input type="text" v-model="msg">+lastname<input type="text" v-model="msg1">=fullname<input type="text"
            v-model="msg2">
    </div>
 var login = {
            template: ' <h1>登录组件</h1>',
        }
        var register = {
            template: ' <h1>注册组件</h1>',
        }
        var app = new Vue({
            el: '#app',
            data: {
                msg: '',
                msg1: '',
            },
            /* 在computed中可以定义一些属性,这些属性叫计算属性,计算属性本质就是方法 */
            computed: {
                /* 计算属性在引用的时候一定不要加()调用 */
                /* 只要计算属性这个函数内部中的data发生了改变,就会触发这个函数 */
                /*computed里面的数据如果没有改变,则会缓存  */
                msg2:function(){
                    return this.msg+'-'+this.msg1;
                }
            },
        })

solt的使用

如何去封装这类的组件呢?

它们也很多区别,但是也有很多共性。

如果,我们每一个单独去封装一个组件 ,显然不合适:比如每个页面都返回,这部分内容我们就要重复去封装。口但是,如果我们封装成一个,好像也不合理:有些左侧是菜单,有些是返回,有些中间是搜索,有些是文字,等等。

如何封装合适呢?抽取共性,保留不同。

最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。

一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。

是搜索框,还是文字,还是菜单。由调用者自己来决定。

这就是为什么我们要学习组件中的插槽slot的原因。

样式一样的不改动,不同的地方用插槽

<div id="app">
      <!-- slot里面要写的东西 -->
    <cpn> <button>btn</button></cpn>
    <cpn></cpn>
  </div>
    <template id="tml">
        <div>
            <h1>哈哈哈</h1>
            <!-- slot里面可以给默认值,如果组件里面没有写就使用默认值 -->
            <slot><p>hhh</p></slot>
        </div>
    </template>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
          const cpn={
            template: '#tml',
        }
        const app=new Vue({
            el:'#app',
            data:{},
            components:{
                cpn
            }
        })

具名slot

<div id="app">
    <cpn> <h2 slot="left">66666</h2></cpn>
  </div>
    <template id="tml">
        <div>
            <h1>哈哈哈</h1>
            <slot name="left"><span>默认值</span></slot>
            <slot name='right'><span>默认值</span></slot>
        </div>
    </template>

Vue生命周期

 <div id="app">
        <input type="button" value="修改msg" @click='change'>
        <p>{{msg}}</p>
    </div>
 var app = new Vue({
            el: "#app",
            data: {
                msg: '红火火恍恍惚惚'
            },
            methods: {
                change() {
                    this.msg = "no"
                }
            },
            beforeCreate() {
                console.log(this.msg);
                //这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
                //注意:在beforeCreate执行的时候,data和methods中的数据还没有初始化
            },
            //*重要
            created() {
                //这是第二个生命周期函数
                //在created中,data和methods已经被创建好了
                console.log(this.msg);
            },
            beforeMount() {
                //这是第三个生命周期函数,表示模板已经在内存中编辑完成,但是尚未渲染到页面中去
                console.log(document.querySelector('p').innerText);
            },
            //*重要
            mounted() {
                //这是第四个生命周期函数,表示内存中的模板已经被真实的挂载到了页面中
                //这个函数执行完成后就表示整个vue实例被创建完成,开始进行运行阶段
                console.log(document.querySelector('p').innerText);
            },
            //运行函数
            beforeUpdate() {
                //这个函数发生的时机是data被更新后执行的
                //beforeUpdate执行时输出的数据是未更新前的数据,此时data数据是最新的
                console.log(document.querySelector('p').innerText);
                console.log(this.msg);
            },
            updated() {
                //update执行时输出的数据是更新后的数据,此时页面与data中的数据已经保持同步了
                console.log(document.querySelector('p').innerText);
                console.log(this.msg);
            },
            //销毁阶段
            /* 当执行 beforeDestroy钩子函数的时候, Vue实例就已经从运行阶段,进入到了销毁阶段;
            当执行beforeDestroy 的时候,实例身上所有的data和所有的methods,
            以及过滤器、指....都处于可用状态,此时,还没有真正执行销毁的过程*/
            beforeDestroy() { },
            /* 当执行到destroyed函数的时候,组件已经被完全销毁了,此时,
            组件中所有的数据、方法、指令、过滤器.... 都已经不可用*/
            Destroyed() { }
        })

在这里插入图片描述

Vue过滤器

过滤器只能用于插值表达式或v-bind中,不影响原来的数据
什么是: 专门对变量的原始值进行加工后,再显示的特殊函数

为什么: 个别变量的原始值不能直接给人看!
比如: 性别 0和1 日期的毫秒数

何时: 如果一个变量的值不能直接给人看时,必须经过加工,才能给人看时

如何:
(1). 向Vue大家庭中添加过滤器函数
Vue.filter(“过滤器名字”, function(oldVal){ //接受一个变量的原始值
return 根据oldVal的不同,动态返回的新值
})
(2). 在绑定语法中使用过滤器函数:
{{变量 | 过滤器名 }}

结果:
(1). 变量的原始值不会立刻显示出来,而是先交给|后的过滤器函数
(2). 再将过滤器处理后的返回值,返回出来,显示在元素内容中

原理:
(1). Vue.filter(“过滤器名”, function(oldVal){ return 新值 })
定义一个过滤器函数,加入到Vue大家庭中备用
(2). 当new Vue()扫描到{{}}中的|时,会回Vue大家庭中查找相应名称的过滤器函数。
(3). 只要找到,就先将|前的变量原始值,交给过滤器函数的oldVal参数,经过过滤器函数的加工,返回新值。显示到当前绑定语法的位置。

  <div id="app">
        <!-- 过滤器格式 -->
        <p>{{msg | change}}</p>
    </div>
//定义一个全局的过滤器fliter,第一个参数已经被规定死了,永远都是过滤器前面的数据
        Vue.filter('change',function(data){
            return data.replace(/单纯/g,'邪恶')
        })
        var app=new Vue({
            el:'#app',
            data:{
                msg:'我是一个单纯的人,很单纯'
            },
            methods:{}
        })

Vue-resource

 <div id="app">
        <input type="button" value="get请求" @click='get'>
        <input type="button" value="post请求" @click='post'>
        <input type="button" value="jsonp请求" @click='jsonp'>
    </div>
 //请求过来的数据都在res.body里面
        var app=new Vue({
            el:'#app',
            methods:{
                get(){
                    this.$http.get('http://jsonplaceholder.typicode.com/users').then(function(res){
                        console.log(res);
                    })
                },
                //手动发起post请求默认没有表单格式,所以有的服务器处理不了
                post(){
                  //post请求,中间花括号空的部分为提交给服务器的数据这里默认,emulateJSON:true,将手动提交表单格式设置为application/x-www-form-urlencoded格式
                  //第一个是请求地址,第二个是我们提交给服务器的数据,第三个规定格式
                    this.$http.post('http://jsonplaceholder.typicode.com/users',{},{emulateJSON:true}).then(res=>{
                        console.log(res);
                    })
                },
                jsonp(){
                    this.$http.jsonp('http://jsonplaceholder.typicode.com/users').then(result=>{
                         console.log(result)
                     })
                }
            }

        })

使用ref获取dom元素

 <div id="app">
        <input type="button" value="点击获取value和h3中的文本" ref='mybtn' @click='getcontent'>
        <h3 ref="myh3">这是h3</h3>
        <login ref="mylogin"></login>
    </div>
    <template id="tml">
        <div>
            登录组件
        </div>
var login={
            template: '#tml',
            methods:{
                show(){
                    return  console.log('调用了show方法');
                }
            }
        }
        var app=new Vue({
            el:'#app',
            methods:{
                getcontent(){
                    console.log(this.$refs);
                    console.log(this.$refs.myh3.innerText);
                    console.log(this.$refs.mybtn.value);
                    console.log(this.$refs.mylogin.show());
                }
            },
            components:{
                login
            }

        })

Vue-router的基本使用

router-link默认会渲染为一个a标签
router-view这是vue router提供的,充当占位符,将来匹配到的组件就会在其中展示

<div id="app">   
       <!-- tag可以设置对应元素 -->
       <router-link to="/login" tag="span">登录组件</router-link>
       <router-link to="/register">注册组件</router-link>
        <router-view></router-view>
    </div>
 var login = {
            template: ' <h1>登录组件</h1>',
        }
        var register = {
            template: ' <h1>注册组件</h1>',
        }
        //创建一个路由对象
        const routers = new VueRouter({
            //routes表示路由匹配规则,这个规则对象上有两个必须的属性:
            //属性1:是path,表示监听哪个路由链接地址
            //属性2是component,表示如果路由匹配到path则展示component对应的那个组件
            //注意component属性值必须是一个组件的模板对象,不能是组件的引用名称
            routes: [
                { path: '/login', component: login },
                //重定向redirect默认打开页面在login页面
                { path: '/', redirect: '/login' },
                { path: '/register', component: register },
            ]
        });
        var app=new Vue({
            el:'#app',
            //将路由规则对象注册到vue实例上,用来监听url地址的变化
            router:routers
        })

params和query传递参数

params

<router-link to="/login/18">登录组件</router-link>

query

 <router-link to="/login?name=wyh&age=18">登录组件</router-link>

使用chilidren属性实现路由嵌套

 <div id="app">
        <router-link to="/account">account</router-link>
        <router-view></router-view>
    </div>
    <template id="tml">
        <div>
            <h1>这是account组件</h1>
            <router-link to="/account/login">登录组件</router-link>
            <router-link to="/account/register">注册组件</router-link>
            <router-view></router-view>
        </div>
    </template>
  var account={
            template:'#tml'
        }
        var login = {
            template: ' <h1>登录组件</h1>',
        }
        var register = {
            template: ' <h1>注册组件</h1>',
        }
        //创建一个路由对象
        const routers = new VueRouter({
            routes: [
                { path: '/account',
                 component:account,
                 /* 使用childred实现子路由,并且前面不带/,否则永远以根路径开始请求 */
                 children:[{path:'login',component: login},
                {path:'register',component:register }] },
            ]
        });
        var app=new Vue({
            el:'#app',
            router:routers
        })

watch监听data和路由

watch属性用于监听指定数据的变化,并且触发里面的函数

 <div id="app">
        firstname<input type="text" v-model="msg">+lastname<input type="text" v-model="msg1">=fullname<input type="text"
            v-model="msg2">
        <router-link to="/login">登录组件</router-link>
        <router-link to="/register">注册组件</router-link>
        <router-view></router-view>
    </div>
 var login = {
            template: ' <h1>登录组件</h1>',
        }
        var register = {
            template: ' <h1>注册组件</h1>',
        }
        const router = new VueRouter({
            routes: [
                { path: '/login', component: login },
                { path: '/', redirect: '/login' },
                { path: '/register', component: register },
            ]
        });
        var app = new Vue({
            el: '#app',
            data: {
                msg: '',
                msg1: '',
                msg2: ''
            },
            router,
            watch: {
                msg: function () {
                    this.msg2 = this.msg + '-' + this.msg1
                },
                msg1: function () {
                    this.msg2 = this.msg + '-' + this.msg1
                },
                /* 这个函数有两个指定的形参,第一个是改变后新的数据,第二个是旧数据 */
                '$route.path': function (newval, oldval) {
                   if(newval=='/login'){
                       console.log('欢迎进入登录页面');
                   }else{
                       console.log("欢迎进入注册页面");
                   }
                }
            }
        })

路由导航守卫

vue-router传参

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

mixin混入

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

// 定义一个混入对象
var myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}

// 定义一个使用混入对象的组件
var Component = Vue.extend({
  mixins: [myMixin]
})

var component = new Component() // => "hello from mixin!"

当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。

比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。

vue中的el属性

每个vue2.0项目中我们都会看到入口文件(即main.js)中,在生成根实例时会配置el属性,而我们自己创建的组件中则不能配置该属性。

- - - - -

比方说我这里想获取自定义组件tabControl,并获取它的OffsetTop。就需要先获取该组件。
在组件内设置 属性 ref=‘一个名称(tabControl2)’,

然后 this.$refs.tabControl2 就拿到了该组件

切记:ref属性,而获取组件的时候要用$refs

获取 OffsetTop,组件不是DOM元素,是没有OffsetTop的,无法通过 点 .OffsetTop来获取的。就需要通过$el来获取组件中的DOM元素
在这里插入图片描述

响应式数组方法

因为vue是响应式的,所以当数据发生变化时,vue会自动检测数据的变化,视图会发生对应的更新。
vue中包含了一组观察数组编译的方法,使用他们改变数组也会触发视图的更新。

push() //往数组最后添加元素
pop() //删除数组中最后一个元素
shift() //删除数组中第一个元素
unshift() //在数组最前面添加元素
splice() //删除元素/插入元素/替换元素
    splice(start,length,元素)
    删除元素:第二个参数传入你要删除几个元素(如果没有传,就删除后面所有的元素)
    替换元素:第二个参数,表示我们要替换几个元素,后面是用于替换前面的元素
    插入元素:第二个参数,传入0,并且后面跟上要插入的元素
sort() //数组元素排序
reverse() //数组元素位置倒序

这里讲一下哪些数组操作不会引起视图更新?

1.通过索引值修改数组的元素
比如:this.books[0] = "深入浅出vue.js"
 
解决方法:
    1. this.books.splice(0,1,"深入浅出vue.js")//替换
 
    2. Vue.set(要修改的对象,索引值,修改后的值)
       Vue.set(this.books,0"深入浅出vue.js")
       或者this.$set(this.books,0,"深入浅出vue.js") (这也是全局 Vue.set 方法的别名)
 
 
 
2.修改数组的长度
this.books.length = 10

Vue computed和watch的区别

计算属性computed
支持缓存,只有依赖数据发生改变,才会重新进行计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化
computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
如果computed属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
侦听属性watch:
不支持缓存,数据变,直接会触发相应的操作;
watch支持异步;
监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
当一个属性发生变化时,需要执行对应的操作;一对多;
监听数据必须是data中声明过或者父组件传递过来的props中的数据.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值