Vue学习进度二

这里写目录标题

  • 1.分析脚手架
  • 2.ref属性(id类似)
  • 3.props配置
  • 4.mixin混入
    • 混入中的钩子函数,加载问题
      • 局部引入
      • 全局引入
  • 5.plugin插件
  • 6.scoped样式
  • 7.TodoList案例
  • 8.浏览器本地存储
    • 在TodoList的应用
  • 9.组件自定义事件(子到父|emit,on,off)
  • 10.全局事件总线【student传数据给school】
  • 11.消息订阅与发布
  • 12.动画,过渡【略】
  • 13.配置代理(axios请求数据)
    • 13.1方法1
    • 13.2方法2
  • 14.gitHub搜索案例[请求数据]
    • main.js
    • App.vue
    • List.vue
    • Search.vue
  • 15.vue-resource(与axios相同用法)
  • 16.插槽slot
    • 16.1默认插槽
    • 16.2具名插槽
    • 16.3作用域插槽
  • 17.求和案例_Vuex
      • vuex工作流程
  • 18.求和案例_getters配置
  • 19.求和案例_四个map的使用方法
  • 22.求和案例_多组件共享数据(连23)
  • 23.求和案例_Vuex模块化编码
      • components/Count.vue
      • components/Person.vue
      • store/index.js
      • store/Count.js
      • store/Person.js
      • App.vue
      • main.js
  • 24.路由的基本使用
      • 24.1总结![在这里插入图片描述](https://img-blog.csdnimg.cn/0d517b071b164527952a1b64cc10dc90.png)
      • 24.2代码
  • 25.路由使用的几个注意点
  • 26.路由嵌套使用
      • 26.1总结
      • 26.2代码
  • 27.路由的query传递参数
      • 27.1总结
      • 27.2代码
  • 28.命名路由
  • 29.路由的params传递参数
      • 29.1总结
      • 29.2代码
  • 30.路由中的props配置
      • 30.1总结
      • 30.2代码
  • 31.路由_浏览器操作记录_replace
      • 31.1总结
      • 31.2代码
  • 32.编程式路由导航【push,replace,back...】
      • 32.1总结
      • 32.2代码
  • 33.路由_缓存路由组件【keep-alive】
      • 33.1总结
      • 33.2代码
  • 34.路由_钩子(activate,deactivate)
  • 35.路由_全局路由守卫&&独享路由守卫
      • 31.1总结
      • 35.2代码
  • 36.路由_组件内路由守卫
  • 37.路由_hash,history

1.分析脚手架

npm install -g @vue/cli
vue craete XXX
npm run serve

Vue学习进度二_第1张图片

Vue学习进度二_第2张图片

Vue学习进度二_第3张图片
在这里插入图片描述

2.ref属性(id类似)

Vue学习进度二_第4张图片
App.vue文件

<template>
    <div>
        <h1 v-text="msg" ref="title"></h1>
        <button ref="btn" @click="showDOM">获取上方DOM</button>
        <School ref="zj"></School>
    </div>
</template>

<script>
import School from './components/School.vue'
export default {
    name : "App",
    data()
    {
       return { 
           msg:"学习Vue",
       }
    },
    components:{
        School
    },
    methods:{
        showDOM(){
            // console.log(document.getElementById("title").innerHTML)
            console.log(this.$refs.title)
            console.log(this.$refs.btn)
            console.log(this.$refs.zj)
        }
    }   

}
</script>

3.props配置

Vue学习进度二_第5张图片

App.vue

<template>
    <div>
        <School name="张三" sex="男" :age="18"></School>
        <hr>
        <School name="李四" sex="女" :age="19"></School>
        <hr>
        <School name="王五" sex="男"></School>
    </div>
</template>

<script>
import School from './components/Student.vue'
export default {
    name : "App",
    components:{
        School
    },
}
</script>

Student.vue

<template>
    <div>
        <h2>学生姓名:{{name}}</h2>
        <h2>学生性别:{{sex}}</h2>
        <h2>学生年龄:{{myage}}</h2>
        <button @click="addAge">点击加一</button>
    </div>
</template>

<script>
export default {
    name: 'Student',
    data(){
        return {
            myage:this.age,
        }
    },
    //接受
    //方法1:
    props:["name","sex","age"],//先加载props,后加载data
    methods:{
        // props传入的属性值不要改动
        addAge()
        {
            this.myage++;
        }
    },

    //方法2:
    // props:{
    //     name:String,
    //     sex:String,
    //     age:Number,
    // }

    // 方法3:
    // props:{
    //     name:{
    //         type:String,
    //         required:true,
    //     },
    //     sex:{
    //         type:String,
    //         required:true,
    //     },
    //     age:{
    //         type:Number,
    //         default:99,
    //     }
    // }
}
</script>

4.mixin混入

Vue学习进度二_第6张图片
在这里插入图片描述
在这里插入图片描述
Student.vue

<template>
    <div>
        <h2>学生姓名:{{name}}</h2>
        <h2>学生性别:{{sex}}</h2>
        <h2>学生年龄:{{age}}</h2>
        <button @click="show">点击提示姓名信息</button>
    </div>
</template>

<script>
// import {hunhe,hunhe2} from "../mixin"
export default {
    name: 'Student',
    // mixins:[hunhe,hunhe2],
    data(){
        return{
            name: '张三',
            sex: '男',
        }
    },
    mounted(){
        console.log("mounted")
    }
}
</script>

School.vue

<template>
    <div class="school">
        <h1>学校名称{{name}}</h1>
        <h1>学校地址{{address}}</h1>
        <button @click="show">点击提示学校名称信息</button>
    </div>
</template>

<script>
// import {hunhe,hunhe2} from "../mixin"

export default {
    name: 'School',
    // mixins: [hunhe,hunhe2],
    data(){
        return {
            name: '河南中医药大学',
            address:"郑州",
        }
    }
}
</script>

<style>
    .school{
        background-color:orange
    }    
</style>

App.vue

<template>
    <div>
        <School></School>
        <hr>
        <Student></Student>
    </div>
</template>

<script>
import School from './components/Student.vue'
import Student from './components/School.vue'

export default {
    name : "App",
    components:{
        School,
        Student,
    },
}
</script>

mixin.js

//data数据重复:组件中data和mixin中data取交集,且以组件中data为主
const hunhe = {
    data(){
        return {
        name: 'hunhe_name',
        sex:"女",
        age:18,
        }
    }
}

//同名钩子函数会叠加 
//函数叠加
const hunhe2 = {
    methods:{
        show()
        {
            alert(this.name)
        }
    },
    mounted() {
       console.log('hunhe2_mounted')
    }
}


export {hunhe, hunhe2}

main.js

//引入Vue
import Vue from 'vue';
//引入App组件
import App from './App.vue'

//关闭提示信息
Vue.config.productionTip = false
import {hunhe,hunhe2} from './mixin'

Vue.mixin(hunhe)
Vue.mixin(hunhe2)

new Vue({
    el:"#app",
    render: h =>  h(App),  
})

混入中的钩子函数,加载问题

局部引入

两次hunhe2_mounted

Student组件
School组件
Vue学习进度二_第7张图片

全局引入

四次hunhe2_mounted

Student组件
School组件
App组件
VM实例
Vue学习进度二_第8张图片

5.plugin插件

Vue学习进度二_第9张图片
plugins.js

export default {
  install(Vue,x,y,z){
    console.log(x,y,z)
    //全局过滤器
    Vue.filter('mySlice', function(value){return value.slice(0,4)})

    //定义全局指令
    Vue.directive('fbind',{
      //指令与元素成功绑定时(一上来)
      bind(element,binding){element.value = binding.value},
      //指令所在元素被插入页面时
      inserted(element,binding){element.focus()},
      //指令所在的模板被重新解析时
      update(element,binding){element.value = binding.value}
    })

    //定义混入
    Vue.mixin({
      data() {return {x:100,y:200}},
    })

    //给Vue原型上添加一个方法(vm和vc就都能用了)
    Vue.prototype.hello = ()=>{alert('你好啊')}
  }
}

School.vue

<template>
  <div>
    <h2>学校名称:{{ name | mySlice }}</h2>
    <h2>学校地址:{{ address }}</h2>
    <button @click="test">点我测试一个hello方法</button>
  </div>
</template>

<script>
  export default {
    name:'School',
    data() {
      return {
        name:'尚硅谷atguigu',
        address:'北京',
      }
    },
    methods: {
      test(){
        this.hello()
      }
    },
  }
</script>

Student.vue

<template>
  <div>
    <h2>学生姓名:{{ name }}</h2>
    <h2>学生性别:{{ sex }}</h2>
    <input type="text" v-fbind:value="name">
  </div>
</template>

<script>
  export default {
    name:'Student',
    data() {
      return {
        name:'张三',
        sex:'男'
      }
    },
  }
</script>

6.scoped样式

一般在App组件中,控制所有子组件的样式[不用写sxoped]
Vue学习进度二_第10张图片
App.vue

<template>
    <div>
        <h2>App组件中</h2>
        <hr>
        <School></School>
        <hr>
        <Student></Student>
    </div>
</template>

<script>
import School from './components/Student.vue'
import Student from './components/School.vue'

export default {
    name : "App",
    components:{
        School,
        Student,
    },
}
</script>

<style scoped>
    h2{
        color: red;
    }
</style>

Student.vue

<template>
    <div class="student">
        <h2>学生姓名:{{name}}</h2>
        <h2>学生性别:{{sex}}</h2>
        <h2>学生年龄:{{age}}</h2>
    </div>
</template>

<script>
export default {
    name: 'Student',
    data(){
        return{
            name: '张三',
            sex: '男',
            age:18,
        }
    },
}
</script>

<style scoped>
    .student{
        background-color:yellow;
    }
</style>

School.vue

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
    </div>
</template>

<script>

export default {
    name: 'School',
    data(){
        return {
            name: '河南中医药大学',
            address:"郑州",
        }
    },
}
</script>

<style>
    .school{
        background-color:grey;
    }    
</style>

7.TodoList案例

1.父–>子【传入参数即可】
2.子–>父【子组件传数据给父组件做法:1.父组件定义函数 2.传给子组件 3.合适的时机调用函数】
3.子–>子【子–>父,父–>子】

Vue学习进度二_第11张图片
Vue学习进度二_第12张图片
代码略

8.浏览器本地存储

Vue学习进度二_第13张图片

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>LocalStroage</title>
</head>

<br>
    <h1>LocalStorage</h1>
    <button onclick="saveData()">点击我保存一个数据</button><br>
    <button onclick="readData()">点击我读取一个数据</button><br>
    <button onclick="deleteData()">点击我删除一个数据</button><br>
    <button onclick="clearData()">点击我删除ALL数据</button><br>
    <script type="text/javascript">

        //1.存入
        function saveData() {
            let p = { name: "dyh", age: 18 }
            // console.log(JSON.stringify(p))
            //key[string类型]   value[string类型]
            
            //@@@@@@@@@@@@@@@@@@存入@@@@@@@@@@@@@@@@@@
            localStorage.setItem("mgs", "hello!!")
            localStorage.setItem("mgs2",666)
            localStorage.setItem("mgs3",JSON.stringify(p))

        }
        // 2.取出
        function readData() {
            console.log(localStorage.getItem("mgs"))
            console.log(localStorage.getItem("mgs2"))

            let x =localStorage.getItem("mgs3")
            console.log(JSON.parse(x))
        }
        // 删除
        function deleteData(){
             localStorage.removeItem("mgs2")   
        }
        // 清空
        function clearData(){
            localStorage.clear()
        }
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>sessionStroage</title>
</head>
<body>
    <h1>sessionStorage</h1>
    <button onclick="saveData()">点击我保存一个数据</button><br>
    <button onclick="readData()">点击我读取一个数据</button><br>
    <button onclick="deleteData()">点击我删除一个数据</button><br>
    <button onclick="clearData()">点击我删除ALL数据</button><br>
    <script type="text/javascript">

        //1.存入
        function saveData() {
            let p = { name: "dyh", age: 18 }
            // console.log(JSON.stringify(p))
            //key[string类型]   value[string类型]
            
            //@@@@@@@@@@@@@@@@@@存入@@@@@@@@@@@@@@@@@@
            sessionStorage.setItem("mgs", "hello!!")
            sessionStorage.setItem("mgs2",666)
            sessionStorage.setItem("mgs3",JSON.stringify(p))

        }
        // 2.取出
        function readData() {
            console.log(sessionStorage.getItem("mgs"))
            console.log(sessionStorage.getItem("mgs2"))

            let x =sessionStorage.getItem("mgs3")
            console.log(JSON.parse(x))
        }
        // 删除
        function deleteData(){
             sessionStorage.removeItem("mgs2")   
        }
        // 清空
        function clearData(){
            sessionStorage.clear()
        }
    </script>
</body>
</html>

在TodoList的应用

<template>
	<div id="root">
		<div class="todo-container">
			<div class="todo-wrap">
				<MyHeader :addTodo="addTodo"/>
				<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
				<MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
			</div>
		</div>
	</div>
</template>

<script>
	import MyHeader from './components/MyHeader'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter.vue'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				// 从本地存储中获得数据,null就创建空数组[]
				todos:JSON.parse(localStorage.getItem('todos')) || []
			}
		},
		methods: {
			//添加一个todo
			addTodo(todoObj){
				this.todos.unshift(todoObj)
			},
			//勾选or取消勾选一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			},
			//全选or取消全选
			checkAllTodo(done){
				this.todos.forEach((todo)=>{
					todo.done = done
				})
			},
			//清除所有已经完成的todo
			clearAllTodo(){
				this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})
			}
		},
    // 数据发生改变就放到本地存储中,注意深度侦听,以及JSON转化为字符串
		watch: {
			todos:{
				deep:true,
				handler(value){
					localStorage.setItem('todos',JSON.stringify(value))
				}
			}
		},
	}
</script>

9.组件自定义事件(子到父|emit,on,off)

Vue学习进度二_第14张图片
App.vue

<template>
  <div class="app">
    <h1>{{ msg }},学生姓名是:{{ studentName }}</h1>
		
    <!-- 通过父组件给子组件传递函数类型的props实现子给父传递数据 -->
    <School :getSchoolName="getSchoolName"/>

    <!-- 通过父组件给子组件绑定一个自定义事件实现子给父传递数据(第一种写法,使用@或v-on) -->
    <!-- <Student @atguigu="getStudentName" @demo="m1"/> -->

    <!-- 通过父组件给子组件绑定一个自定义事件实现子给父传递数据(第二种写法,使用ref) -->
    <Student ref="student" @click.native="show"/> <!-- native -->
  </div>
</template>

<script>
  import Student from './components/Student'
  import School from './components/School'

  export default {
    name:'App',
    components:{School,Student},
    data() {
      return {
        msg:'你好啊!',
        studentName:''
      }
    },
    methods: {
      getSchoolName(name){
        console.log('App收到了学校名:',name)
      },
      getStudentName(name,...params){
        console.log('App收到了学生名:',name,params)
        this.studentName = name
      },
      m1(){
        console.log('demo事件被触发了!')
      },
      show(){
        alert(123)
      }
    },
    mounted() {
      this.$refs.student.$on('atguigu',this.getStudentName) // 绑定自定义事件
      // this.$refs.student.$once('atguigu',this.getStudentName) // 绑定自定义事件(一次性)
    },
  }
</script>

<style scoped>.app{background-color: gray;padding: 5px;}</style>

Student.vue

<template>
	<div class="student">
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>当前求和为:{{number}}</h2>
		<button @click="add">点我number++</button>
		<button @click="sendStudentlName">把学生名给App</button>
		<button @click="unbind">解绑atguigu事件</button>
		<button @click="death">销毁当前Student组件的实例(vc)</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		data() {
			return {
				name:'张三',
				sex:'男',
				number:0
			}
		},
		methods: {
			add(){
				console.log('add回调被调用了')
				this.number++
			},
			sendStudentlName(){
				// 触发Student组件实例身上的atguigu事件
				this.$emit('atguigu',this.name,666,888,900)
				// this.$emit('demo')
				// this.$emit('click')
			},
			unbind(){
        // 解绑
				this.$off('atguigu') //解绑一个自定义事件
				// this.$off(['atguigu','demo']) //解绑多个自定义事件
				// this.$off() //解绑所有的自定义事件
			},
			death(){
        // 销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效
				this.$destroy()
			}
		},
	}
</script>

<style lang="less" scoped>
	.student{background-color: pink;padding: 5px;margin-top: 30px;}
</style>

School.vie

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="sendName">点击获得学校名</button>
    </div>
</template>

<script>

export default {
    name: 'School',
    props: ['getSchoolName'],
    data(){
        return {
            name: '河南中医药大学',
            address:"郑州",
        }
    },
    methods: {
        sendName()
        {
            console.log("触发了sendName",this.name)
            this.getSchoolName(this.name)
        }
    }
}
</script>

<style scoped>
    .school{
        background-color:lawngreen;
    }  
</style>

10.全局事件总线【student传数据给school】

Vue学习进度二_第15张图片
main.js

//引入Vue
import Vue from 'vue';
//引入App组件
import App from './App.vue'

//关闭提示信息
Vue.config.productionTip = false



new Vue({
    el:"#app",
    render: h =>  h(App),  
    beforeCreate(){
        Vue.prototype.$bus = this   //$bus是当前的vm
    }
})

App.vue

<template>
    <div>
        <h2>App组件中</h2>
        <hr>
        <School></School>
        <hr>
        <Student></Student>
    </div>
</template>

<script>
import School from  './components/School.vue'
import Student from './components/Student.vue'

export default {
    name : "App",
    components:{
        School,
        Student,
    },
}
</script>

<style scoped>
    div{
        background-color: aqua;
    }
</style>

school.vue

<template>
    <div class="school">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
    </div>
</template>

<script>

export default {
    name: 'School',
    data(){
        return {
            name: '河南中医药大学',
            address:"郑州",
        }
    },
    methods:{
        demo(data)
        {
            console.log("我是school组件,接受data:",data)
        }
    },
    mounted(){
        // 绑定[事件+回调函数]
        this.$bus.$on('hello',this.demo)
    },
    beforeDestroy()
    {
        // 解绑
        this.$bus.$off('hello')
    }
}
</script>

<style scoped>
    .school{
        background-color:grey;
    }    
</style>

student.vue

<template>
    <div class="student">
        <h2>学生姓名:{{name}}</h2>
        <h2>学生性别:{{sex}}</h2>
        <h2>学生年龄:{{age}}</h2>
        <button @click="sendStudentName">学生名传给school组件</button>
    </div>
</template>

<script>
export default {
    name: 'Student',
    data(){
        return{
            name: '张三',
            sex: '男',
            age:18,
        }
    },
    methods:{
        sendStudentName()
        {
            //触发
            this.$bus.$emit("hello",this.name)
        }
    }
}
</script>

<style scoped>
    .student{
        background-color:yellow;
    }
</style>

11.消息订阅与发布

Vue学习进度二_第16张图片
代码略

12.动画,过渡【略】

13.配置代理(axios请求数据)

Vue学习进度二_第17张图片

13.1方法1

Vue学习进度二_第18张图片

13.2方法2

Vue学习进度二_第19张图片
请求部分
Vue学习进度二_第20张图片

<template>
	<div>
		<button @click="getStudents">获取学生信息</button>
		<button @click="getCars">获取汽车信息</button>
	</div>
</template>

<script>
	import axios from 'axios'
	export default {
		name:'App',
		methods: {
			getStudents() {
				axios.get('http://localhost:8080/students').then(
					response => {
						console.log('请求成功了',response.data)
					},
					error => {
						console.log('请求失败了',error.message)
					}
				)
			},
			getCars() {
				axios.get('http://localhost:8080/demo/cars').then(
					response => {
						console.log('请求成功了',response.data)
					},
					error => {
						console.log('请求失败了',error.message)
					}
				)
			}
		},
	}
</script>

14.gitHub搜索案例[请求数据]

main.js

//引入Vue
import Vue from 'vue';
//引入App组件
import App from './App.vue'

//关闭提示信息
Vue.config.productionTip = false


new Vue({
    el:"#app",
    render: h =>  h(App),  
    beforeCreate(){
    Vue.prototype.$bus = this
    }
})

App.vue

<template>
  <div class="container">
    <Search/>
    <List/>
  </div>
</template>

<script>
  import Search from './components/Search.vue'
  import List from './components/List.vue'

  export default {
    name:'App',
    components:{ Search, List },
  }
</script>

List.vue

<template>
  <div class="row">
    <!-- 展示用户列表 -->
    <div class="card" v-for="user in info.users" :key="user.login">

      <a :href="user.html_url" target="_blank">
        <img :src="user.avatar_url" style="width: 100px" />
      </a>

      <p class="card-text">{{user.login}}</p>
    </div>
    <!-- 展示欢迎词 -->
    <h1 v-show="info.isFirst">欢迎使用!</h1>
    <!-- 展示加载中 -->
    <h1 v-show="info.isLoading">加载中....</h1>
    <!-- 展示错误信息 -->
    <h1 v-show="info.errMsg">错误信息:{{info.errMsg}}</h1>
  </div>
</template>

<script>
export default {
  name: "List",
  data() {
    return {
      info:{
      isFirst: true,
      isLoading:false,
      errMsg:"",
      users:[],
      }
    };
  },
  methods:{
    getUsers(dataObj)
    {
      this.info = dataObj;
      // console.log("触发事件,得到数据user",this.info)
    }
  },
  mounted(){
    // 绑定
    this.$bus.$on('updateListUsers',this.getUsers);
  },
  beforeDestroy()
  {
    // 解绑
    this.$bus.$off('updateListUsers');
  }

};
</script>

<style scoped>
.album {min-height: 50rem; /* Can be removed; just added for demo purposes */
  padding-top: 3rem;padding-bottom: 3rem;background-color: #f7f7f7;}
.card {float: left;width: 33.333%;padding: 0.75rem;margin-bottom: 2rem;
  border: 1px solid #efefef;text-align: center;}
.card > img {margin-bottom: 0.75rem;border-radius: 100px;}
.card-text {font-size: 85%;}
</style>

Search.vue

<template>
  <section class="jumbotron">
    <h3 class="jumbotron-heading">Search Github Users</h3>
    <div>
      <input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
      <button @click="searchUsers">Search</button>
    </div>
  </section>
</template>

<script>
import axios from "axios";

export default {
  name: "Search",
  data() {
    return {
      keyWord: "",
    };
  },
  methods: {
    searchUsers(){
      // 1.请求前更新List数据
      this.$bus.$emit('updateListUsers',{isFirst:false,isLoading:true,errMsg:"",users:[]})
      axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
        // 成功
        response => {
          // console.log("请求成功了!!",response.data.items);
          // 2.请求成功更新List数据
          this.$bus.$emit('updateListUsers',{isFirst:false,isLoading:false,errMsg:"",users:response.data.items})
        },
        // 失败
        error => {
          // console.log("请求失败了!!",error.message)
          // 3.请求失败更新List数据
          this.$bus.$emit('updateListUsers',{isFirst:false,isLoading:false,errMsg:error.message,users:[]})
        }
      )
    },
    
  },
  
};
</script>

15.vue-resource(与axios相同用法)

Vue学习进度二_第21张图片

Vue学习进度二_第22张图片

在这里插入图片描述

16.插槽slot

Vue学习进度二_第23张图片
Vue学习进度二_第24张图片
Vue学习进度二_第25张图片
Vue学习进度二_第26张图片
Vue学习进度二_第27张图片

16.1默认插槽

App.vue

<template>
	<div class="container">
		<Category title="美食" >
			<img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
		</Category>

		<Category title="游戏" >
			<ul>
				<li v-for="(g,index) in games" :key="index">{{g}}</li>
			</ul>
		</Category>

		<Category title="电影">
			<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
		</Category>
	</div>
</template>

<script>
	import Category from './components/Category'
	export default {
		name:'App',
		components:{ Category },
		data() {
			return {
				foods:['火锅','烧烤','小龙虾','牛排'],
				games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
				films:['《教父》','《拆弹专家》','《你好,李焕英》','《尚硅谷》']
			}
		},
	}
</script>

<style scoped>.container{display: flex;justify-content: space-around;}</style>

Categroy.vue

<template>
	<div class="category">
		<h3>{{ title }}分类</h3>
		<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
		<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
	</div>
</template>

<script>
	export default {
		name:'Category',
		props:['title']
	}
</script>

<style scoped>
	.category {background-color: skyblue;width: 200px;height: 300px;}
	h3 {text-align: center;background-color: orange;}
	video {width: 100%;}
	img {width: 100%;}
</style>

Vue学习进度二_第28张图片

16.2具名插槽

App.vue

<template>
	<div class="container">
		<Category title="美食" >
			<img slot="conter" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
			<a slot="footer" href="http://www.atguigu.com">更多美食</a>
		</Category>

		<Category title="游戏" >
			<ul slot="center">
				<li v-for="(g,index) in games" :key="index">{{g}}</li>
			</ul>
			<div class="foot" slot="footer">
				<a href="http://www.atguigu.com">单机游戏</a>
				<a href="http://www.atguigu.com">网络游戏</a>
			</div>
		</Category>

		<Category title="电影">
			<video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
			<template v-slot:footer>
				<div class="foot">
					<a href="http://www.atguigu.com">经典</a>
					<a href="http://www.atguigu.com">热门</a>
					<a href="http://www.atguigu.com">推荐</a>
				</div>
				<h4>欢迎前来观影</h4>
			</template>
		</Category>
	</div>
</template>

<script>
	import Category from './components/Category'
	export default {
		name:'App',
		components:{Category},
		data() {
			return {
				foods:['火锅','烧烤','小龙虾','牛排'],
				games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
				films:['《教父》','《拆弹专家》','《你好,李焕英》','《尚硅谷》']
			}
		},
	}
</script>

<style scoped>
	.container,.foot{display: flex;justify-content: space-around;}
	h4{text-align: center;}
</style>

Categroy.vue

<template>
	<div class="category">
		<h3>{{title}}分类</h3>
		<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
		<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot>
		<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot>
	</div>
</template>

<script>
	export default {
		name:'Category',
		props:['title']
	}
</script>

<style scoped>
	.category{background-color: skyblue;width: 200px;height: 300px;}
	h3{text-align: center;background-color: orange;}
	video{width: 100%;}
	img{width: 100%;}
</style>

Vue学习进度二_第29张图片

16.3作用域插槽

App.vue

<template>
	<div class="container">

		<Category title="游戏">
			<template scope="atguigu">
				<ul>
					<li v-for="(g,index) in atguigu.games" :key="index">{{g}}</li>
				</ul>
			</template>
		</Category>

		<Category title="游戏">
			<template scope="{games}">
				<ol>
					<li style="color:red" v-for="(g,index) in games" :key="index">{{g}}</li>
				</ol>
			</template>
		</Category>

		<Category title="游戏">
			<template slot-scope="{games}">
				<h4 v-for="(g,index) in games" :key="index">{{g}}</h4>
			</template>
		</Category>
	</div>
</template>

<script>
	import Category from './components/Category'
	export default {
		name:'App',
		components:{ Category },
	}
</script>

<style scoped>
	.container,.foot{display: flex;justify-content: space-around;}
	h4{text-align: center;}
</style>

categroy.vue

<template>
	<div class="category">
		<h3>{{title}}分类</h3>
		<slot :games="games" msg="hello">我是默认的一些内容</slot>
	</div>
</template>

<script>
	export default {
		name:'Category',
		props:['title'],
		data() {
			return {
				games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
			}
		},
	}
</script>

<style scoped>
	.category{background-color: skyblue;width: 200px;height: 300px;}
	h3{text-align: center;background-color: orange;}
	video{width: 100%;}
  img{width: 100%;}
</style>

Vue学习进度二_第30张图片

17.求和案例_Vuex

vuex工作流程

Vue学习进度二_第31张图片

Vue学习进度二_第32张图片

Vue学习进度二_第33张图片

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

src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'	// 引入Vuex

Vue.use(Vuex)	// 应用Vuex插件

const actions = {}		// 准备actions——用于响应组件中的动作
const mutations = {}	// 准备mutations——用于操作数据(state)
const state = {}			// 准备state——用于存储数据

// 创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

src/main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'	// 引入store

Vue.config.productionTip = false

new Vue({
	el: '#app',
	render: h => h(App),
	store,										// 配置项添加store
	beforeCreate() {
		Vue.prototype.$bus = this
	}
})

Vue学习进度二_第34张图片

src/store/index.js

// 引入Vue
import Vue from 'vue';
// 引入Vuex插件
import Vuex from 'vuex';


// 使用插件
Vue.use(Vuex) //Vuex.use(Vuex)必须在new Vuex.store({})前面

// 准备actions——用于响应组件中的动作
const actions = {
    //context是mini版的$store     context = $store
    
    // jia(context,value){
    //     // console.log(context,value)
    //     console.log("actions中的jia被调用了")
    //     context.commit('JIA',value)
        
    // },
    // jian(context,value){
    //     console.log("actions中的jian被调用了")
    //     context.commit('JIAN',value)
    // },
   
    jiaOdd(context,value){
        if(context.state.sum % 2){
        console.log("actions中的jiaOdd被调用了")
        context.commit('JIA',value)
        }
    },
    jiaWait(context,value){
        setTimeout(() => {
            console.log("actions中的jiaWait被调用了")
            context.commit('JIA',value)
        }, 1000);
    }
}

// 准备mutations——用于操作数据(state)  响应actions
const mutations = {
    JIA(state,value){
        // console.log(state,value);
        // console.log(this.state)
        // state = this.state.sum [this = $store]
        state.sum+=value;
        console.log("mutations中的JIA被调用了");
    },
    JIAN(state,value){
        state.sum-=value;
        console.log("mutations中的JIAN被调用了");
    },
}

// 准备state——用于存储共享数据
const state = {
    sum:0,
}

// 创建并暴露store
export default new Vuex.Store({
    actions: actions,
    mutations: mutations,
    state: state,  
})


Count.vue

<template>
  <div>
    <h1>当前为{{$store.state.sum}}</h1>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">奇数再加</button>
    <button @click="incrementWait">等等再加</button>
  </div>
</template>

<script>
  export default {
    name: "Count",
    props:[],
    data() {
			return {
        n:1,
			}
		},
    methods:{
      increment(){
        console.log("increment被调用了")
        this.$store.commit('JIA',this.n)
        // console.log(this)
        // console.log(this.$store.state)
        // console.log(this.$store.state.sum)
      },
      decrement(){
        console.log("decrement被调用了")
        this.$store.commit('JIAN',this.n)
      },
      incrementOdd(){
        console.log("incrementOdd被调用了")
        this.$store.dispatch('jiaOdd',this.n)
      },
      incrementWait(){
        console.log("incrementWait被调用了")
        this.$store.dispatch('jiaWait',this.n)
      }

    }
  }
</script>
<style scoped>
  button{
    margin: 5px;
  }
</style>

18.求和案例_getters配置

Vue学习进度二_第35张图片
Vue学习进度二_第36张图片

Vue学习进度二_第37张图片

在这里插入图片描述

19.求和案例_四个map的使用方法

Vue学习进度二_第38张图片
Vue学习进度二_第39张图片

Count.vue

<template>
  <div>
    <h1>当前为:{{sum}}</h1>
    <h1>当前为放大十倍:{{bigSum}}</h1> 
    <h1>我在{{name}}{{school}}上学</h1>   
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">奇数再加</button>
    <button @click="incrementWait(n)">等等再加</button>
  </div>
</template>

<script>
  import {mapState,mapGetters,mapMutations,mapActions} from "vuex"

  export default {
    name: "Count",
    props:[],
    data() {
			return {
        n:1,
			}
		},
    methods:{
      // increment(){
      //   console.log("increment被调用了")
      //   this.$store.commit('JIA',this.n)
      //   // console.log(this)
      //   // console.log(this.$store.state)
      //   // console.log(this.$store.state.sum)

      // },
      // decrement(){
      //   console.log("decrement被调用了")
      //   this.$store.commit('JIAN',this.n)
      // },
      // ...mapMutations({increment:'JIA',decrement:'JIAN'}),
      

      /*
      
      
      */
      // 对象写法(生成对应的方法,会调用commit联系mutations)
      ...mapMutations({increment:'JIA',decrement:'JIAN'}),

      /*
      
      
      */
      // 数组写法
      // ...mapMutations(['JIA','JIAN']),


// ============================================================================================

      // incrementOdd(){
      //   console.log("incrementOdd被调用了")
      //   this.$store.dispatch('jiaOdd',this.n)
      // },
      // incrementWait(){
      //   console.log("incrementWait被调用了")
      //   this.$store.dispatch('jiaWait',this.n)
      // }


      /*
      
            
      */ 
      // 对象写法(生成对应的方法,会调用dispatch联系Ations)
      ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),
      
      /*
      
      
      */
      // 数组写法
      // ...mapActions(['jiaOdd','jiaWait']),



    },
    computed:{

      // 对象写法
      // ...mapState({sum:'sum',name:'name',school:'school'})
      // 数组写法
      ...mapState(['sum','name','school']),
// =================================================================================================
      // 对象写法
      // ...mapGetters({bigSum:'bigSum'}),
      // 数组写法
      ...mapGetters(['bigSum'])
    },

  }
</script>
<style scoped>
  button{
    margin: 5px;
  }
</style>

22.求和案例_多组件共享数据(连23)

23.求和案例_Vuex模块化编码

Vue学习进度二_第40张图片
Vue学习进度二_第41张图片

const countAbout = {
  namespaced: true,	// 开启命名空间
  state: {x:1},
  mutations: { ... },
  actions: { ... },
  getters: {
    bigSum(state){ return state.sum * 10 }
  }
}

const personAbout = {
  namespaced: true,	// 开启命名空间
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    countAbout,
    personAbout
  }
})

Vue学习进度二_第42张图片
Vue学习进度二_第43张图片
Vue学习进度二_第44张图片

Vue学习进度二_第45张图片

components/Count.vue

<template>
  <div>
    <h1>当前为:{{sum}}</h1>
    <h1>当前为放大十倍:{{bigSum}}</h1> 
    <h1>我在{{name}}{{school}}上学</h1>   
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">奇数再加</button>
    <button @click="incrementWait(n)">等等再加</button>
    <h1 style="color:red"> Person组件:{{personSum}} </h1>
  </div>
</template>

<script>
  import {mapState,mapGetters,mapMutations,mapActions} from "vuex"

  export default {
    name: "Count",
    props:[],
    data() {
			return {
        n:1,
			}
		},
    methods:{
      // 调用mutations
      ...mapMutations('countAoubt',{increment:'JIA',decrement:'JIAN'}),
      // 调用actions
      ...mapActions('countAoubt',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),
    },
    computed:{
      // 读取state
      ...mapState('countAoubt',['sum','name','school']),
      // 读取getters
      ...mapGetters('countAoubt',['bigSum']),
      ...mapGetters('personAoubt',['personSum'])
    },

  }
</script>
<style scoped>
  button{
    margin: 5px;
  }
</style>

components/Person.vue

<template>
  <div>
    <input type="text" placeholder="请输入" v-model="name"></input>
    <button @click="addPerson">添加人员</button>
    <button @click="addWang">添加一个姓王的人员</button>
    <button @click="addAnyPerson">任意添加一个人员</button>
    <h1 style="color:red">Count组件:{{sum}}</h1>
    <h2>列表中的第一个人的名字:{{firstPersonName}}</h2>
    <ul>
        <li v-for="p in personList" :key="p.id">{{p.name}}</li>
    </ul>
  </div>
</template>

<script>
  import {nanoid} from "nanoid"
import { mapGetters } from 'vuex';

  export default {
    name: "Person",
    data(){
        return {
            name:'',
        }
    },
    methods:{
        addPerson(){
            if(this.name === "") return alert("不能空格!!") ;
            const personObj = {id:nanoid(),name:this.name}
            // commit
            this.$store.commit('personAoubt/ADDPERSON', personObj)
            this.name = "";
        },
        addWang(){
            // dispatch
            const personObj = {id:nanoid(),name:this.name}
            this.$store.dispatch('personAoubt/addPersonWang',personObj);
        },
        addAnyPerson(){
            // dispatch
            this.$store.dispatch('personAoubt/addAnyPersonServer')
        }
    },
    computed:{
        sum(){
            // state
            return this.$store.state.countAoubt.sum;
        },
        personList(){
            // state
            return this.$store.state.personAoubt.personList;
        }, 
        firstPersonName(){
            return this.$store.getters['personAoubt/firstPersonName'];
        }      
    },
  }
</script>
<style scoped>
  button{
    margin: 5px;
  }
</style>

store/index.js

// 引入Vue
import Vue from 'vue';
// 引入Vuex插件
import Vuex from 'vuex';

import countOptions from './Count';
import personOptions from './Person';

Vue.use(Vuex)


// 创建并暴露store
export default new Vuex.Store({
    modules:{
        countAoubt: countOptions,
        personAoubt: personOptions,
    }
})

store/Count.js

const countOptions = {
    namespaced:true,
    actions : {
        jiaOdd(context,value){
            if(context.state.sum % 2){
            console.log("actions中的jiaOdd被调用了")
            context.commit('JIA',value)
            }
        },
        jiaWait(context,value){
            setTimeout(() => {
                console.log("actions中的jiaWait被调用了")
                context.commit('JIA',value)
            }, 1000);
        }        
    },
    mutations : {
        JIA(state,value){
            state.sum+=value;
            console.log("mutations中的JIA被调用了");
        },
        JIAN(state,value){
            state.sum-=value;
            console.log("mutations中的JIAN被调用了");
        },
    },
    state : {
        sum:0,
        name:"河南",
        school:"河南中医药大学",
    },
    getters : {
        bigSum(state){
            // console.log(state)
            return state.sum*10;
        },
    },
}

export default countOptions;

store/Person.js

import axios from "axios";
import {nanoid} from "nanoid";


const personOptions = {
    namespaced:true,
    actions : {
        addPersonWang(context,value){
            if(value.name[0]==="王"){
                context.commit('ADDPERSON',value);
            }
            else{
                alert("请写王姓!!")
            }
        },
        addAnyPersonServer(context){
           axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(
                response =>{
                    // console.log("response.data");
                    context.commit('ADDPERSON',{id:nanoid(),name:response.data})
                },
                error =>{
                    // console.log("error.message");
                    alert(error.message);
                }

           ) 
        }
    },
    mutations : {    
        ADDPERSON(state,personObj){
            state.personList.unshift(personObj);
            console.log("mutations中的ADDPERSON被调用了");
        }
    },
    state : {
        personList:[{id:"001",name:"Pjon"}],
    },
    getters : {
        personSum(state){
            return state.personList.length;
        } ,
        firstPersonName(state){
            return state.personList[0].name;
        }       
    },
}

export default personOptions;

App.vue

<template>
  <div>
    <Count/>
    <Person/>
  </div>
</template>

<script>
  import Count from "./components/Count.vue";
  import Person from "./components/Person.vue";

  export default {
    name:'App',
    components:{ Count , Person},
    	
  }
</script>
<style scoped>

</style>



main.js

//引入Vue
import Vue from 'vue';
//引入App组件
import App from './App.vue'
// 引入store
import store from './store/index.js';


//关闭提示信息
Vue.config.productionTip = false


new Vue({
    el:"#app",
    render: h =>  h(App),  
    // 配置store选项
    store:store,
    beforeCreate(){
    Vue.prototype.$bus = this
    }
})

24.路由的基本使用

24.1总结Vue学习进度二_第46张图片

Vue学习进度二_第47张图片

npm i vue-router

Vue学习进度二_第48张图片


import VueRouter from 'vue-router'			// 引入VueRouter
import About from '../components/About'	// 路由组件
import Home from '../components/Home'		// 路由组件

// 创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
	routes:[
		{
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home
		}
	]
})

//暴露router
export default router

Vue学习进度二_第49张图片

24.2代码

src/components/About.vue

<template>
  <div>
    <h1>我是Aoubt页面展示的</h1>
  </div>
</template>

<script>
  export default {
    name: "About",
  }
</script>
<style scoped>

</style>

src/components/Home.vue

<template>
  <div>
    <h1>我是Home页面展示的</h1>
  </div>
</template>

<script>
  export default {
    name: "Home",
  }
</script>
<style scoped>

</style>

src/router/index.js

import VueRouter  from "vue-router"
// 引入组件
import Home from "../components/Home"
import About from "../components/About"


// const router = 
export default  new VueRouter({
    routes:[
        {
            path:"/about", //key
            component:About,//value
        },
        {
            path:"/home",
            component:Home,
        }
    ]
})

src/App.vue

<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header"><h2>Vue Router Demo</h2></div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
					<!-- 原始html中我们使用a标签实现页面的跳转 -->
          <!-- <a class="list-group-item active" href="./about.html">About</a> -->
          <!-- <a class="list-group-item" href="./home.html">Home</a> -->

					<!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link class="list-group-item" active-class="active" to="/about">Aoubt</router-link>
          <router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
						<!-- 指定组件的呈现位置 -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
	export default {
		name:'App'
	}
</script>

src/main.js

//引入Vue
import Vue from 'vue';
//引入App组件
import App from './App.vue'
// 引入Vuerouter插件
import Vuerouter from 'vue-router';
// 引入路由器
import router from './router/index.js';


Vue.use(Vuerouter)//使用插件

//关闭提示信息
Vue.config.productionTip = false


new Vue({
    el:"#app",
    render: h =>  h(App),  
    router:router,
})

25.路由使用的几个注意点

Vue学习进度二_第50张图片

26.路由嵌套使用

26.1总结

在这里插入图片描述

routes:[
	{
		path:'/about',
		component:About,
	},
	{
		path:'/home',
		component:Home,
		children:[ 					// 通过children配置子级路由
			{
				path:'news', 		// 此处一定不要带斜杠,写成 /news
				component:News
			},
			{
				path:'message',	// 此处一定不要写成 /message
				component:Message
			}
		]
	}
]

在这里插入图片描述

<router-link to="/home/news">News</router-link>

26.2代码

Vue学习进度二_第51张图片
Banner.vue

<template>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header"><h2>Vue Router Demo</h2></div>
      </div>
    </div>
</template>

<script>
  export default {
    name: "Banner",
  }
</script>
<style scoped>

</style>

About.vue

<template>
  <div>
    <h1>我是Aoubt页面展示的</h1>
  </div>
</template>

<script>
  export default {
    name: "About",
  }
</script>
<style scoped>

</style>

Home.vue

<template>
  <div>
    <h1>我是Home页面展示的</h1>
    <div>
			<ul class="nav nav-tabs">
			
      	<li>
          <router-link class="list-group-item" 
                       active-class="active" 
                       to="/home/news">News</router-link>
        </li>
				<li>
          <router-link class="list-group-item" 
                       active-class="active" 
                       to="/home/messages">Message</router-link>
        </li>
			
      </ul>
			<router-view></router-view>
		</div>
  </div>
</template>

<script>
  export default {
    name: "Home",
  }
</script>
<style scoped>

</style>

Messages.vue

<template>
    <ul>
        <li>
            <a href="/message1">message001</a>&nbsp;&nbsp;
        </li>
        <li>
            <a href="/message2">message002</a>&nbsp;&nbsp;
        </li>
        <li>
            <a href="/message/3">message003</a>&nbsp;&nbsp;
        </li>
    </ul>
</template>

<script>
    export default {
        name:'Messages'
    }
</script>

News.vue

<template>
    <ul>
        <li>news001</li>
        <li>news002</li>
        <li>news003</li>
    </ul>
</template>

<script>
    export default {
        name:'News'
    }
</script>

router/index.js

import VueRouter  from "vue-router"
// 引入组件
import Home from "../pages/Home"
import About from "../pages/About"
import News from "../pages/News"
import Messages from "../pages/Messages"


// const router = 
export default  new VueRouter({
    routes:[
        {
            path:"/about", //key
            component:About,//value
        },
        {
            path:"/home",
            component:Home,
            children:[
                {
                    path:"news",
                    component:News,
                },
                {
                    path:"messages",
                    component:Messages,
                },
            ]
        }
    ]
})

App.vue

<template>
<div>
    <Banner></Banner>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
					<!-- 原始html中我们使用a标签实现页面的跳转 -->
          <!-- <a class="list-group-item active" href="./about.html">About</a> -->
          <!-- <a class="list-group-item" href="./home.html">Home</a> -->

					<!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link class="list-group-item" active-class="active" to="/about">Aoubt</router-link>
          <router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
						<!-- 指定组件的呈现位置 -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
</div>
</template>

<script>
  import Banner from './components/Banner.vue';

	export default {
		name:'App',
    components: { Banner }
	}
</script>



main.js

//引入Vue
import Vue from 'vue';
//引入App组件
import App from './App.vue'
// 引入Vuerouter插件
import Vuerouter from 'vue-router';
// 引入路由器
import router from './router/index.js';


Vue.use(Vuerouter)//使用插件

//关闭提示信息
Vue.config.productionTip = false


new Vue({
    el:"#app",
    render: h =>  h(App),  
    router:router,
})

27.路由的query传递参数

27.1总结

1.传递参数

<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>
				
<!-- 跳转并携带query参数,to的对象写法(推荐) -->
<router-link 
	:to="{
		path:'/home/message/detail',
		query:{
		   id: m.id,
       title: m.title
		}
	}"
>跳转</router-link>

2.接收参数

$route.query.id
$route.query.title

27.2代码

src/router/index.js

import VueRouter from "vue-router";
import Home from '../pages/Home'
import About from '../pages/About'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'

// 创建并暴露一个路由器
export default new VueRouter({
  routes:[
    {
      path:'/about',
      component:About
    },
    {
      path:'/home',
      component:Home,
      children:[
        {
          path:'news',
          component:News
        },
        {
          path:'message',
          component:Message,
          children:[
            {
              path:'detail',
              component:Detail
            }
          ]
        }
      ]
    }
  ]
})

src/pages/Messages.vue

<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带query参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">
                      {{m.title}}
    				 </router-link>&nbsp;&nbsp; -->

        <!-- 跳转路由并携带query参数,to的对象写法 -->
        <router-link :to="{
                            path:'/home/message/detail',
                            query:{
                              id:m.id,
                              title:m.title
                            }
                          }">
          {{m.title}}
      </router-link>&nbsp;&nbsp;
      </li>
    </ul>
    <hr/>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name:'News',
    data(){
      return{
        messageList:[
          {id:'001',title:'消息001'},
          {id:'002',title:'消息002'},
          {id:'003',title:'消息003'}
        ]
      }
    }
  }
</script>

src/pages/Detail.vue

<template>
    <ul>
        <li>消息编号:{{ $route.query.id }}</li>
        <li>消息标题:{{ $route.query.title }}</li>
    </ul>
</template>

<script>
    export default {
        name:'Detail'
    }
</script>

28.命名路由

Vue学习进度二_第52张图片
Vue学习进度二_第53张图片

29.路由的params传递参数

29.1总结

Vue学习进度二_第54张图片
Vue学习进度二_第55张图片
Vue学习进度二_第56张图片

29.2代码

index.js

import VueRouter  from "vue-router"
// 引入组件
import Home from "../pages/Home"
import About from "../pages/About"
import News from "../pages/News"
import Messages from "../pages/Messages"
import Detail from "../pages/Detail"


// const router = 
export default  new VueRouter({
    routes:[
        {
            name:"guanyu",
            path:"/about", //key
            component:About,//value
        },
        {
            name:"jia",
            path:"/home",
            component:Home,
            children:[
                {   
                    name:"xinwen",
                    path:"news",
                    component:News,
                },
                {
                    name:"xiaoxi",
                    path:"messages",
                    component:Messages,
                    children:[
                        {
                            name:"xiangqing",
                            path:"detail/:id/:title",
                            component:Detail,
                        }
                    ]
                },
            ]
        }
    ]
})

Messages.vue

<template>
    <ul>
        <li v-for="m in messageList" :key="m.id">
            
            <!-- 跳转路由并携带params参数,to的字符串写法 -->
            <router-link :to="`/home/messages/detail/${m.id}/${m.title}`">  {{m.title}}   </router-link>
            
            <!-- 携带params参数 必须是name,不能是path-->
            <!-- 跳转路由并携带params参数,to的对象写法 -->
            <!-- <router-link :to="{
                                name:'xiangqing',
                                params:{
                                    id:m.id,
                                    title:m.title,
                                    }
                                }">
                {{m.title}}
            </router-link>&nbsp;&nbsp;  -->
        
        </li>
        <router-view></router-view>
    </ul>
</template>

<script>
    export default {
        name:'Messages',
        data(){
            return {
                messageList:[
                    {id:"001",title:"消息1"},
                    {id:"002",title:"消息2"},
                    {id:"003",title:"消息3"},
                ]
            }
        }
    }
</script>

Detail.vue

<template>
    <ul>
        <li>信息id:{{$route.params.id}}</li>
        <li>信息title:{{$route.params.title}}</li>
    </ul>
</template>

<script>
  export default {
    name: "Detail",
    // mounted(){
    //     console.log(this.$route.query.id1,this.$route.query.title1)
    // }
  }
</script>
<style scoped>

</style>

30.路由中的props配置

30.1总结

在这里插入图片描述

{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
	// props:{a:900}

	//第二种写法:props值为布尔值,为true时,则把路由收到的所有params参数通过props传给Detail组件
	// props:true
	
	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
	props($route){
		return {
			id: $route.query.id,
			title: $route.query.title
		}
	}
}

30.2代码

index.js

import VueRouter  from "vue-router"
// 引入组件
import Home from "../pages/Home"
import About from "../pages/About"
import News from "../pages/News"
import Messages from "../pages/Messages"
import Detail from "../pages/Detail"


// const router = 
export default  new VueRouter({
    routes:[
        {
            name:"guanyu",
            path:"/about", //key
            component:About,//value
        },
        {
            name:"jia",
            path:"/home",
            component:Home,
            children:[
                {   
                    name:"xinwen",
                    path:"news",
                    component:News,
                },
                {
                    name:"xiaoxi",
                    path:"messages",
                    component:Messages,
                    children:[
                        {
                            name:"xiangqing",
                            path:"detail/:id/:title",
                            component:Detail,
	                        //第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件 【固定数据】
                            // props:{a:1,b:"hello"}

                            //第二种写法:props值为布尔值,为true时,则把路由收到的所有params参数通过props传给Detail组件【params】
                            // props:true,

                            //第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件 【params,query】
                            props($route){
                                return {
                                    id:$route.params.id,
                                    title:$route.params.title,
                                    // id:$route.query.id,
                                    // title:$route.query.title,
                                }
                            }
                        }
                    ]
                },
            ]
        }
    ]
})

Messages.vue

<template>
    <ul>
        <li v-for="m in messageList" :key="m.id">
            
            <!-- 跳转路由并携带params参数,to的字符串写法 -->
            <router-link :to="`/home/messages/detail/${m.id}/${m.title}`">  {{m.title}}   </router-link>
            
            <!-- 携带params参数 必须是name,不能是path-->
            <!-- 跳转路由并携带params参数,to的对象写法 -->
            <!-- <router-link :to="{
                                name:'xiangqing',
                                params:{
                                    id:m.id,
                                    title:m.title,
                                    }
                                }">
                {{m.title}}
            </router-link>&nbsp;&nbsp;  -->
        
        </li>
        <router-view></router-view>
    </ul>
</template>

<script>
    export default {
        name:'Messages',
        data(){
            return {
                messageList:[
                    {id:"001",title:"消息1"},
                    {id:"002",title:"消息2"},
                    {id:"003",title:"消息3"},
                ]
            }
        }
    }
</script>

Detail.vue

<template>
    <ul>
        <li>信息id:{{id}}</li>
        <li>信息title:{{title}}</li>
        <!-- <li>{{a}}</li> -->
        <!-- <li>{{b}}</li> -->
       </ul>
</template>

<script>
  export default {
    name: "Detail",
    // mounted(){
    //     console.log(this.$route.query.id1,this.$route.query.title1)
    // }
    props:['id','title',],
    // computed:{
    //     id()
    //     {
    //         return this.$route.params.id;
    //     },
    //     title(){
    //         return this.$route.params.title;
    //     }

    // }
  }
</script>
<style scoped>

</style>

31.路由_浏览器操作记录_replace

31.1总结

Vue学习进度二_第57张图片

31.2代码

App.vue

<template>
<div>
    <Banner></Banner>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
					<!-- 原始html中我们使用a标签实现页面的跳转 -->
          <!-- <a class="list-group-item active" href="./about.html">About</a> -->
          <!-- <a class="list-group-item" href="./home.html">Home</a> -->

					<!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :replace="true" class="list-group-item" active-class="active" to="/about">Aoubt</router-link>
          <router-link replace class="list-group-item" active-class="active" to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
						<!-- 指定组件的呈现位置 -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
</div>
</template>

<script>
  import Banner from './components/Banner.vue';

	export default {
		name:'App',
    components: { Banner }
	}
</script>

32.编程式路由导航【push,replace,back…】

32.1总结

Vue学习进度二_第58张图片

this.$router.push({
	name:'xiangqing',
  params:{
    id:xxx,
    title:xxx
  }
})

this.$router.replace({
	name:'xiangqing',
  params:{
    id:xxx,
    title:xxx
  }
})

32.2代码

Banner.vue

<template>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header"><h2>Vue Router Demo</h2></div>
        <button @click="back">后退</button>
        <button @click="forward">前进</button>
        <button @click="Any">any(-3</button>
      </div>
    </div>
</template>

<script>
  export default {
    name: "Banner",
    methods:{
      back(){
        this.$router.back();
      },
      forward(){
        this.$router.forward();
      },
      Any(){
        this.$router.go(-3)
      }
    }
  }
</script>
<style scoped>

</style>

Messages.vue

<template>
    <ul>
        <li v-for="m in messageList" :key="m.id">

            <router-link :to="{
                                name:'xiangqing',
                                params:{
                                    id:m.id,
                                    title:m.title,
                                    }
                                }">
                {{m.title}}
            </router-link>&nbsp;&nbsp; 
            
            <button @click="pushShow(m)">push查看</button>
            <button @click="replaceShow(m)">replace查看</button>        
        </li>
        <router-view></router-view>
    </ul>
</template>

<script>
    export default {
        name:'Messages',
        data(){
            return {
                messageList:[
                    {id:"001",title:"消息1"},
                    {id:"002",title:"消息2"},
                    {id:"003",title:"消息3"},
                ]
            }
        },
        methods:{
            // push记录
            pushShow(m){
                this.$router.push({
                        name:'xiangqing',
                        params:{
                            id:m.id,
                            title:m.title,
                        }
                    })
            },
            // replace记录
            replaceShow(m){
                this.$router.replace({
                        name:'xiangqing',
                        params:{
                            id:m.id,
                            title:m.title,
                        }                    
                })
            }
        }
    }
</script>

33.路由_缓存路由组件【keep-alive】

33.1总结

在这里插入图片描述

// 缓存一个路由组件
<keep-alive include="News"> // include中写想要缓存的组件名,不写表示全部缓存
    <router-view></router-view>
</keep-alive>

// 缓存多个路由组件
<keep-alive :include="['News','Message']"> 
    <router-view></router-view>
</keep-alive>

33.2代码

Home.vue

<template>
  <div>
    <h1>我是Home页面展示的</h1>
    <div>
			<ul class="nav nav-tabs">
			
      	<li>
          <router-link class="list-group-item" 
                       active-class="active" 
                       to="/home/news">News</router-link>
        </li>
				<li>
          <router-link class="list-group-item" 
                       active-class="active" 
                       to="/home/messages">Message</router-link>
        </li>
			
      </ul>
      <!-- News组件名 -->
      <!-- <keep-alive include="News"> -->
       <keep-alive :include="['News']"> 
        <router-view></router-view>
      </keep-alive>
		</div>
  </div>
</template>

<script>
  export default {
    name: "Home",
  }
</script>
<style scoped>

</style>

News.vue

<template>
    <ul>
        <li>news001<input></input></li>
        <li>news002<input></input></li>
        <li>news003<input></input></li>
    </ul>
</template>

<script>
    export default {
        name:'News'
    }
</script>

34.路由_钩子(activate,deactivate)

Vue学习进度二_第59张图片
News.vue

<template>
    <ul>
        <li :style="{opacity}">欢迎学习vue</li>
        <li>news001 <input type="text"></li>
        <li>news002 <input type="text"></li>
        <li>news003 <input type="text"></li>
    </ul>
</template>

<script>
    export default {
        name:'News',
        data(){
            return{
                opacity:1
            }
        },
        activated(){
            console.log('News组件被激活了')
            this.timer = setInterval(() => {
                this.opacity -= 0.01
                if(this.opacity <= 0) this.opacity = 1
            },16)
        },
        deactivated(){
            console.log('News组件失活了')
            clearInterval(this.timer)
        }
    }
</script>

35.路由_全局路由守卫&&独享路由守卫

31.1总结

在这里插入图片描述
1.全局守卫

// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {
	console.log('beforeEach',to,from)
	if(to.meta.isAuth){ // 判断当前路由是否需要进行权限控制
		if(localStorage.getItem('school') === 'atguigu'){ // 权限控制的具体规则
			next()	// 放行
		}else{
			alert('暂无权限查看')
		}
	}else{
		next()	// 放行
	}
})

// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from) => {
	console.log('afterEach',to,from)
	if(to.meta.title){ 
		document.title = to.meta.title //修改网页的title
	}else{
		document.title = 'vue_test'
	}
})

2.独享守卫

beforeEnter(to,from,next){
	console.log('beforeEnter',to,from)
    if(localStorage.getItem('school') === 'atguigu'){
        next()
    }else{
        alert('暂无权限查看')
    }
}

35.2代码

index.js

// 引入插件
import VueRouter  from "vue-router"
// 引入组件
import Home from "../pages/Home"
import About from "../pages/About"
import News from "../pages/News"
import Messages from "../pages/Messages"
import Detail from "../pages/Detail"
// 引入router路由器


 
const router =  new VueRouter({
    routes:[
        {
            name:"guanyu",
            path:"/about", //key
            component:About,//value
            meta:{isAuth:false,title:"关于"} //不需要校验
        },
        {
            name:"jia",
            path:"/home",
            component:Home,
            meta:{isAuth:false,title:"主页"},
            children:[
                {   
                    name:"xinwen",
                    path:"news",
                    component:News,
                    meta:{isAuth:true,title:"新闻"},
                    // 独享守卫,特定路由切换之后被调用
                    beforeEnter:(to,from,next)=>
                    {
                        // console.log(to,from,next)
                        // 到达需要校验的组件, 判断当前路由是否需要进行权限控制
                        if(to.meta.isAuth)
                        {
                            if(localStorage.getItem('school')==="河南中医药大学")
                            {
                                next()
                            }
                            else
                            {
                                alert("学校不是河南中医药大学!!")
                            }
                        }
                        else
                        {
                            next()
                        }  
                    }
                },
                {
                    name:"xiaoxi",
                    path:"messages",
                    component:Messages,
                    meta:{isAuth:true,title:"消息"},
                    children:[
                        {
                            name:"xiangqing",
                            path:"detail/:id/:title",
                            component:Detail,
	                        //第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件 【固定数据】
                            // props:{a:1,b:"hello"}

                            //第二种写法:props值为布尔值,为true时,则把路由收到的所有params参数通过props传给Detail组件【params】
                            // props:true,

                            //第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件 【params,query】
                            props($route){
                                return {
                                    id:$route.params.id,
                                    title:$route.params.title,
                                    // id:$route.query.id,
                                    // title:$route.query.title,
                                }
                            }
                        }
                    ]
                },
            ]
        }
    ]
})


// // 全局前置守卫:初始化时、每次路由切换前执行
// router.beforeEach((to,from,next)=>{
//     // console.log(to,from,next)
//     // 到达需要校验的组件, 判断当前路由是否需要进行权限控制
//     if(to.meta.isAuth)
//     {
//         if(localStorage.getItem('school')==="河南中医药大学")
//         {
//             next()
//         }
//         else
//         {
//             alert("学校不是河南中医药大学!!")
//         }
//     }
//     else
//     {
//         next()
//     }
// })

// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from)=>{
    // console.log(to,from)
    document.title = to.meta.title || "前端vue学习"
})

export default router


36.路由_组件内路由守卫

Vue学习进度二_第60张图片

About.vue

<template>
  <div>
    <h1>我是Aoubt页面展示的</h1>
  </div>
</template>

<script>
  export default {
    name: "About",
    //进入守卫:通过路由规则,进入该组件时被调用
    beforeRouteEnter (to, from, next) 
    {
      console.log("beforeRouteEnter进入了About")
      // 到达需要校验的组件, 判断当前路由是否需要进行权限控制
      if(to.meta.isAuth)
      {
          if(localStorage.getItem('school')==="河南中医药大学11111")
          {
              next()
          }
          else
          {
              alert("学校不是河南中医药大学!!")
          }
      }
      else
      {
          next()
      }
    },
    //离开守卫:通过路由规则,离开该组件时被调用
    beforeRouteLeave (to, from, next) 
    {
      console.log("beforeRouteLeave离开了About")
      next()
    },
  }
</script>
<style scoped>

</style>

37.路由_hash,history

Vue学习进度二_第61张图片

const router =  new VueRouter({
	mode:'history',
	routes:[...]
})

export default router

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