Vue基础知识

  1. vue提供了内置变量,名字叫做$event,它是原生DOM的事件对象

  1. event对象

  • 事件处理函数会回调一个参数event,代表当前事件对象,event中有很多常用的方法和属性

  • currentTarget 此属性返回当前事件所绑定的对象。

  • target 此属性返回当前触发事件的对象,注意target是触发事件的对象,是真正的事件源。例:给div绑定一个事件,点击带文字的span后,target是span,而currentTarget是div。

  1. :init="",为数字 init=""为字符串

4.(x) => x + 6

相当于

function(x){        
     return x + 6;
}

箭头函数

1、ES6允许使用“箭头”(=>)定义函数

var f = a = > a

//等同于
var f = function(a){
   return a;  
}

2、如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

//无形参
var f = () => 5;
// 等同于
var f = function () { return 5 };

//多个形参
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

注意事项:

1、函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
var name = '张三';   
 var person = {
        name:'李四',
           age:18,  
        fav:function(){        
            console.log(this)
            console.log(this.name)  //李四
        }
}
person.fav();
 此时this指向的是使用它的对象,也就是person对象
var person2 = {
    name:'李四',
    age:18,
    fav: ()=>{
         // 当前this指向了定义时所在的对象(window)
         console.log(this);  // window
    }
}
person2.fav();

var let const

  • var

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。

例:变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变。a[6]=10

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10
  • let :

let所声明的变量一定要在声明后使用,否则报错。

在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”

上例中如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。

  • const

声明创建一个值的只读引用 (即指针),这里就要介绍下 JS 常用类型: String、Number、Boolean、Array、Object、Null、Undefined。其中基本类型有 Undefined、Null、Boolean、Number、String,保存在栈中;复合类型 有 Array、Object ,保存在堆中; 基本数据当值发生改变时,那么其对应的指针也将发生改变,故造成 const申明基本数据类型时,再将其值改变时,将会造成报错, 例如 const a = 3 ; a = 5 时 将会报错;但是如果是复合类型时,如果只改变复合类型的其中某个Value项时, 将还是正常使用;

Promise Async Await

Promise:将程序异步执行变成同步执行

  1. 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

  1. Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

格式:

//Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数
const promise = newPromise ((resolve,reject)=>{   
})
//用箭头函数表示
const promise =newPromise(function(resolve, reject){ 

});
  1. resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

  1. reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

  1. Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

then方法可以接受两个回调函数作为参数。

第一个回调函数是Promise对象的状态变为resolved(即Promise对象状态变为成功)时调用

第二个回调函数是Promise对象的状态变为rejected(即失败)时调用。

这两个函数都是可选的,不一定要提供。它们都接受Promise对象传出的值作为参数。

Promise对象的简单实例
function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});

//timeout方法返回一个Promise实例,表示一段时间以后才会发生的结果。过了指定的时间(ms参数)以后,Promise实例的状态变为resolved,就会触发then方法绑定的回调函数。

async:表示该方法下有promise请求

await:在需要调用promise的方法的前面加await

示例

    function one(){
        return 'I am one'
    }
    //假设two需要向后端发送请求,对方服务器的响应需要一定的时间
    function two() {
        return new Promise((resolve ,reject)=>{
            setTimeout(()=>{
                resolve('I am two')
            },3000)//等待3秒,以毫秒为单位
        })
    }
    function three() {
        return 'I am three'
    }
    async function run() {
        console.log(one())//但是console.log不会等到响应后再执行,此处就是异步执行
        console.log(await two())
        console.log(three())
    }

样式:<style lang="less" scoped>

  1. lang="less" 可定义样式中的子样式

2.scoped:该组件中设置的样式只在该组件中生效。添加scoped后vue自动给该组件中每个标签添加v-data-,

  1. /deep/:在父组件中直接修改自定义样式,

当使用第三方组件库时,如果有修改默认组件样式的需求,需要用到/deep/

/deep/h5 = [data-v-...] h5

//例1   left.vue和right.vue中都使用了<h5>
<style style lang="less" scoped>
h5{
  color=pink
}
<style>
//样式不生效,没有选中left.vue中的h5,因为没有 [data-v-...]

//例2
<style style lang="less" scoped>
/deep/h5{
  color=pink
}
<style>

组件的生命周期:组件从创建-运行-销毁的整个阶段,强调的是一个时间段

计算属性:描述依赖响应式状态的复杂逻辑

    • 一个数据的结果要依赖另一个数据的动态计算时使用

  1. 计算属性要有返回值

  1. 原始数据发生改变,计算属性会重新计算

  1. 计算属性可以绑定到表单中

<template>
  <div class="hello">
    {{ computeMsg }}<br>
    {{ msg }}
    <div> 
        <input v-model="msg" >
    </div>  
  </div>
  
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg:'hello'
    }  
  },
//计算属性
  computed:{
    computeMsg:function(){
      return this.msg.toUpperCase();
    }
  }

}
</script>
//计算属性绑定到表单
<input type="text" v-model="computMsg"

调用函数和计算属性(有缓存)的区别:

  • 计算属性计算一次后,若数据不改变则下次调用直接输出。一个计算属性仅会在其响应式依赖更新时才重新计算。

  • 调用方法每次调用都要计算

可写计算属性:计算属性默认是只读的。尝试修改一个计算属性时,可以通过同时提供 getter 和 setter 来创建

两种代码的区别:

  1. 表单绑定到msg

  1. 表单绑定到计算属性computeMsg

<template>
  <div class="hello">
<!--输出计算属性计算后的值-->
    {{ computeMsg }}<br>
    <div> 
      <!--将表单绑定到msg上-->
        <input v-model="msg" >
    </div>  
  </div>  
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg:'hello'
    }  
  },
  computed:{
    computeMsg:{
      //计算属性computeMsg中的get获取表单中的内容,并将表单中的内容变为大写
      get:function(){
      return this.msg.toUpperCase();
      },
    }
  }
}
</script>

<template>
  <div class="hello">
    {{ computeMsg }}<br>
    <div> 
      <!--将表单绑定到计算属性computMsg上-->
        <input v-model="computeMsg" >
    </div>  
  </div>  
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg:'hello'
    }  
  },
  computed:{
    computeMsg:{
      //计算属性computeMsg中的get获取表单中的内容
      get:function(){
      return this.msg.toUpperCase();
      },
      //拿到表单中的内容后给msg赋值
      set:function(value){
      this.msg = value;
      }
    }
  }
}
</script>

侦听属性:需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。使用 watch 函数在每次响应式状态发生变化时触发回调函数

  1. 侦听数据区中的数据变化,若变化则触发相应函数

  1. 侦听到改变后的值

<template>
  <div class="hello">
    {{ msg }}<br>
    <div> 
        <input v-model="msg" >
    </div>  
  </div>  
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg:'hello'
    }  
  },
  //监听msg的变化,只要msg一变化就执行function()
  //console.log("mmm"):在控制台打印mmm
  watch:{
      msg:function(){
        console.log("mmm")

      },   
  }
}
</script>

<style scoped>
h1 {
  font-weight:bold;
  color: #42b983;
  text-align:left;
}
</style>
  • immediate选项

默认值是false

作用:控制侦听器是否自动触发一次

计算属性与侦听属性的区别:

  1. 计算属性只在数据更新时才重新计算,而侦听属性会一直监听

  1. 能用计算属性尽量用计算属性

侦听属性需侦听firstname和lastname,而计算属性直接计算fullname

//使用侦听属性
<template>
  <div class="hello">
    <div> 
        firstname:<input v-model="firstname" ><br>
        lastname:<input v-model="lastname" ><br>
        <hr>
        fullname:{{ fullname }}<br>
    </div>  
  </div>  
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      fullname:'',
      firstname:'',
      lastname:''
    }  
  },
  watch:{
      firstname:function(firstname){
        this.fullname = firstname + ''+this.lastname;
      },
      lastname:function(lastname){
        this.fullname = this.firstname + ''+lastname;
      },
  }
}
</script>
//使用计算属性
<template>
  <div class="hello">
    <div> 
        firstname:<input v-model="firstname" ><br>
        lastname:<input v-model="lastname" ><br>
        <hr>
        fullname:{{ computedfullname }}<br>
    </div>  
  </div>  
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      fullname:'',
      firstname:'',
      lastname:''
    }  
  },
  computed:{
    computedfullname:function(){
      return this.firstname + this.lastname;
    }
  }
}
</script>

vue实例

<template>
  <div id="app">
    {{msg}} 
  </div>  
</template>

<script>
new Vue({
  el: '#app',
  data:{
      msg="hello"
   }
})
</script>
    • 什么是DOM:

dom是一种文档对象模型,同时也是用于html编程的接口,通过dom来操作页面中的元素。当html页面被实现加载的时候,浏览器会创建一个dom,给文档提供了一种新的逻辑结构,并且可以改变内容和结构。

DOM是面向对象,并且定义了修改文档所需要的对象,各个对象之前的关系,我们可以也页面上的dom看成一个树状结构,通过js,对html文档进行添加排版,js要想访问html中的元素,就要通过对象模型来获得。

2.dom获取元素的方法

  • 在html中,我们都知道网页是有很多标签组织起来的,但是这些标签的id是唯一的,我们只要通过id号就能找到对应的标签,然后进行操作。

  • 我们也可以通过名称获取元素,查找返回带有名称对象的集合。是用元素的name属性进行查询,但是由于name元素可能不是唯一值,所以返回是一个数组,并不是一个元素。

  • 通过指定元素节点的属性来获取。

3.创建新实例:

  • var vm = new Vue({

})

  • el: '#app'

将数据(data)msg挂载到DOM中的#app上,el:element的缩写

<div id="app">

{{msg}}

</div>

将指定元素app中的内容加载到vue的虚拟DOM中,最终转换成html的展示的方式

main.js:

import Vue from 'vue'
import App from './App'
import router from './router'

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
  1. import 组件 from '路径'

  • ./:同级目录

  • ../:上一级目录

  • @/:当前组件的根目录下

  • 直接是文件名:当前组件直接来源于工程的依赖文件

2.创建新的实例并挂载到app组件上

路由文件index.js:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

组件注册:

    • 注册全局组件:反复频繁使用的组件

在vue项目的main.js入口文件中,通过Vue.component()方法注册全局组件。在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。

使用时:<Mycount></Mycount>

//导入需要全局注册的组件
import Count from "@/component/count.vue"

//参数1:字符串格式,表示组件的“注册名称”,尽量大写开头
//参数2:需要被全局注册的组件
Vue.component('Mycount',Count)
    • 注册私有组件:通过components注册

例:在组件A的components结点下,注册组件F,则组件F只能在A中使用

//组件A
<script>
//1.导入需要使用的组件
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'

export default{
//2.注册组件
  components:{
    Left,
    Right
   }
 }
</script>

组件之间的数据共享(只要不是父子关系的都是兄弟关系)

    • 父组件向子组件传递数据:使用自定义属性

  • props是只读的,不要直接修改props中的数据,会报错

//父组件
//运用v-bind绑定自定义属性,将父组件data中的值传给自定义属性
//如果不使用v-bind,传过去的是message字符串
<Son :msg="message" :user="userinfo"></Son>

data(){
 return{
  message:'hello'
  userinfo:{name:'zs',age:'21'}
 }
}
//子组件
<template>
 <div>
  <p>父组件传来的msg:{{ msg }}</p>
  <p>父组件传来的userinfo:{{ userinfo }}</p>
 </div>
</template>

//子组件通过自定义属性接收
props:['msg','user']
  • 修改props值的方法

//父组件
//运用v-bind绑定自定义属性,将父组件data中的值传给自定义属性
//如果不使用v-bind,传过去的是message字符串
<template>
 <div>
  <Son :msg="message" :user="userinfo"></Son>
 <div>
</template>

data(){
 return{
  message:'hello'
  userinfo:{name:'zs',age:'21'}
 }
},
compoents:{
 Son
}
//子组件
//修改
<template>
 <div>
  //错误,不能直接修改msg
  <button @click="msg = 'ls'">修改user</button>
  //正确
  <button @click="user.name = 'ls'">修改user</button>
 <div>
</template>

props:['msg','user']

2.*子组件向父组件传递数据:使用自定义事件

//子组件
<template>
    <div class="A">
        <hr>
        <h1>{{ count }}</h1>
        <button @click="add">+1</button>
    </div>
</template>

<script>
    export default {
        name: 'A',
        props:{
            a : Number
        },
        data(){
            return{
                count : 0
            }
        },
        methods:{
            add(){
//修改数据时,通过$emit()方法触发自定义事件numchange,this.count是传给父组件的新值
//this.count实参
                this.count += 1
                this.$emit('numchange',this.count)
            }
        }
    }
//父组件
<template>
  <div class="home">
    <h1>{{countFromA}}</h1>
//监听自定义事件,调用函数
    <A @numchange ="getNewchange"/>
  </div>
</template>

<script>
// @ is an alias to /src
//1.导入需要使用的组件
import A from '../views/A.vue'

export default {
  name: 'Home',
  components: {
    A
  },
  data(){
    return{
      countFromA:0
    }
  },
  methods:{
    getNewchange(val){
//val为形参
      this.countFromA = val
    }
  }
}
</script>

3.兄弟组件间的数据共享

在vue2.x中,兄弟组件间的数据共享的方案:EventBus

  • bus就是发送方的儿子,接收方的父亲

//发送方
<template>
    <div class="A">
        <hr>
        <p>我是A</p>
        <button @click="send">发送给B</button>
    </div>
</template>

<script>
    //1.导入EventBus来发送数据
import bus from '../components/EvuentBus.js'
    export default {
        props:{a : String},
        data(){
            return{
                str :'哦嗨哟'
            }
        },
        methods:{
            send(){
                //通过eventBus来发送数据
                bus.$emit('share',this.str)
            }
        }
    }
</script>

<style scoped>

</style>
//接收方
<template>
    <div class="B">
        <hr>
        <p>我是B</p>
        {{ strFromA }}

    </div>
</template>

<script>
    //1.导入EventBus来发送数据
    import bus from '../components/EvuentBus.js'
    export default {
        data(){
            return{
            strFromA:''
            }
        },
        created() {
            bus.$on('share',val =>{
                this.strFromA = val
            })
        }
    }
</script>

reduce()方法对数组中的每一个元素执行一个reducer函数(由你提供),从而得到一个单一的输出值。

输出值可以是数字、对象或字符串。reduce() 方法有两个参数,第一个是回调函数,第二个是初始值

语法:

  • array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

  • 接受两个参数:

  1. 一个是在每一项上调用的函数

这个调用函数中接受四个参数:累加值、当前值、当前项的索引和数组对象。这个函数返回的任何值都会作为累加值自动传给下一项。

  1. 一个是作为归并基础的初始值(可选)如果设置了初始值,那么初始值就相当于初始的累加值

const numbersArr = [67, 90, 100, 37, 60];

const total = numbersArr.reduce(function(accumulator, currentValue){
    console.log("accumulator is " + accumulator + " current value is " + currentValue);
    return accumulator + currentValue;
}, 0);

console.log("total : "+ total);

//输出
accumulator is 0 current value is 67
accumulator is 67 current value is 90
accumulator is 157 current value is 100
accumulator is 257 current value is 37
accumulator is 294 current value is 60
total : 354

第一个累加器(accumulator)被分配了初始值0。currentValue 是正在处理的 numbersArr 数组的元素。在这里,currentValue 被添加到累加器,在下次调用回调函数时,会将返回值作为参数提供。

引入第三方库内置组件绑定事件

<!--比如用了第三方框架,或者一些封装的内置组件; 然后想绑定事件-->
<!--// 错误例子1-->
<el-input placeholder="请输入特定消费金额 " @mouseover="test()"></el-input>
<!--// 错误例子2-->
<router-link :to="item.menuUrl" @click="toggleName=''">
  <i :class="['fzicon',item.menuIcon]"></i>
  <span>{{item.menuName}}</span>
</router-link>
<!--上面的两个例子都没法触发事件!!!-->
<!--究其原因,少了一个修饰符 .native-->
<router-link :to="item.menuUrl" @click.native="toggleName=''">
  <i :class="['fzicon',item.menuIcon]"></i>
  <span>{{item.menuName}}</span>
</router-link>
<!--https://cn.vuejs.org/v2/guide/components.html#给组件绑定原生事件-->

ref引用

使用ref引用DOM元素

  1. 在不依赖jQuery情况下,获取DOM元素或组件的引用

每个vue的组件实例上,都包含一个$refs对象,里面存储着对应的DOM元素或组件的引用。

  1. 默认情况下,组件的$refs指向一个空对象

  1. 凡是$开头,都是vue内置对象

<template>
  <div id="app">
    <div id="nav">
      <h1 ref="myh1">呀吼</h1>
      <button @click="showThis">打印this</button>
    </div>
    <router-view/>
  </div>
</template>

<script>
  export default {
    methods:{
      showThis(){
        this.$refs.myh1.style.color = 'pink'
      }

    }
  }
</script>
  1. 起名称 ref=""

  1. 引用 this.$ref

ref引用组件实例

//父组件
<template>
  <div id="app">
      <h1>APP根组件</h1>
      <button @click="onReset">重置</button>
      <Left ref="comLeft"/>
    <router-view/>
  </div>
</template>

<script>
  import Left from "./views/Left";
  export default {
    methods:{
        onReset(){
            this.$refs.comLeft.resetCount()
        }
    },
    components:{ Left }
  }
</script>
//子组件
<template>
    <div class="Left-container">
        <h3>left组件---{{count}}</h3>
        <button @click="count += 1">+1</button>
        <button @click="resetCount">重置</button>
    </div>
</template>

<script>
    export default {
        data(){
            return{
                count:0
            }
        },
        methods:{
            resetCount(){
                this.count = 0
            }
        }
    }
</script>

this.$nextTick(cb)方法:延迟cb的调用

  • 组件的$nextTick(cb)方法,会把cb回调推迟到下一个DOM更新周期后执行。

DOM更新后再执行cb回调函数,保证cb可以操作到更新后的DOM元素

  • 不能用生命周期函数updated()(写在与methods评级的地方)代替,因为每次数值改变都会触发一次updated()

如:单击按钮,inputvisible值改变,触发updated,获得焦点,但是单击外面失去焦点,inputvisible值又发生改变,又调用updated函数使输入框获得焦点,但此时输入框已经隐藏了

<template>
  <div id="app">
      <h1>APP根组件</h1>
      <input type="text " v-if="inputVisible" @blur="showButton" ref="iptRef">
      <button v-else @click="showInput">展示输入框</button>
      <Left ref="comLeft"/>
    <router-view/>
  </div>
</template>

<script>
  import Left from "./views/Left";
  export default {
    data(){
        return{
            inputVisible : false
        }
    },
    methods:{
        showInput(){
            //1.切换boolean值为true,将文本框显示出来
            this.inputVisible = true
            //2.让显示出来的文本框自动获得焦点。
            //此时inputVisible值改变,数据需要更新并重新渲染,如果此时直接调用iptRef则此时iptRef=undefined,因为还没渲染上去
            this.$nextTick(()=>{//延迟调用input框的focus()函数
                this.$refs.iptRef.focus()
            })
        },
        showButton(){
            this.inputVisible = false
        }
    },
    components:{ Left }
  }
</script>

数组中的方法:.filter(item=>())

    • .filter()方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

过滤器

是否改变原数组:否

是否对空数组进行检测:否

语法:

const arr=[32,33,16,40];
const arr1 = arr.filter(item => item >=18)console.log(amr) [32,33,16.40]
console.log(arr1) // [32,33,40]
    • .map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。map()方法按照原始数组元素顺序依次处理元素。

是否改变原数组:否

是否对空数组进行检测:否

语法:

const arr=[4,9,16,25];
const arr1 =arr.map(item => item+2)
console.log(arr)   //[4,9,16,25]
console.log(arr1)  //[6,11,18,27]
    • .forEach()方法用于调用数组的每个元素,并将元素传递给回调函数。

注意: forEach()对于空数组是不会执行回调函数的。

tips: forEach()中不支持使用break(报错)和return(不能结束循环),有需要时可使用常规的for循环。

语法:

const arr= [4,9,16, 25];
const arr1 =;
arr.forEach(item => arr1 .push(item))
console.log(arr)   //[4,9,16,25]
console.log(arr1)  //[4,9,16,25]

    • .find()方法返回通过测试(函数内判断)的数组的第一个元素的值。

该方法为数组中的每个元素都调用一次函数执行:

当数组中的元素在测试条件时返回true时, find()返回符合条件的元素,之后的值不会再调用执行函数.

如果没有符合条件的元素返回undefined

注意: find()对于空数组,函数是不会执行的。

注意: find()并没有改变数组的原始值。

语法:

const arr=[4,9,16,25];
const b = arr.find(item -> item>10)
const c= arr.find(item => item<1)
console.log(arr)  //[4,9,16,25]
console.log(b)    // 16
console.log(c)    //undefined
    • .findlndex()方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。

该方法为数组中的每个元素都调用一次函数执行:

当数组中的元素在测试条件时返回true 时, findlndex()返回符合条件的元紊的索引位置,之后的值不会再调用执行函数。如果没有符合条件的元素返回-1

注意: findIndex()对于空数组,函数是不会执行的。

注意: findIndex()并没有改变数组的原始值。

语法:

const arr= [4,9,16,25];
const b = arr.findIndex(item => item>10)
const c= arr.findIndex(item => iteme1)
console.log(arr)    //[4,9,16,25]
console.log(b)      //2,从零开始
console.log(c)      //-1,没有符合条件的值
    • .some()方法用于检测数组中的元素是否满足指定条件(函数提供)。返回bool值

some()方法会依次执行数组的每个元素:

如果有一个元素满足条件.则表达式返回true,剩余的元素不会再执行检测。如果没有满足条件的元素,则返回false。

注意:some()不会对空数组进行检测。

注意:some()不会改变原始数组。

语法:

const arr=[4,9,16,25];
const b = arr.some(item => item>10)
const c= arr.some(item => item<1)
console.log(arr)   //[4,9,16,25]
console.log(b)     //true
console.log(c)     //false
    • .every()方法用于检测数组所有元素是杏都符合指定条件(通过函数提供)。

every()方法使用指定函数检测数组中的所有元素:

如果数组中检测到有一个元素不满足,则整个表达式返回 false,且剩余的元素不会再进行检测。如果所有元素都满足条件.则返回true。

注意:every()不会对空数组进行检测。

注意:every()不会改变原始数组。

语法:

const ar=[4,9,16,25];
const b = arr.every(item => item>10)
const c= arr.every(item => item>1)
console.log(arr)   //[4,9,16,25]
console.log(b)     //false
console.log(c)     //true

动态组件:动态切换组件的显示与隐藏

小贴士:组件的“声明名称”与“注册名称”

  1. 如果在“声明组件”时,没有为组件指定name名称,则组件名称默认为“注册时候的名称”

  1. 当提供了name属性后,组件的名称就是name属性的值

  1. 组件的注册名称:以标签形式使用该组件

  1. 组件的声明名称:在调试工具中该组件的名字,<keep-alive>标签实现组件缓存

//Left.vue
<script>
export default {
  name:'ABC'
  data() {
    return {

    }
  }
}
</script>

    • vue 提供了一个内置的 <component> 组件,专门用来实现动态组件的渲染。

  • <component> 组件,可看成一个给组件占位的占位符

  • 简单用法:<component :is="要渲染的组件名"></component>

//不是写死的值,动态绑定is的值用v-bind
<component :is="comName"></component>

export default {
  data() {
    return {
      //comName表示要展示的组件的名字
      comName:'Left'
    }
  }
    • keep-alive

  • 默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组件的状态。不用每次切换都销毁,再次切换回来再新建

<keep-alive>

<component :is="comName"></component>

</keep-alive>

//App.vue
<template>
  <div class="app-container">
    <h1 ref="myh12">App 根组件</h1>
    <hr/>
    <button @click="comName='Left'">展示Left</button>
    <button @click="comName='Right'">展示Right</button>

    <div class="box">
      <!-- 渲染 Left 组件和 Right 组件 -->
      <keep-alive>
        <component :is="comName"></component>
      </keep-alive>
    </div>
  </div>
</template>

<script>
import Left from "./components/Left";
import Right from "./components/Right";

export default {
  data() {
    return {
      //comName表示要展示的组件的名字
      comName:''
      // 控制输入框和按钮的按需切换;
      // 默认值为 false,表示默认展示按钮,隐藏输入框

    }
  },
  components:{
    Left,Right
  }
}
</script>
生命周期

当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。

当组件被激活时,会自动触发组件的 activated 生命周期函数。

  1. 当组件第一次被创建时,执行created,activated

  1. 当组件被激活,只会触发activated生命周期,不再触发created,因为组件没有被重新创建

//Left.vue
<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  created() {
    console.log("Left组件创建")
  },
  destroyed() {
    console.log("Left组件销毁")
  },
  activated() {
    console.log('Left组件被激活')
  },
  deactivated() {
    console.log('Left组件被缓存')
  }

}
</script>
  • 默认条件下,keeo-alive会把其中包裹的所有组件都缓存

include属性:指定哪些组件需要缓存

仅缓存了Left没有缓存Right

      <keep-alive include="Left">
        <component :is="comName"></component>
      </keep-alive>
exclude属性:指定哪些组件不需要缓存
  • 不能和include同时使用

  • 使用时默认所有组件都keep-alive,exclude中写不被缓存的组件

插槽:渲染出自定义组件中的内容节点

例:<Left>内容</Left>

    • 基本用法:

//app.vue
<template>
  <div class="app-container">
    <div class="box">
      <!--渲染Left和Right组件-->
      <Left>
//<p>标签内容被放到<slot>中
        <p>hhhhhh</p>
      </Left>
    </div>
  </div>
</template>

<script>
import Left from "./components/Left";
import Right from "./components/Right";

export default {
  components:{
    Left,Right
  }
}
</script>
//Left.vue
<template>
  <div class="left-container">
    <h3>Left 组件 --- {{ count }}</h3>
    <hr>
    <!--声明一个插槽区,可以留给用户自定义-->
    <slot></slot>
  </div>
</template>

  • 规定每一个<slot>插槽都要有一个name属性

  • 如果省略了slot插槽的name属性,则默认名称为default

  • 默认情况下,在使用组件时,提供的内容会被填充到名字为default的插槽之中

    • v-slot:插槽的名称:指定该内容要被渲染到哪个插槽中

//App.vue     
 <Left>
        <template v-slot:Left>
          <p>hhhhhh</p>
        </template>
      </Left>

//Left.vue
    <slot name="Left"></slot>
  • 如果要把内容填充到指定名称的插槽中需使用 v-slot

  • v-slot:插槽的名称

  • <template>标签是个虚拟的标签,只起到包裹作用,但是不会被渲染成任何实质性的html元素

  • v-slot:的简写形式:#

<template v-slot:Left> === <template #Left>

    • v-slot只能在组件或<template>中使用
    • 后备内容——声明插槽时提供默认内容:当用户没有指定时生效

即不能同时生效

//Left.vue
<slot name="default">这是default插槽的默认内容</slot>

//App.vue
      <Left>
        <template v-slot:Left>
          <p>hhhhhh</p>
        </template>
      </Left>

4.具名插槽:带有具体名称的插槽

如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。

//App.vue
<template>
  <div class="app-container">
    <h1 ref="myh12">App 根组件</h1>
    <hr/>

    <Article>
      <template #title>
        <div>
          1
        </div>
      </template>

      <template #content>
        <div>
          2
        </div>
      </template>

      <template #author>
        <div>
          3
        </div>
      </template>
    </Article>

    <div class="box">
      <!--渲染Left和Right组件-->
    </div>
  </div>
</template>
//Article
<template>
    <div class="article-container">
        <!--文章的标题-->
        <div class="header-box">
            <slot name="title"></slot>
        </div>

        <!--文章的内容-->
        <div class="content-box">
            <slot name="content"></slot>
        </div>

        <!--文章内容-->
        <div class="footer-box">
            <slot name="author"></slot>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Article"
    }
</script>

<style scoped lang="less">
.article-container{
    div{
        min-height: 150px;
    }
    .header-box{
        background-color: aquamarine;
    }
    .content-box{
        background-color: coral;

    }
    .footer-box{
        background-color: plum;
    }
}

</style>

5.作用域插槽:在插槽内带数据的插槽

在封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据,这种带有 props 数据的 <slot> 叫做“作用域插槽”。

//App.vue父组件
   <Article>
//在Article组件中定义了一个name为content的作用域插槽
      <template #content="obj">//obj为形参,一般使用scope作为形参接收
        <div>
          <p>2</p>
          <p>{{ obj.msg }}</p>
          <p>{{ obj.user.name }}</p>
          <p>{{ obj.user.age }}</p>
        </div>
      </template>
    </Article>
//写法2
      <template #content="{ msg,user }">//obj为形参,一般使用scope作为形参接收
        <div>
          <p>2</p>
          <p>{{ msg }}</p>
          <p>{{ user.name }}</p>
          <p>{{ user.age }}</p>
        </div>
      </template>
//Article.vue子组件,组件的封装
        <!--文章的内容-->
        <div class="content-box">
//作用域插槽,传递数据msg
            <slot name="content" msg="hello" :user="userinfo"></slot>
        </div>

<script>
    export default {
        data(){
            return{
                userinfo:{
                    name:'jack',
                    age:'20'
                }
            }
        }
    }
</script>

自定义指令

自定义指令也像组件那样存在钩子函数:
  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。

指令的值可能发生了改变,也可能没有。

但是你可以通过比较更新前后的值来忽略不必要的模板更新

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用

  • unbind:只调用一次,指令与元素解绑时调用

所有的钩子函数的参数都有以下:
  • el:指令所绑定的元素,可以用来直接操作 DOM

  • binding:一个对象,包含以下 property

  • name:指令名,不包括 v- 前缀。

  • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2

  • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。

  • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"

  • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"

  • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }

  • vnodeVue 编译生成的虚拟节点

  • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用

除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行

    • 私有自定义属性:只能在这个组件内部使用

directives: { }

  • 在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。

//App.vue
<template>
  <div class="app-container">
    <h1 v-color>App 根组件</h1>
  </div>
</template>

<script>
  //私有自定义指令的节点
  directives:{
    //定义名为color的指令,指向一个配置对象
    color:{
      //当指令v-color第一次被绑定到元素上时,会立即触发v-bind函数
      //形参中的el表示当前指令所绑定到的那个DOM对象
      bind(el){
        el.style.color = 'red'
      }
    }
  }
</script>
为自定义指令动态绑定参数值:可以通过形参中的第二个参数,来接收指令的参数值bind(el,binding)
  • el:指令所绑定的元素,可以用来直接操作 DOM

  • binding:一个对象

通过形参val对象的.value属性获得动态的参数值

调试工具中:

  • expression: "color"

表示用户在等号后写的表达式是color(v-color="color")

  • value: "blue"

真正能用的值

//App
<h1 v-color="color">App 根组件</h1>

export default {
  data() {
    return {
      color:'blue'
    }
  },
  components:{
    Left,Right,Article
  },
  //私有自定义指令的节点
  directives:{
    //定义名为color的指令,指向一个配置对象
    color:{
      //当指令v-color第一次被绑定到元素上时,会立即触发v-bind函数
      //形参中的el表示当前指令所绑定到的那个DOM对象
      bind(el,val){
        console.log(val)//value属性拿到了用户传来的变量值color:blue
        el.style.color = val.value
      }
    }
  }
}
</script>
bind函数的缺点
  • 当v-bind指令第一次被绑定到元素上时,会立即触发bind函数

  • 如果页面上的数据发生更新,不会再次触发bind指令

    <h1 v-color="color">App 根组件</h1>
    <button @click="color='green'">改变color的颜色</button>
//App 根组件这几个字仍为蓝色,没有变成绿色,因为没有触发bind函数
解决方法:update 函数会在每次 DOM 更新时被调用。
    <h1 v-color="color">App 根组件</h1>
    <button @click="color='green'">改变color的颜色</button>

 directives:{
    //定义名为color的指令,指向一个配置对象
    color:{
      //当指令v-color第一次被绑定到元素上时,会立即触发v-bind函数
      //形参中的el表示当前指令所绑定到的那个DOM对象
      //第一次绑定时执行
      bind(el,val){
        console.log(val)//value属性拿到了用户传来的变量值color:blue
        el.style.color = val.value
      },
      //数据更新时执行
      update(el,val){
        el.style.color = val.value
      }
    }
  }

v-color自定义指令的简写形式

如果bind和updata函数中内容完全一样的时候就可以简写

//普通形式
//私有自定义指令的节点
  directives:{
    //定义名为color的指令,指向一个配置对象
    color:{
      //当指令v-color第一次被绑定到元素上时,会立即触发v-bind函数
      //形参中的el表示当前指令所绑定到的那个DOM对象
      //第一次绑定时执行
      bind(el,val){
        console.log(val)//value属性拿到了用户传来的变量值color:blue
        el.style.color = val.value
      },
      //数据更新时执行
      update(el,val){
        el.style.color = val.value
      }
    }
  }

//简写形式
  directives:{
    //定义名为color的指令,指向一个配置对象
    /*color:function () { }*/
    //简写:
    color(el,val){
      el.style.color = val.value
    }
  }

    • 全局自定义属性:所有组件中都可以用。

  • 通过“Vue.directive()”进行声明

    • 全局声明的过滤器和自定义指令要放到main.js中
//main.js
//全局自定义指令
//el:指令绑定的元素
//bindinng:一个对象
//写法1
Vue.directive('color',{
  bind(el,binding){
    el.style.color = binding.value
  },
  update(el,binding){
    el.style.color = binding.value
  }
})

//写法2:简写
Vue.directive('color', function (el,binding) {
    el.style.color = binding.value
})

axios

    • 导入axios:npm i axios -S

    • 将axios挂载到Vue原型上

每个.vue组件都相当于一个vue实例,可以在main.js中全局导入axios,这样不用在每个组件中导入axios

写法1

//main.js
Vue.prototype.axios = axios
const {data:res} = await this.axios.post('http://www.liulongbin.top:3006/api/post')
  • 写法2 Vue.prototype.axios = axios中左边的axios可以任意替换

//main.js
Vue.prototype.$http = axios
const {data:res} = await this.$http.post('http://www.liulongbin.top:3006/api/post')

    • 将请求的根路径写在组件中不便于维护,全局配置axios的请求根路径(根路径改变时不用在每个组件中修改)

发起请求的组件不用写完整路径

//main.js
//全局配置axios的请求根路径
axios.defaults.baseURL = 'http://www.liulongbin.top:3006'
//把axios挂载到Vue.prototype上,供每个.vue组件的实例直接使用
Vue.prototype.axios = axios
//Left.vue
methods:{
    async getInfo(){
      const {data:res} = await this.axios.get('/api/get')
      console.log(res)
    }
  }

    • 将axios挂载到Vue原型上的缺点

  • 优点:今后在每个.vue组件中要发起请求,直接调用this.axios.xxx

  • 缺点:不利于API复用

    • axios的基本用法

每个组件中可能都有请求数据的需求:

  1. import axios from 'axios'

  1. get方法

  1. post方法

//Left,请求
<script>
  import axios from 'axios'
export default {
  data() {
    return {

    }
  },
  methods:{
    async getInfo(){
      const {data:res} = await axios.get('http://www.liulongbin.top:3006/api/get')
      console.log(res)
    }
  }
}
</script>
//right,获取
<script>
import axios from "axios";

export default {
  methods:{
    async postInfo(){
      const {data:res} = await axios.post('http://www.liulongbin.top:3006/api/post')
      console.log(res)
    }
  }
}
</script>

路由:Hash 地址与组件之间的对应关系

5. 前端路由的工作方式

① 用户点击了页面上的路由链接

② 导致了 URL 地址栏中的 Hash 值发生了变化

③ 前端路由监听了到 Hash 地址的变化

④ 前端路由把当前 Hash 地址对应的组件渲染都浏览器中

例:path:'#/home',component:Home

手动模拟简单的前端路由:

  • window.onhashchange:监听 window 对象的 onhashchange 事件取得hash地址的值

  • 根据监听到的hash值动态改变comName的值

  • 箭头函数不改变this

<template>
  <div class="app-container">
    <h1>App 根组件</h1>

    <a href="#/home">首页</a>
    <a href="#/movie">电影</a>
    <a href="#/about">关于</a>
    <hr />

    <component :is="comName"></component>
  </div>
</template>

<script>
// 导入组件
import Home from '@/components/Home.vue'
import Movie from '@/components/Movie.vue'
import About from '@/components/About.vue'

export default {
  name: 'App',
  data() {
    return {
      // 在动态组件的位置,要展示的组件的名字,值必须是字符串
      comName: 'Home'
    }
  },
  created() {
    // 只要当前的 App 组件一被创建,就立即监听 window 对象的 onhashchange 事件
    window.onhashchange = () => {
      console.log('监听到了 hash 地址的变化', location.hash)  //取的了hash地址
      switch (location.hash) {
        case '#/home': //根据监听到的hash值动态改变comName的值
          this.comName = 'Home'
          break
        case '#/movie':
          this.comName = 'Movie'
          break
        case '#/about':
          this.comName = 'About'
          break
      }
    }
  },
  // 注册组件
  components: {
    Home,
    Movie,
    About
  }
}
</script>

路由配置

将路由与项目产生联系:

第6行若改为import routerobj

则第19行改为router:routerobj

//main.js:将路由与项目产生联系
import Vue from 'vue'
import App from './App2.vue'
// 导入路由模块,目的:拿到路由的实例对象
// 在进行模块化导入的时候,如果给定的是文件夹,则默认导入这个文件夹下,名字叫做 index.js 的文件
import router from "./router";

// 导入 bootstrap 样式
import 'bootstrap/dist/css/bootstrap.min.css'
// 全局样式
import '@/assets/global.css'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  // 在 Vue 项目中,要想把路由用起来,必须把路由实例对象,通过下面的方式进行挂载
  // router: 路由的实例对象
  router
}).$mount('#app')
//index.js
// index.js 就是当前项目的路由模块
import Vue from 'vue'
import VueRouter from 'vue-router'

// 导入需要的组件
import Home from './components/Home.vue'

// 把 VueRouter 安装为 Vue 项目的插件
// Vue.use() 函数的作用,就是来安装插件的
Vue.use(VueRouter)

// 创建路由的实例对象
const router = new VueRouter()
  // routes 是一个数组,作用:定义 “hash 地址” 与 “组件” 之间的对应关系

export default router

使用 vue-router

    • 导入需要的组件
    • 在路由实例对象中加入 “hash 地址” 与 “组件” 之间的对应关系

注意!是routes!!!不是routers

routes:[

{ path:'/home',component:Home },

{ path:'/movie',component:Movie },

{ path: '/About',component: About}

]

// src/router/index.js 就是当前项目的路由模块
import Vue from 'vue'
import VueRouter from 'vue-router'


// 导入需要的组件
import Home from "../components/Home";
import Movie from "../components/Movie";
import About from "../components/About";

// 把 VueRouter 安装为 Vue 项目的插件
// Vue.use() 函数的作用,就是来安装插件的
Vue.use(VueRouter)

// 创建路由的实例对象
const router = new VueRouter({
    // routes 是一个数组,作用:定义 “hash 地址” 与 “组件” 之间的对应关系
    routes:[
        { path:'/home',component:Home },
        { path:'/movie',component:Movie },
        { path: '/About',component: About}
    ]
})
    • router-link

当安装和配置了 vue-router 后,就可以使用 router-link 来替代普通的 a 链接了

//App
<a href="#/home">首页</a> 
<router-link to="/home">首页</router-link>
    • router-view

显示组件的内容,没有组件占位符就看不到组件

//App    
<!-- 只要在项目中安装和配置了 vue-router,就可以使用 router-view 这个组件了 -->
    <!-- 它的作用很单纯:占位符 -->
    <router-view></router-view>

vue-router 的常见用法:见day7PPT,项目见router1

index.js中path地址要和.vue中的 <router-link to="/about/tab2">地址相同

    • 路由重定向
  • 不要在原来的对应关系上改!!

  • 添上地址A要强制跳转的地址

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

2. 子级路由

路由链接+子级路由占位符

只要该组件中写了<router-link>就要写<router-view>!!!
  • 子级路由(children[数组])地址重定向

// 创建路由的实例对象
const router = new VueRouter({
    // routes 是一个数组,作用:定义 “hash 地址” 与 “组件” 之间的对应关系
    routes:[
        //路由重定向
        { path:'/',redirect:'/home' },
        { path:'/home',component:Home },
        { path:'/movie',component:Movie },
        {
            path: '/About',
            redirect: '/about/tab1',
            component: About,
            children:[
                //子路由
                { path:'tab1',component:tab1 },
                { path: 'tab2',component: tab2}
            ]}
    ]
})
  • 用默认路由取代地址重定向

默认路由:如果children数组中,某个路由规则的path值为空字符串,则这条路由规则为默认字符串

即当显示About组件时自动显示tab1子级组件

//index.js
{
            path: '/About',
            component: About,
            children:[
                //子路由
                { path:'',component:tab1 },
                { path: 'tab2',component: tab2}
            ]}

//about.vue
    <!--子级路由连接-->
   <!--<router-link to="/about/tab1">tab1</router-link>-->
    <router-link to="/about">tab1</router-link>
    <router-link to="/about/tab2">tab2</router-link>
路径参数(查id等)

在 hash 地址中, / 后面的参数项,叫做“路径参数”

在路由“参数对象”中,需要使用 this.$route.params 来访问路径参数

查询参数

在 hash 地址中,? 后面的参数项,叫做“查询参数”

在路由“参数对象”中,需要使用 this.$route.query 来访问查询参数

fullPath与path

在 this.$route 中,path 只是路径部分;fullPath 是完整的地址

例如:

<router-link to="/movie/2?name=zs&age=20"></router-link>中

/movie/2?name=zs&age=20 是 fullPath 的值

/movie/2 是 path 的值

vue-router 中的编程式导航 API

vue-router 提供了许多编程式导航的 API,其中最常用的导航 API 分别是:

① this.$router.push('hash 地址')
  • 跳转到指定 hash 地址,并增加一条历史记录

② this.$router.replace('hash 地址')
  • 跳转到指定的 hash 地址,并替换掉当前的历史记录

③ this.$router.go(数值 n)
  • 实现导航历史前进、后退

  • 数值n为前进/后退的层数

例:A,B,C。从C后退,n=-1时到B,n=-2时到A

 <template>
  <div class="movie-container">
    <h3>电影----{{ id }}</h3>
    <button @click="showThis">打印this</button>
    <button @click="goback">后退</button>

  </div>
</template>

<script>
export default {
  props:[ 'id' ],
  methods:{
    showThis(){
      console.log(this)
    },
    goback(){
      this.$router.go(-1)
    }
  }

}
</script>
当仅前进/后退一层时有简写形式

在行内使用编程式跳转时,this必须要省略,否则会报错

    <button @click="$router.back()">后退</button>
    <button @click="$router.forward()">前进</button>
点击按钮跳转页面的简写方式:
//原来要定义函数
<template>
  <div class="home-container">
    <h3>Home 组件</h3
    <hr />
    <button @click="gotolj">通过push跳转到洛基</button>

  </div>
</template>

<script>
export default {
  name: 'Home',
  methods:{
    gotolj(){
      this.$router.push('/movie/1')
    }
  }
}
</script>
//简写
<template>
  <div class="home-container">
    <h3>Home 组件</h3>
    <hr />
    <button @click="$router.push('/movie/1')">通过push跳转到洛基</button>

  </div>
</template>

路由守卫:没登录时不能访问后台主页

分析:

  1. 要拿到用户将要访问的hash地址

  1. 判断hash地址是否等于/main

  • 若等于/main:则需登录后才能访问

  • 若不等于/main:则直接放行next()

  1. 如果访问的页面地址为/main,则需读取localStorage中的token值(后台主页的访问权限)

  • 如果有:放行

  • 如果没有:强制跳转到登录页

//index.js
//为router实例对象,声明全局前置导航守卫
//只要发生了路由跳转,必然触发beforeEach指定的function回调函数
router.beforeEach(function (to,from,next) {
    //to:跳转到哪,from:从哪跳转,next()函数:表示该次路由跳转是否放行
    if (to.path === '/main') {
        //此代码可以直接访问主页面,因为此处定义了token,所以拿到了token值直接放行
        const token = localStorage.getItem('token')
        if (token){
            next()
        }else {
            next('/login')
        }
    }else {
        next()//访问的不是主页面,直接放行
    }

})

传入参数id的两种方法

  1. 动态路由

  1. 通过路径参数:在路由“参数对象”中,需要使用 this.$route.params 来访问路径参数

//uesrdetail
<template>
  <div>
    <button type="button" class="btn btn-light btn-sm" @click="$router.back()">后退</button>
//法2
    <h4 class="text-center">用户详情---{{this.$route.params.id}}</h4>
//法1
    <h4>{{ id }}</h4>
  </div>
</template>

<script>
export default {
//法1需设置自定义属性
  props:['id']

}
</script>
//index.js
//点击用户管理页中详情跳转到详情页,在同一个地方显示,为同级路由,所以detail也是/home的子路由
//在路由规则中才能出现冒号,具体页面跳转时不能出现冒号
                { path: 'detail/:id',component: Detail,props:true}
//myuser
    <!-- 用户列表 -->
    <table class="table table-bordered table-striped table-hover">
      <thead>
        <tr>
          <th>#</th>
          <th>姓名</th>
          <th>年龄</th>
          <th>头衔</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in userlist" :key="item.id">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.age }}</td>
          <td>{{ item.position}}</td>
          <td>
            <!--阻止click的默认事件,阻止默认刷新页面行为-->
            <a href="#" @click.prevent="gotoDetail(item.id)">详情</a>

methods:{
    //方法中写具体id值
    gotoDetail(id){
      this.$router.push('/home/detail/'+id)
//错误写法,这样会跳转到地址为/home/detail/id的页面去,id不显示为具体数值
this.$router.push('/home/detail/id')
    }
  }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值