Vue2.x 学习笔记

vue-cli3全位对vue-cli2(https://cli.vuejs.org/zh/config/#vue-config-js)

  • 安装node

选择对应系统进行下载,下载完成后直接安装即可

http://nodejs.cn/download/

// 输下命令,成功输出版本即为安装成功

node -v

  • 安装vue-cli3

npm install -g @vue/cli

// 输出版本号即为安装成功

vue -V

  • 创建项目

vue create project 或 可视化创建  vue ui

vue init webpack project

  • CLI服务
  • 脚本名更改
  • 启动服务的依赖更改

       CLi3启动方式是:vue-cli-service serve

       CLi2启动方式是:webpack-dev-server --inline --progress --config

  • 生成的目录结构介绍

  • 3.0的目录简单了很多,少了build、config两个目录。需要对webpack进行配置的话,要手动在根 目录新建一个vue.config.js文件
  • vue.config.js 常用配置
// vue.config.js 常用配置
module.exports = {
    // 基本路径, vue.cli 3.3以前请使用baseUrl
    publicPath: '/',
    // 输出文件目录
    outputDir: 'dist',
    // 用于嵌套生成的静态资产(js,css,img,fonts)的目录。
    assetsDir: '',
    // 生产环境sourceMap
    productionSourceMap: true,
    // webpack配置
    configureWebpack: () => {},
    chainWebpack: () => {},
    // css相关配置
    css: {
        // 启用 CSS modules
        modules: false,
        // 是否使用css分离插件
        extract: true,
        // 开启 CSS source maps?
        sourceMap: false,
        // css预设器配置项
        loaderOptions: {},
    },
    // webpack-dev-server 相关配置
    devServer: {
        host: '0.0.0.0',
        port: 8080,
        proxy: {}, // 设置代理
    },
    // 第三方插件配置
    pluginOptions: {
        // ...
    }
}

 

引包、留坑、实例化 、插值表达式{{}}

1、引包

  • 确认已经下载了node,然后执行命令 npm install vue  (如需下载自己要的版本在vue后面加上@版本号)

  • 页面引入下载的包

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 或者 <script type="text/javascript" src="vue.js"> </script>

2、留坑

即留一个vue模板插入的地方或者是vue代码对其生效的地方

3、实例化  即启动Vue

启动: new Vue({el:目的地,template:模板内容});实例化传入的是一个对象options

options

  • 目的地:  el 对应上面留坑的坑位,可通过id名,类名,标签名来查找 。方式和jq一样

  • 内容:    template

  • 数据:  data 值为函数形式也可是对象,但是都是用函数,因为用的函数最后也是return一个对象

4、插值表达式{{ }}

插值表达式内填入data里面的变量即可在页面取到变量值{{ data里的变量 }}

代码示例

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<!-- 留坑 -->
	<div id="app"></div>


	<!-- 引包 -->
	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		// 实例化启动vue
		new Vue({
			el:'#app',//目的的,可以识别类名、id名和标签名,如果做到极致优化可以直接用document.getElementById获取
			template:`     
			<div>
				<div>我这里是模板内容{{ msg }}</div>
				<div>111</div>
			</div>
			`,//模板内容,根节点只能有一个
			data:function(){
				return {
					msg:'Hello Vue!'
				}
			}
		})
	</script>
</body>
</html>

vue的常用指令以及使用场景

1、什么是指令

  • 在vue中提供一些对于页面+数据的更为方便的操作,这些操作就叫做指令。

    • 譬如在HTML页面中这样使用<div v-xxx=''></div>
  • 在vue中v-xxx就是vue的指令

  • 指令就是以数据去驱动DOM行为的,简化DOM操作

2、常用的指令有哪些,及怎么使用这些指令

  • v-text 不可解析html标签

  • v-html 可解析html标签

  • v-if 做元素的插入(append)和移除(remove)操作

  • v-else-if  判断

  • v-else   判断

  • v-show   display:none 和 display:block的切换

  • v-for

    • 数组 item,index
    • 对象 value,key ,index

代码演示

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app"></div>
	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		
		new Vue({
			el:'#app',
			template:`
			<div>
					<!--测试v-text-->
					<div v-text='mytext'></div>
					</hr>
					<!--测试v-html-->
					<div v-html='myhtml'></div>
					<!--测试v-if  v-else-if  v-else-->
					<button v-if='num==1'>测试v-if</button>
					<button v-else-if='num==2'>测试v-else-if</button>
					<button v-else>测试v-else</button>

					<!--测试v-show-->
					<div v-show='checkshow'>我是V-SHOW</div>
					<!--循环数组-->
					<ul>
					    <li v-for='(item,index) in arrayfor'>
					        {{ item }}-{{index}}
					    </li>
					</ul>
					<ul>
					    <!--循环对象-->
					    <li v-for='(oj,key) in ojfor'>
					        {{key}}:{{oj}}
					    </li>
					</ul>
			</div>
			`,
			data:function(){
				return {
					mytext:'<h1>我这里是v-text</h1>',
					myhtml:'<h1>我这里是v-html</h1>',
					checkvif:true,
					num:6,
					checkshow:true,
					arrayfor:['篮球','足球','乒乓球'],
					ojfor:{play:'篮球',people:'ming',age:'19'}
				}
			}
		})
	</script>
</body>
</html>

vue单双向数据流及事件绑定

1、vue单向数据流绑定属性值 v-bind: (属性) 简写 :(属性)

例子:<input v-bind:value="name" v-bind:class="name">

  • 单向数据绑定 内存改变影响页面改变
  • v-bind就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染

2、vue双向数据流 v-model 只作用于有value属性的元素

例子:<input v-model="name" v-bind:class="name">

  • 双向数据绑定, 页面对于input的value改变,能影响内存中name变量
  • 内存js改变name的值,会影响页面重新渲染最新值

3、事件绑定v-on:事件名="表达式||函数名"   简写  @事件名="表达式||函数名"

事件名可以是原生也可以是自定义的

4、总结

v-model 双向数据绑定

  • vue页面改变影响内存(js)
  • 内存(js)改变影响vue页面

v-bind 单向数据绑定只是内存(js)改变影响vue页面

代码演示

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app"></div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		console.log(this)
		new Vue({
			el:"#app",
			template:`
				<div>
				单向数据绑定
				<input type='text' v-bind:value="name" :class="name"><br>
				双向数据绑定
				<input type='text' v-model="name"></br>
				{{ name }}
				<button v-on:click="change">点击我改变name变量</button>
				</div>
			`,
			data:function(){
				return {
					name:'hello'
				}
			},
			methods:{
				change:function(){
					console.log(this)
					this.name='我改变了,是在方法属性里面定义的方法'
				},
			}
		})
	</script>
</body>
</html>

过滤器

过滤器就是可以对我们的数据进行添油加醋然后再显示

  • 过滤器有全局过滤器和组件内的过滤器

    • 全局过滤器Vue.filter('过滤器名',过滤方式fn );

    • 组件内的过滤器 filters:{ '过滤器名',过滤方式fn }

    • {{ msg | 过滤器名}}

  • 最终都是在过滤方式fn里面 return 产出最终你需要的数据

vue中的this是vue封装好给我们使用的,跟平常方法里面的this是不同的

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>过滤器</title>
</head>
<body>
		<div id="app">
			我输入的:<input type="text" name="" v-model='instring'></br>
			我输出的:{{ instring }}</br>
			{{ instring | reversal('翻转输出:')}}
		</div>

		<script type="text/javascript" src="vue.js"></script>
		<script type="text/javascript">
			console.log(this)
			Vue.filter('reversal',function(val,arg2){
				return  arg2+val.split('').reverse().join('')
			})
			new Vue({
				el:'#app',
				data(){
					return {
						instring:''
					}
				},
				created(){
					console.log(this,'vue的')
				}
				// filters:{
				// 	reversal(val,arg2){
				// 		//          字符串转数组  翻转数组转字符串
				// 		return  arg2+val.split('').reverse().join('')
				// 	}
				// }
			})
		</script>
</body>
</html>

数据监听 watch  计算属性 computed

watch监听单个,computed监听多个

思考业务场景:

1. 类似淘宝,当我输入某个人名字时,我想触发某个效果
2. 利用vue做一个简单的计算器

当watch监听的是复杂数据类型的时候需要做深度监听

watch:{
    msg:{
         handler(val){
            if(val.text=='vincent'){
                alert(val.text)
            }
         },
         deep:true//开启深度监听
    }
}

computed 监视对象, 写在了函数内部, 凡是函数内部有 this.相关属性 ,改变都会触发当前函数

代码演示

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app">
		<div>watch监听数据</div>
		<input type="text" name="" v-model='msg.text'>
		<div>computed计算属性</div>
		(<input type="text" name="" v-model='n1'>+
		<input type="text" name="" v-model='n2'>)*
		<input type="text" name="" v-model='n3'>={{result}}
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		
		new Vue({
			el:'#app',
			data(){
				return {
					msg:{text:''},
					n1:'',
					n2:'',
					n3:'5'
				}
			},
			computed:{
				result(){
					return (Number(this.n1)+Number(this.n2))*Number(this.n3)
				}
			},
			watch:{
				// msg(newval,oldval){
				// 	if(newval.text=='love'){
				// 		alert(newval.text)
				// 	}
				// }
				msg:{
					handler(newval,oldval){
						if(newval.text=='vincent'){
							alert(newval.text)
						}
					},
					deep:true
				}
			}
		})
	</script>
</body>
</html>

组件化开发

  • 创建组件的两种方式

var Header = { template:'模板' , data是一个函数,methods:功能,components:子组件们 }  //局部声明

Vue.component('组件名',组件对象);//全局注册  等于注册加声明了

  • 组件类型
  • 通用组件(例如表单、弹窗、布局类等)

  • 业务组件(抽奖、机器分类)

  • 页面组件(单页面开发程序的每个页面的都是一个组件、只完成功能、不复用)

组件开发三步曲:声明、注册、使用

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>组件化开发</title>
</head>
<body>
	<div id="app">

	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		var MyHeader={
			template:`
				<div>我是头部</div>
			`,

		}
		var MyBody=Vue.extend({
			template:`
				<div>我是身体</div>
			`
		})
		//这个是语法糖
		// var MyBody={
		// 	template:`
		// 		<div>我是身体</div>
		// 	`
		// }
		Vue.component('MyFooter',{
			template:`
				<div>我是尾部</div>
			`
		})
		new Vue({
			el:'#app',
			//注册组件
			components:{
				MyHeader,
				MyBody
			},
			template:`
				<div>
					<my-header></my-header>
					<my-body></my-body>
					<my-footer></my-footer>
				</div>
			`,
			data(){
				return{}
			},
		})
	</script>
</body>
</html>

slot插槽和 ref、$parent

  • slot插槽
  • slot就是子组件里给DOM留下的坑位

  • <子组件>DOM</子组件>

  • slot是动态的DOM

  • ref获取子组件实例
  • 识别:在子组件或元素上使用属性ref="xxxx"

  • 获取:this.$refs.xxxx 获取元素

  • $el 是拿其DOM

  • $parent获取父组件实例(可在子组件直接使用this.$parent即可)

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>组件化开发</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		var Child={
			template:`
				<div>我是子组件</div>
			`,
			data(){
				return {
					msg:'hello'
				}
			},
			created(){
				console.log(this.$parent)
			}

		}
		var Parent={
			template:`
				<div>
				我是父组件
				<slot name='hello'></slot>
				<child ref='childs'></child>
				</div>
			`,
			components:{
				Child
			},
			data(){
				return {
					parents:'我是父组件'
				}
			},
			mounted(){
				// console.log(this.$refs.childs)
			}
		}
		
		new Vue({
			el:'#app',
			components:{
				Parent
			},
			template:`
				<div>
					<parent>
						<div>我是插槽内容</div>
						<div slot='hello'>我是插槽内容2</div>
					</parent>
				</div>
			`,
			data(){
				return{}
			},
		})
	</script>
</body>
</html>

父子组件的通信

  • 父传子

  • 父用子的时候通过属性传递

  • 子要声明 props:['属性名'] 来接收

  • 收到就是自己的了,随便你用

    • 在template中 直接用

    • 在js中 this.属性名 用

  • 子传父
  • 子组件里通过$emit('自定义事件名',变量1,变量2)触发

  • 父组件@自定义事件名=‘事件名’ 监听

  • 子组件方法里  this.$emit('sendfather',val1,val2) 触发自定义事件
    父组件里  <child @sendfather='mymethods'></child>

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>父子组件的通信</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		//子组件定义好了props直接用
		var Child={
			template:`
				<div>
				    我是子组件{{sendchild}}
				    <button @click='sendparent'>我要反馈东西给父亲</button>
				</div>
			`,
			props:['sendchild'],
			methods:{
				sendparent(){
					this.$emit('baba','这是儿子组件给你的')
				}
			}
		}
		//父组件通过属性sendchild传递了数据给子组件
		var Parent={
			template:`
				<div>
				    我是父组件{{ msg }}
				    <child sendchild='父亲给你的' @baba='reserve'></child>
				</div>
			`,
			components:{
				Child
			},
			data(){
				return {
					msg:''
				}
			},
			methods:{
				reserve(val){
						this.msg=val
				}
			}
		}
		
		new Vue({
			el:'#app',
			components:{
				Parent
			},
			template:`
				<div>
				<parent></parent>
				</div>
			`,
			data(){
				return {

				}
			},
		})
	</script>
</body>
</html>

非父子组件之间的通信

  • 创建一个空实例(bus中央事件总线也可以叫中间组件)
  • 利用 $emit $on 的触发和监听事件实现非父子组件的通信

Vue.prototype.$bus=new Vue()  //在vue上面挂载一个$bus作为中央处理组件


this.$bus.$emit('自定义事件名','传递的数据')   //触发自定义事件传递数据


this.$bus.$on('自定义事件名',fn) //监听自定义事件获取数据

解决的方案还有vuex、provide/inject 是解决同根往下派发、本地存储也可以进行非父子组件之间的通信

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>非父子组件的通信</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">

		Vue.prototype.$bus=new Vue()
		var MyHeader={
			template:`
				<div>
				我是头部
				{{ headermsg }}
				</div>
			`,
			data(){
				return {
					headermsg:'我是头部的信息'
				}
			},
			created(){
				// var self=this
				// self.$bus.$on('sending',function(val){
				// 	self.headermsg=val
				// })
				this.$bus.$on('sending',val=>{
					this.headermsg=val
				})
			}
		}
		var MyBody={
			template:`
				<div>我是身体</div>
			`,
		}
		var MyFooter={
			template:`
				<div>我是底部<button @click='sendhead'>我要跟头部通信</button></div>
			`,
			methods:{
				sendhead(){
					this.$bus.$emit('sending','我是底部的数据')
				}
			}
		}
		new Vue({
			el:'#app',
			components:{
				MyHeader,
				MyBody,
				MyFooter
			},
			template:`
				<div>
					<my-header></my-header><hr>
					<my-body></my-body><hr>
					<my-footer></my-footer>
				</div>
			`,
			data(){
				return {}
			},
		})
	</script>
</body>
</html>

vue的生命周期

  • 需要频繁的创建和销毁组件

比如页面中部分内容显示与隐藏,但是用的是v-if

  • 组件缓存
  • 内置组件中<keep-alive>

  • 被其包裹的组件,在v-if=false的时候,不会销毁,而是停用

  • v-if="true" 不会创建,而是激活

  • 避免频繁创建组件对象的性能损耗

  • 组件的激活和停用

    • activated 和 deactivated

  • 成对比较
  • created 和 beforeCreate

    • A 可以操作数据 B 数据没有初始化

  • mounted 和 beforeMount

    • A 可以操作DOM   B 还未生成DOM

  • updated 和 beforeUpdate

    • A 可以获取最终数据   B 可以二次修改

  • destroyed 和 beforeDestroy

    性能调优:频繁销毁创建的组件使用内置组件<keep-alive></keep-alive>包裹

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>vue的生命周期</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript" src="main.js">

	</script>
</body>
</html>
 // created 和 beforeCreate 

 // A 可以操作数据 B 数据没有初始化

 // mounted 和 beforeMount

 // A 可以操作DOM B 还未生成DOM

 // updated 和 beforeUpdate

 //  A 可以获取最终数据 B 可以二次修改

 // destroyed 和 beforeDestroy
var Test={
	template:`
		<div>我是Test组件{{ msg }}
		<button @click="msg+='1'">msg+1</button>
		</div>
	`,
	data(){
		return{
			msg:'hello vincent'
		}
	},
	//组件创建前
	beforeCreate(){
		console.log('组件创建前')
		console.log(this.msg)
	},
	//组件创建后
	created(){
		console.log('组件创建后')
		console.log(this.msg)
	},
	//Dom挂载前
	// beforeMount(){
	// 	console.log('Dom挂载前')
	// 	console.log(document.body.innerHTML)
	// },
	// //Dom挂载后
	// mounted(){
	// 	console.log('Dom挂载后')
	// 	console.log(document.body.innerHTML)
	// }
	//基于数据更新前
	beforeUpdate(){
			console.log('数据更新前')
			console.log(document.body.innerHTML)
	},

	//基于数据更新后
	updated(){
			console.log('数据更新后')
			console.log(document.body.innerHTML)
	},
	//销毁前
	beforeDestroy(){
		console.log('销毁前')
	},
	//销毁后
	destroyed(){
		console.log('销毁后')
	},
	//组件停用
	deactivated(){
		console.log('组件停用')
	},
	//组件激活
	activated (){
		console.log('组件激活')
	}
}
new Vue({
	el:'#app',
	components:{
		Test	
	},
	template:`
		<div>
			<keep-alive><test v-if='testshow'></test></keep-alive></br>
			<button @click='clickbut'>销毁组件</button>
		</div>
	`,
	data(){
		return {
			testshow:true
		}
	},
	methods:{
		clickbut(){
			this.testshow=!this.testshow
		}
	}
})

路由的跳转原理(哈希模式)

  • 单页应用的路由模式有两种
  • 哈希模式(利用hashchange 事件监听 url 的hash 的改变)

  • history模式(使用此模式需要后台配合把接口都打到我们打包后的index.html上)

  • 哈希模式原理
window.addEventListener('hashchange', function(e) {
  console.log(e)
})

核心是锚点值的改变,我们监听到锚点值改变了就去局部改变页面数据,不做跳转。跟传统开发模式url改变后 立刻发起请求,响应整个页面,渲染整个页面比路由的跳转用户体验更好

代码演示

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<a href="#/login">登录</a>
	|
	<a href="#/register">注册</a>
	<div id="app"></div>

	<script type="text/javascript">
		var appdiv=document.getElementById('app')

		window.addEventListener('hashchange', function(e) {
			  console.log(location.hash)
			  switch(location.hash){
			  	case '#/login':
			  	    appdiv.innerHTML='我是登录页面';
			  	break;
			  	case '#/register':
			  	    appdiv.innerHTML='我是注册页面';
			  	break;
			  }
			})
	</script>
</body>
</html>

安装和使用路由

路由是以插件的形式引入到我们的vue项目中来的

  • vue-router是vue的核心插件

1:下载 npm i vue-router -S

2:安装插件Vue.use(VueRouter);

3:创建路由对象 var router = new VueRouter();

4:配置路由规则 router.addRoutes([路由对象]);

路由对象{path:'锚点值',component:要(填坑)显示的组件}

5:将配置好的路由对象交给Vue

  • options中传递-> key叫做 router

6:留坑(使用组件) <router-view></router-view>

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>路由的安装和使用</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Login={
			template:`
				<div>我是登录页面</div>
			`,
		}
		//安装路由插件
		Vue.use(VueRouter);
		//创建路由对象
		var router= new VueRouter({
			//配置路由对象
			routes:[
				{path:'/login',name:'login',component:Login}
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<p>请在链接上加上login测试路由功能</p>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			},
		})
	</script>
</body>
</html>

路由的跳转

  • 路由的跳转方式
  1. 通过标签:<router-link to='/login'></router-link>

  2. 通过js控制跳转: this.$router.push({path:'/login'})

  • 区别

this.$router.push() :跳转到指定的url,会向history插入新记录

this.$router.replace() :同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的

this.$router.go(-1) :常用来做返回,读history里面的记录后退一个

  • vue-router中的对象
  • $route   路由信息对象,只读对象
  • $router  路由操作对象,只写对象

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>路由的跳转</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">

		var Login={
			template:`
				<div>我是登录页面</div>
			`,
		}
		var Register={
			template:`
				<div>我是注册页面</div>
			`,
		}
		var Buy={
			template:`
				<div>我要买东西</div>
			`,
		}
		//安装路由插件
		Vue.use(VueRouter);
		//创建路由对象
		var router= new VueRouter({
			//配置路由对象
			routes:[
				{path:'/login',name:'login',component:Login},
				{path:'/register',name:'register',component:Register},
				{path:'/buy',name:'buy',component:Buy},
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-link to='/login'>去登录</router-link>
					|
					<router-link to='/register'>去注册</router-link>
					<div>
						<button @click='goregister'>我要去买东西</button>
						<button @click='back'>返回上一页</button>
					</div>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			},
			methods:{
				goregister(){
					//push跟replace是达到同样效果,但是replace是不会向history插入记录
					// this.$router.push({path:'/register'})
					this.$router.replace({path:'/buy'})
				},
				back(){
					this.$router.go(-1)
				}
			}
		})
	</script>
</body>
</html>

路由的传参和取参

1、查询参

  • 配置(传参) :to="{name:'login',query:{id:loginid}}"

  • 获取(取参) this.$route.query.id

2、路由参数

  • 配置(传参) :to="{name:'register',params:{id:registerid} }"

  • 配置路由的规则 { name:'detail',path:'/detail/:id'}

  • 获取 this.$route.params.id

总结

  1. :to传参的属性里 params 是和name配对的 query和name或path都可以

  2. 使用路由参数必须要配置路由规则里面配置好参数名,否则刷新页面参数会丢失

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>路由的跳转</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Login={
			template:`
				<div>我是登录页面 
					<span>这是我获取到的参数: {{ msg }}</span>
				</div>
			`,
			data(){
				return { 
					msg:''
				}
			},
			created(){
				this.msg=this.$route.query.id
			}
		}
		var Restiger={
			template:`
				<div>我是注册页面
					<span>这是我获取到的路由参数:{{ foo }}</span>
				</div>
			`,
			props:['foo']
			// data(){
			// 	return {
			// 		restigerfoo:''
			// 	}
			// },
			// created(){
			// 	this.restigerfoo=this.$route.params.foo
			// }
		}
		//安装路由插件
		Vue.use(VueRouter);
		//创建路由对象
		var router= new VueRouter({
			//配置路由对象
			routes:[
				{path:'/login',name:'login',component:Login},
				{path:'/restiger/:foo',name:'restiger',props:true, component:Restiger},
			]
		})
        // js跳转路由传参和标签传参,路由相同而参数不同时页面不做刷新的问题
        // 解决:<router-view :key="$route.fullPath"></router-view>
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-link :to="{name:'login',query:{id:'123'}}">去登录</router-link>
					|
					<router-link :to="{name:'restiger',params:{foo:'bar'}}">去注册</router-link>
					<button @click='jslink'>js跳转去登录</button>
					<router-view :key="$route.fullPath"></router-view>
				</div>
			`,
			data(){
				return {}
			},
			methods:{
				//js跳转传参是一样的
				jslink(){
					this.$router.push({name:'login',query:{id:'456'}})
				}
			}
		})
	</script>
</body>
</html>

嵌套路由

1、router-view 的细分

  • router-view 第一层中,包含一个router-view

2、每一个坑挖好了,要对应单独的组件

路由配置:

routes: [
           {
               path:'/nav',
               name:'nav',
               component:Nav,
               //路由嵌套增加此属性
               children:[
                   //在这里配置嵌套的子路由
               ]
           }
]

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>嵌套路由</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Nav={
			template:`
				<div>
					<router-view></router-view>
					<router-link :to="{name:'nav.index'}">首页</router-link>
					|
					<router-link :to="{name:'nav.pensonal'}">个人中心</router-link>
					|
					<router-link :to="{name:'nav.message'}">资讯</router-link>
					|
					<router-link :to="{name:'nav.mine'}">我的</router-link>
				</div>
			`,
		}
		var Index={
			template:`
				<div>首页</div>
			`,
		}
		var Pensonal={
			template:`
				<div>个人中心</div>
			`,
		}
		var Message={
			template:`
				<div>资讯</div>
			`,
		}
		var Mine={
			template:`
				<div>我的</div>
			`,
		}
		//安装路由插件
		Vue.use(VueRouter);
		//创建路由对象
		var router= new VueRouter({
			//配置路由对象
			routes:[
				{
					path:'',
					redirect:'/nav'
				},
				{
					path:'/nav',
					name:'nav',
					component:Nav,
					//嵌套路由增加这个属性
					children:[
						//配置我们的嵌套路由
						{path:'',redirect:'/nav/index'},
						{path:'index',name:'nav.index',component:Index},
						{path:'pensonal',name:'nav.pensonal',component:Pensonal},
						{path:'message',name:'nav.message',component:Message},
						{path:'mine',name:'nav.mine',component:Mine},
					]
				}
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			},
			methods:{
			}
		})
	</script>
</body>
</html>

路由守卫

// 通过router中的beforeEach注册全局守卫,每次切换路由时触发

const router = new VueRouter({ ... }
//前置的钩子函数 最后要执行next()才会跳转
router.beforeEach((to, from, next) => {
  // ...

  next()
})

to: 将进入的路由对象

from: 将离开的路由对象

next(): 确认完成操作,最后一定要调用,不然路由就不会进行切换


//后置的钩子函数 已经跳转了不需要next
router.afterEach((to, from) => {
  // ...
})

路由守卫主要用于检验是否登录了,没登录就跳转到登录页面不让他在其他页面停留,但是现在这种处理主要的都用请求的全局拦截来做了

  • 路由懒加载
  • 提高页面加载速度
  • 避免进入项目后加载全部组件
  • 在路由中的 component 中设置函数,用 import 方式进行使用

component: () => import('./views/Home.vue'),

代码演示

<!DOCTYPE html>
<html>
<head>
	<title>路由守卫</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Nav={
			template:`
				<div>
					<router-view></router-view>
					<router-link :to="{name:'nav.index'}">首页</router-link>
					|
					<router-link :to="{name:'nav.pensonal'}">个人中心</router-link>
					|
					<router-link :to="{name:'nav.message'}">资讯</router-link>
					|
					<router-link :to="{name:'nav.mine'}">我的</router-link>
				</div>
			`,
		}
		var Index={
			template:`
				<div>首页</div>
			`,
		}
		var Pensonal={
			template:`
				<div>个人中心</div>
			`,
		}
		var Message={
			template:`
				<div>资讯</div>
			`,
		}
		var Mine={
			template:`
				<div>我的</div>
			`,
		}
		//安装路由插件
		Vue.use(VueRouter);
		//创建路由对象
		var router= new VueRouter({
			//配置路由对象
			routes:[
				{
					path:'',
					redirect:'/nav'
				},
				{
					path:'/nav',
					name:'nav',
					component:Nav,
					//嵌套路由增加这个属性
					children:[
						//配置我们的嵌套路由
						{path:'',redirect:'/nav/index'},
						{path:'index',name:'nav.index',component:Index},
						{path:'pensonal',name:'nav.pensonal',component:Pensonal},
						{path:'message',name:'nav.message',component:Message},
						{path:'mine',name:'nav.mine',component:Mine},
					]
				}
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {
					loginstate:true
				}
			},
			methods:{
			},
			mounted(){
				//利用路由守卫做当跳转首页时可直接跳转,跳转其他页面要等待两秒才可以跳转
				router.beforeEach((to,from,next)=>{
					console.log(to)
					if(to.path=='/nav/index'){
						next()
					}else{
						setTimeout(function(){
								next()
						},2000)
					}
				})
			}
			
		})
	</script>
</body>
</html>

状态管理中心—vuex的用法

  • State

数据,存放一些公用部分的数据

  • Mutations

数据怎么改变,定义改变state的一些方法

  • Actions

异步改变, 如果需要异步改变state,则在这书写

  • vuex里包含的基本参数
export default {
 // 组件间公共数据部分
 state: {},
 // 需要改变state中的数据时,要在mutation里定义改变的方法
 mutations: {},
 // 当改变state中的数据是异步操作时,在action里定义
 actions: {}
}
  • vuex中的计算属性—Getters
  • 当你需要依赖vuex里的state中的数据,做进一步处理时使用
state: {
 count: 0,
},
// 根据state中的count进⼀步处理,计算双倍值
getters: {
 doubleCount (state) {
 return state.count * 2
 }
},
  • 模块化概念—Modules
  • 当vuex里的数据十分庞大时,可根据存放的数据所属模块进行划分
import Vue from 'vue'
import Vuex from 'vuex'
// 第一步 引入模块
import text from './text'
Vue.use(Vuex)
// 第二步 在初始化store时,加载模块
export default new Vuex.Store({
 modules: {
 text
 }
})

 

购物车实战代码演示

<!DOCTYPE html>
<html>
<head>
	<title>购物车</title>
	<style type="text/css">
		span{cursor: pointer;}
	</style>
</head>
<body>
	<div id="app">
		<div>
			课程:<input type="text" name="" v-model='course'>
			价钱:<input type="text" name="" v-model='price'>
			<button @click='addcourse'>添加商品</button>
		</div>
		<ul>
			<li v-for='(list,index) in classlist'>
				课程名称:{{list.text}}---价格:{{list.price}}
				<button @click='addtochat(index)'>添加到购物车</button>
			</li>
		</ul>
		<chat :chatarr='chatarr'></chat>
	</div>
	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		var Chat={
			props:['chatarr'],
			template:`
				<div>
					购物车
					<table border="1">
						<tr>
							<th>选中</th>
							<th>课程</th>
							<th>数量</th>
							<th>价格</th>
						</tr>
						<tr v-for="(chat,index) in chatarr">
							<td><input type="checkbox" name="" v-model='chat.active'></td>
							<td>{{chat.text}}</td>
							<td>
								<span @click='reducecount(index)'>-</span>
								{{chat.count}}
								<span @click='addcount(index)'>+</span>

							</td>
							<td>{{chat.count * chat.price}}</td>
						</tr>
						<tr>
							<td colspan='2'>选中的课程:{{activeCount}}/{{count}}</td>
							<td colspan='2'>需付金额:{{totalpirce}}</td>
						</tr>
					</table>
				</div>

			`,
			//计算属性
			computed:{
				//已选中课程
				activeCount(){
					return this.chatarr.filter(v=>v.active).length
				},
				//购物车存在多少项课程
				count(){
					return this.chatarr.length
				},
				//总价
				totalpirce(){
					let total=0
					this.chatarr.forEach(v=>{
						if(v.active){
							total+=v.price*v.count
						}
					})
					return total
				}
			},
			watch:{
				//监听购物车数组,每当监听到改变就存进本地存储做数据持久化
				chatarr:{
					handler(){
						window.localStorage.setItem('chat',JSON.stringify(this.chatarr))
					},
					deep:true
				}
			},
			methods:{
				//增加购物车商品数量
				addcount(index){
					this.chatarr[index].count++
				},
				//减少购物车商品数量
				reducecount(index){
					if(this.chatarr[index].count>1){
						this.chatarr[index].count--
					}else{
						if(window.confirm(`是否删除${this.chatarr[index].text}?`)){
							this.chatarr.splice(index,1)
						}
					}
				}
			}
		}
		new Vue({
			el:'#app',
			components:{
				Chat
			},
			data(){
				return {
					classlist:[
						{text:'springcloud',price:200},
						{text:'vue',price:150},
						{text:'js',price:80},
						{text:'php',price:60},
					],
					course:'',
					price:'',
					chatarr:[],//购物车数组
				}
			},
			methods:{
				//添加课程
				addcourse(){
					//插入数据到我们的商品库
					this.classlist.push({text:this.course,price:this.price})
					//清空我们刚输入的商品信息
					this.course=''
					this.price=''
				},
				//添加到购物车
				addtochat(index){
					const goods=this.classlist[index]
					const result=this.chatarr.find(v=>v.text==goods.text)
					if(result){
						result.count+=1
					}else{
						this.chatarr.push({...goods,count:1,active:true})
					}
				},
			
			},
			created(){
				//利用本地存储做数据持久化  获取本地存储数据
                if(window.localStorage.getItem('chat') != null){
				    this.chatarr=JSON.parse(window.localStorage.getItem('chat')) 
                }else {
                    this.chatarr=[]
                }
			}
		})
	</script>
</body>
</html>

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值