Vue
引入vue和element-ui
<!--引入 element-ui 的样式,-->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 必须先引入vue, 后使用element-ui -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<!-- 引入element 的组件库-->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
核心知识
留坑
即留一个vue模板插入的地方或者是vue代码对其生效的地方
注意:template里只能有一个最大的div 都包含在一个大div里面
实例化
即启动Vue
启动: new Vue({el:目的地template模板内容});实例化传入的是一个对象options
- options
- 目的地 el 对应上面留坑的坑位,可通过id名,类名,标签名来查找 。方式和jq一样
- 内容 template
- 数据 data 值为函数形式也可是对象,但是都是用函数,因为用的函数最后也是return一个对象
插值表达式{{ }}
插值表达式内填入data里面的变量即可在页面取到变量值{{ data里的变量 }}
<body>
<!-- <el-button>按钮</el-button> -->
<div id="app">
<div v-html='msg2'></div>
</div>
</body>
<script>
new Vue({
el:'#app',
template:`
<div>
<div v-text='msg'></div> //text不能输出标签
<div v-html='msg2'></div> //html可以输出标签
<el-button v-if="num===1">按钮一</el-button>
<el-button v-else-if="num===2">按钮二</el-button> 注意 可以写v-else-if
<el-button v-else>按钮三</el-button>
</div>
`,
data:function(){
return {
msg: '<h1>hello world</h1>', //<h1>hello world</h1>
msg2: '<h1>hello world</h1>', //heool word
num:3
};
},
})
</script>
v-show隐藏是增加了一个样式
v-if隐藏是在这里留了个空位
vue指令
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
new Vue({
el:'#app',
template:`
<div>
<div v-for="(item,index) in array">{{item}}{{index}}</div> //遍历数组 index是下标
<div v-for="(obj,index) in objfor">{{key}}:{{obj}}</div> //遍历对象 index是key 就是定义的属性名
</div>
`,
data:function(){
return {
//定义一个数组
array:[
'篮球','足球','乒乓球'
],
//定义一个对象
objfor:{
name:'张三',age:12,sex:'男'
}
};
},
})
vue单双向数据流及事件绑定
简介:
vue特色之数据的双向绑定和事件绑定详解
vue单向数据流绑定属性值
v-bind: (属性) 简写 :(属性)
例子:
单向数据绑定 内存改变影响页面改变
v-bind就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染
vue双向数据流
v-model 只作用于有value属性的元素
例子:
双向数据绑定 页面对于input的value改变,能影响内存中name变量
内存js改变name的值,会影响页面重新渲染最新值
template:`
<div>
//单项数据绑定 不会影响
<el-input v-bind:value="name"></el-input>
// 双项数据绑定 会影响到内存值的改变
<el-input v-model="name2"></el-input>
</div>
`,
data:function(){
return {
name:'张三',
name2:'李四'
};
},
事件绑定
v-on:事件名=“表达式||函数名” 简写 @事件名=“表达式||函数名”
事件名可以是原生也可以是自定义的
//可以在点击事件中 直接改变值
也可以在methods中定义一个方法 在这里填写方法名
<el-button v-on:click="name='李四'">nameChange</el-button>
总结
-
v-model 双向数据绑定
-
vue页面改变影响内存(js)
-
内存(js)改变影响vue页面
-
v-bind 单向数据绑定只是内存(js)改变影响vue页面
过滤器
简介:
- 讲述如何给数据添加一个管道进行进一步处理再输出
- 过滤器就是可以对我们的数据进行添油加醋然后再显示
- 过滤器有全局过滤器和组件内的过滤器
全局过滤器Vue.filter(‘过滤器名’,过滤方式fn );
组件内的过滤器 filters:{ ‘过滤器名’,过滤方式fn }
{{ msg | 过滤器名}}
最终都是在过滤方式fn里面return产出最终你需要的数据
vue中的this是vue封装好给我们使用的,跟平常方法里面的this是不同的
//组件内的过滤器
template: `
<div>
<el-input v-model="input" placeholder="请输入内容"></el-input>
{{input | reversal('反转输出')}} //注意过滤器的用法 {{ msg | 过滤器名}}
</div>
`,
data: function () {
return {
input: "",
};
},
//过滤器
filters: {
reversal(val,str) { //可以填写多个参数 第一个参数 | 前面那个值
//将输入的字符串反转
return str+':'+val.split("").reverse().join("");
},
},
//全局过滤器
Vue.filter('reversal',function(var1,str1){ //写在new Vue的外边 注意第一个参数要加上引号 否则系统会以为是一个变量
return str1+':'+var1.split("").reverse().join("");
})
this的指向 windos和vue中的区别
数据监听watch计算属性computed
简介:
讲述数据的单个监听以及多个监听还有深度监听的不同
watch监听单个,computed监听多个
当watch监听的是复杂数据类型的时候需要做深度监听**(写法如下)**
computed 监视对象**,写在了函数内部,** 凡是函数内部有this.相关属性,改变都会触发当前函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--引入 element-ui 的样式,-->
<link
rel="stylesheet"
href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
/>
<!-- 必须先引入vue, 后使用element-ui -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<!-- 引入element 的组件库-->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
</div>
</body>
<script>
new Vue({
el: "#app",
template: `
<div>
<el-input type='text' name='' v-model='msg2.text'></el-input>
</div>
`,
data() {
return {
// msg: "",
msg2: {
text: "", //深度监听
},
};
},
watch: {
// msg(newval){
// if(newval==='love'){
// alert('我爱你')
// }
// },
msg2: {
handler(newval,oldval) {
if (newval.text == "love") {
alert("我爱你")
}
},
deep: true, //开启深度监听
},
},
});
</script>
</html>
计算属性computed
<body>
<div id="app">
(<input v-model="num1"></input>+
<input v-model="num2"></input>)*
<input v-model="num3"></input>={{results}}
</div>
</body>
<script>
new Vue({
el: "#app",
// template: `
// <div>
// </div>
// `,
data() {
return {
num1:'',
num2:'',
num3:'1'
}
},
computed:{
results(){
return (Number(this.num1)+Number(this.num2))*Number(this.num3)
}
}
});
组件化开发
创建组件的两种方式
var Header = { template:'模板' , data是一个函数,methods:功能,components:子组件们 }//局 部声明 Vue.component('组件名',组件对象);//全局注册 等于注册加声明了
组件开发三步曲:声明、注册、使用
<body>
<div id="app">
<my-handler></my-handler>
<my-body></my-body>
<my-fonnter></my-fonnter>
</div>
</body>
<script>
var MyHandler={
template:`
<div> 我是头部 </div>
`
}
//以前的写法
// var MyBody=Vue.extend({
// template:`
// <div> 我是身体 </div>
// `
// })
//现在改进后的写法 语法糖
var MyBody={
template:`
<div> 我是身体 </div>
`
}
//全局组件 与组件注册相比少了一个s
Vue.component('MyFonnter',{
template:`
<div> 我是尾部 </div>
`
})
new Vue({
el: "#app",
components:{ //注册组件
MyHandler,
MyBody
},
}
slot插槽和ref、$parent
- slot插槽
- slot就是子组件里给DOM留下的坑位
- <子组件>DOM</子组件>
- slot是动态的DOM
<body>
<div id="app">
<father>
<!-- 如果父组件不留坑<slot /> 插槽内容就不会显示 -->
<div slot="v1">插槽内容</div> <!--插槽设置slod名称 -->
<son></son>
</father>
</div>
</body>
<script>
//现在改进后的写法 语法糖
var Father={
template:`
<div>
我是父组件
<slot name='v1'/>
</div>
`
}
var son={
template:`
<div>
子组件
</div>
`
}
new Vue({
el: "#app",
components:{ //注册组件
Father,
son
},
ref、$parent的使用
-
ref获取子组件实例
- 识别:在子组件或元素上使用属性
ref="xxxx"
- 获取:
this.$refs.xxxx
获取元素$el
是拿其DOM
- 识别:在子组件或元素上使用属性
-
$parent
$parent
获取父组件实例(可在子组件直接使用this.$parent即可)
<body>
<div id="app">
<father></father>
</div>
</body>
<script>
var son={ //子组件
template:`
<div>
子组件
</div>
`,
data(){
return{
msg:'hello' //子组件定义的变量
}
},
created(){ //vue的生命周期 钩子
console.log(this.$parent.faterMsg) //获取父组件的变量 通过$parent
}
}
var Father={ //父组件
template:`
<div>
我是父组件
<son ref="sons"></son>
<slot/>
</div>
`,
mounted() { //vue的生命周期 钩子
console.log('父组件',this.$refs) //获取子组件的变量 通过$refs
},
components:{ //在父组件里注册子组件
son
},
data(){
return{
faterMsg:'我是父组件' //父组件定义的变量
}
}
}
new Vue({
el: "#app",
components:{ //注册组件
Father,
son
},
父子通信
- 父传子
- 首先在子组件定义一个属性props 写一个名称
props:['testson']
- 然后在父组件定义子组件那里 写上 子组件定义的名称
<son testson='父给子'></son>
- 然后在子组件就可以使用父组件传来的值了
- 首先在子组件定义一个属性props 写一个名称
var son={ //子组件
template:`
<div>
子组件{{testson}} //3 把接收到的值显示出来
</div>
`,
//子组件定义一个testson变量 让父组件赋值 然后在页面显示出来
props:['testson'] //1 定义一个props属性
}
var Father={
//父组件通过子组件定义的变量 赋值 子组件接受父组件传递的值
template:`
<div>
我是父组件
<son testson='父给子'></son> // 2把子组件定义的变量赋值
</div>
`,
components:{
son
}
}
- 子传父
- 子组件里通过
$emit('自定义事件名',变量1,变量2)
触发 - 父组件
@自定义事件名=‘事件名’
监听 - 子组件方法里
this.$emit('sendfather',val1,val2)
触发自定义事件 - 父组件里 <son @sendfather=‘mymethods’>
- 子组件里通过
var son={ //子组件
template:`
<div>
子组件
<el-button @click='test'>子传父</el-button>
</div>
`,
methods: {
test(){
this.$emit('fu','子传父的数据') //1设置数据
}
},
}
var Father={
template:`
<div>
我是父组件
{{msg}} //5 把数据给显示出来
<son @fu='futest'></son> //2监听子组件设置的方法名
</div>
`,
components:{
son //注册子组件
},
methods: {
futest(val){ 3 定义一个点击事件 val 接收子组件传来的数据
this.msg=val //4 把传来的数据传给msg
}
},
data() {
return {
msg:''
}
},
}
兄弟通信
-
创建一个空实例(bus中央事件总线也可以叫中间组件)
-
利用
$emit $on
的触发和监听事件实现非父子组件的通信Vue.prototype.$bus=new Vue()//在vue上面挂载一个$bus作为中央处理组件 this.$bus.$emit('自定义事件名','传递的数据')//触发自定义事件传递数据 this.$bus.$on('自定义事件名',fn)//监听自定义事件获取数据
-
解决的方案还有vuex、provide/inject是解决同根往下派发**、**本地存储也可以进行非父子组件之间的通信
<script>
Vue.prototype.$bus=new Vue() //1 定义一个new
var MyHandler={
template:`
<div>
头部{{msg}}
</div>
`,
data() {
return {
msg: 'value',
};
},
created(){
//3 在这里接受 兄弟组件传的值 赋值给msg
this.$bus.$on('chuanxin',val=>{
this.msg=val //这里的this 指向的是bus里面的 所以值为空 要用以下两种方法解决
})
// var text=this //把this指向当前
// text.$bus.$on('chuanxin',val=>{
// text.msg=val
// })
//第二种方法用es6的箭头函数 会改变this的指向
// this.$bus.$on('chuanxin',val=>{
// this.msg=val
// })
}
}
var MyFooter={
template:`
<div>
底部 <el-button @click='tx'>兄弟通信</el-button> //定义一个点击事件
</div>
`,
methods:{
tx(){
this.$bus.$emit('chuanxin', '我是底部 你好呀'); // 2 把传的信息 存到新new的vue里
}
}
}
index1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--引入 element-ui 的样式,-->
<link
rel="stylesheet"
href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
/>
<!-- 必须先引入vue, 后使用element-ui -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<!-- 引入element 的组件库-->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<father></father>
</div>
</body>
<script>
//显示隐藏组件
var ShowHidden={
template:`
<div>
<el-button @click="show = !show">Click Me</el-button>
<div style="display: flex; margin-top: 20px; height: 100px;">
<transition name="el-zoom-in-center">
<div v-show="show" class="transition-box">
<el-input v-model="name" placeholder="用户名"></el-input>{{name}}
<el-input v-model="pwd" placeholder="密码"></el-input>{{pwd}}
<el-button @click='sub'>提交</el-button>
</div>
</transition>
</div>
</div>
`,
data(){
return{
show:true,
name:'',
pwd:''
}
},
methods: {
sub(){
this.show=false
}
},
}
var son={ //子组件
template:`
<div>
子组件
</div>
`,
data(){
return{
msg:'hello' //子组件定义的变量
}
},
created(){ //vue的生命周期 钩子
console.log(this.$parent.faterMsg) //获取父组件的变量 通过$parent
}
}
var Father={ //父组件
template:`
<div>
我是父组件
<son ref="sons"></son>
<show-hidden></show-hidden>
<slot/>
</div>
`,
mounted() { //vue的生命周期 钩子
console.log('父组件',this.$refs) //获取子组件的变量 通过$refs
},
components:{ //在父组件里注册子组件
son,
ShowHidden
},
data(){
return{
faterMsg:'我是父组件' //父组件定义的变量
}
}
}
new Vue({
el: "#app",
components:{ //注册组件
Father
},
// template: `
// <div>
// </div>
// `,
data() {
return {
}
},
});
</script>
<style>
#app{
display: flex;
height: 100vh;
/* width: 100%; */
}
.transition-box{
height: 80px;
width: 200px;
/* background-color: #409EFF;
border-radius: 4px; */
border-radius: 4px;
/* background-color: #409EFF; */
color: rgb(0, 0, 0);
padding: 10px 5px;
box-sizing: border-box;
margin-right: 20px;
}
</style>
</html>
Vue生命周期(重要)
-
简介:
- 详述vue所有的生命周期钩子函数的作用
-
需要频繁的创建和销毁组件
- 比如页面中部分内容显示与隐藏,但是用的是v-if
-
组件缓存
- 内置组件中
<keep-alive> 被包裹的对象</keep-alive>
- 被其包裹的组件,在v-if=false的时候,不会销毁,而是停用
- v-if=“true” 不会创建**,**而是激活
- 避免频繁创建组件对象的性能损耗
- 内置组件中
-
组件的激活和停用
activated
和deactivated
使用时 需要把组件包裹在内置组件中 就是第一条keep-aive
-
成对比较
-
created
和beforeCreate
组件创建前和 创建后 -
A 可以操作数据 B 数据没有初始化
mounted
和beforeMount
DOM挂载前后挂载后 -
A 可以操作DOM B 还未生成DOM
updated
和beforeUpdate
-
A 可以获取最终数据 B 可以二次修改
destroyed
和beforeDestroy
-
性能调优:频繁销毁创建的组件使用内置组件包裹
-
<body>
<div id="app">
<keep-alive><my-handler v-if='test'></my-handler></keep-alive>
<el-button @click='kill'>销毁</el-button>
</div>
</body>
<script>
var MyHandler = {
template: `
<div>
测试组件{{msg}}
</div>
`,
data() {
return {
msg: "value",
}
},
// beforeCreate(){
// //组件创建前
// console.log('组件创建前')
// console.log(this.msg)
// },
// created(){
// //组件创建后
// console.log('组件创建后')
// console.log(this.msg)
// },
// beforeMount (){
// console.log('DOM创建前')
// console.log(document.body.innerHTML)
// },
// mounted (){
// console.log('DOM创建后')
// console.log(document.body.innerHTML)
// },
// beforeUpdate(){
// console.log('数据改变前')
// },
// updated(){
// console.log('数据改变后')
// },
beforeDestroy(){ //频繁销毁很浪费性能 建议使用停用和使用
console.log('vue销毁前')
},
destroyed(){
console.log('vue销毁后')
},
deactivated(){
console.log('停用前')
},
activated (){
console.log('停用后')
}
};
new Vue({
el: "#app",
components: {
//注册组件
MyHandler
},
// template: `
// <div>
// </div>
// `,
data() {
return {
test:true
};
},2
methods:{
kill(){
this.test=!this.test
}
}
});
路由
路由的跳转原理(哈希模式)
-
简介:
- 了解vue核心插件的工作原理
-
单页应用的路由模式有两种
- 哈希模式(利用hashchange 事件监听 url的hash 的改变)
- history模式(使用此模式需要后台配合把接口都打到我们打包后的index.html上)
-
哈希模式原理
-
window.addEventListener('hashchange', function(e) { console.log(e) })
-
核心是锚点值的改变,我们监听到锚点值改变了就去局部改变页面数据,不做跳转。跟传统开发模式url改变后立刻发起请求,响应整个页面,渲染整个页面比路由的跳转用户体验更好
-
<body>
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<div id="app"></div>
</body>
<script>
var appId = document.getElementById("app");
//监听路由的跳转
window.addEventListener("hashchange", function (e) {
console.log(location.hash);
switch (location.hash) {
case "#/login":
appId.innerHTML = "登陆页面";
break;
case "#/register":
appId.innerHTML = "注册页面";
break;
}
});
</script>
安装 使用路由
-
路由是以插件的形式引入到我们的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>
-
<body>
<div id="app">
<router-view></router-view> //5 使用组件 留坑
</div>
</body>
<script>
var MyHandler = {
template: `
<div>
测试组件
</div>
`,
};
//1 将vue-router挂载到vue中
Vue.use(VueRouter)
// 2创建路由对象
var router=new VueRouter({
//3 配置路由对象
routes:[
{
path:'/test',
name:'测试',
component:MyHandler
}
]
});
new Vue({
el: "#app",
router, //4 将配置好的路由交给vue 这步很重要
components: {
//注册组件
MyHandler,
},
// template: `
// <div>
// </div>
// `,
});
路由跳转
-
路由的跳转方式有:
- 通过标签:
- 通过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 路由操作对象**,**只写对象
<body>
<div id="app">
<router-link :to="{name:'login',query:{id:'123'}}">登录</router-link>/
<!-- 路由传参 -->
<router-link :to="{name:'register',params:{foo:'bar'}}">注册</router-link>
<el-button @click='jstz'>js跳转</el-button>
<router-view :key="$route.fullPath"></router-view>
</div>
</body>
<script>
var Login = {
template: `
<div>
登录页面
{{msg}}
</div>
`,
data() {
return {
msg: 'value',
};
},
created(){
this.msg=this.$route.query.id
}
};
var Register = {
template: `
<div>
注册页面
{{msg}}
</div>
`,
//取路由参数的两种方法 1 在路由那里设置props:true, 在组件这里声明 props:['foo']
// props:['foo'],
//方法2 定义一个变量 把传来的值赋值给变量 相比 第一种方法更简单一点
data() {
return {
msg: '',
};
},
created(){
this.msg=this.$route.params.foo
}
};
//将vue-router挂载到vue中
Vue.use(VueRouter)
//创建路由对象
var router=new VueRouter({
//配置路由对象
routes:[
{
path:'/login',
name:'login',
component:Login
},
{
path:'/register/:foo',
name:'register',
// props:true,
component:Register
},
]
});
new Vue({
el: "#app",
router,
components: {
//注册组件
},
methods:{
jstz(){
this.$router.push({name:'login',query:{id:'456'}})
}
}
// template: `
// <div>
// </div>
// `,
});
</script>
路由的传参和取参
-
简介:
- 详解路由之间的沟通交流
-
查询参
- 配置(传参)
:to="{name:'login',query:{id:loginid}}"
- 获取(取参)
this.$route.query.id
- 配置(传参)
-
路由参数
- 配置(传参)
:to="{name:'register',params:{id:registerid} }"
- 配置路由的规则
{ name:'detail',path:'/detail/:id'}
- 获取
this.$route.params.id
- 配置(传参)
-
总结:
- :to传参的属性里 params是和name配对的 query和name或path都可以
- 使用路由参数必须要配置路由规则里面配置好参数名,否则刷新页面参数会丢失
<body>
<div id="app">
<router-link :to="{name:'login',query:{id:'123'}}">登录</router-link>/
<!-- 路由传参 -->
<router-link :to="{name:'register',params:{foo:'bar'}}">注册</router-link>
<el-button @click='jstz'>js跳转</el-button>
<router-view :key="$route.fullPath"></router-view>
</div>
</body>
<script>
var Login = {
template: `
<div>
登录页面
{{msg}}
</div>
`,
data() {
return {
msg: 'value',
};
},
created(){
this.msg=this.$route.query.id
}
};
var Register = {
template: `
<div>
注册页面
{{msg}}
</div>
`,
//取路由参数的两种方法 1 在路由那里设置props:true, 在组件这里声明 props:['foo']
// props:['foo'],
//方法2 定义一个变量 把传来的值赋值给变量 相比 第一种方法更简单一点
data() {
return {
msg: '',
};
},
created(){
this.msg=this.$route.params.foo
}
};
//将vue-router挂载到vue中
Vue.use(VueRouter)
//创建路由对象
var router=new VueRouter({
//配置路由对象
routes:[
{
path:'/login',
name:'login',
component:Login
},
{
path:'/register/:foo',
name:'register',
// props:true,
component:Register
},
]
});
new Vue({
el: "#app",
router,
components: {
//注册组件
},
methods:{
//点击事件 实现js路由跳转 但是跳转后 路由地址改变了 参数不会改变 需要在<router-view :key="$route.fullPath"></router-view> 这样参数就会随着路由地址的改变而改变
jstz(){
this.$router.push({name:'login',query:{id:'456'}})
}
}
// template: `
// <div>
// </div>
// `,
});
</script>
嵌套路由
-
简介:了解嵌套路由的使用场景和如何实现
-
代码思想
-
router-view
的细分router-view
第一层中,包含一个router-view
-
每一个坑挖好了,要对应单独的组件
-
路由配置
-
{path:'',redirect:'/nav/login'},//重定向
-
-
-
routes: [ {
path:'/nav',
name:'nav',
component:Nav,
//路由嵌套增加此属性
children:[ //在这里配置嵌套的子路由 ]
}
]
<body>
<div id="app">
<!-- 留一个空位 -->
<router-view></router-view>
</div>
</body>
<script>
var Nav = {
template: `
<div>
<router-view></router-view>
<router-link :to="{name:'login'}">登录</router-link>
<router-link :to="{name:'register'}">注册</router-link>
</div>
`
};
var Login = {
template: `
<div>
登录页
</div>
`,
};
var Register = {
template: `
<div>
注册页
</div>
`,
};
//将vue-router挂载到vue中
Vue.use(VueRouter)
//创建路由对象
var router=new VueRouter({
//配置路由对象
routes:[
{
path:'/nav',
name:'nav',
component:Nav,
children:[
{path:'',redirect:'/nav/login'},//重定向 跳转到登录页 注意注意
{path:'login',name:'login',component:Login},
{path:'register',name:'register',component:Register}
]
},
]
});
new Vue({
el: "#app",
router,
components: {
//注册组件
},
// template: `
// <div>
// </div>
// `,
});
</script>
路由守卫
使用方法
const router = new VueRouter({ ... }
//前置的钩子函数 最后要执行next()才会跳转
router.beforeEach((to, from, next) => {
// ...
})
//后置的钩子函数 已经跳转了不需要
next router.afterEach((to, from) => {
// ...
})
主要是简单介绍一下,路由守卫主要用于检验是否登录了,没登录就跳转到登录页面不让他 在其他页面停留,但是现在这种处理主要的都用请求的全局拦截来做了。大致了解一下路由守卫即可
mounted(){
router.beforeEach((to,from,next)=>{
// console.log('to',to)
if(to.path=='/nav/login'){
next()
}else{
alert('不能进去啊')
}
// console.log('from',from)
})
}
购物车实战
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id='app'>
书名:<input type="text" v-model='name'>
价格:<input type="text" v-model='price'>
<button @click='add'>添加</button>
<table>
<tr v-for='(item,index) in booklist'>
<td>{{index+1}}</td>
<td>书名:{{item.name}}</td>
<td>价格:{{item.price}}</td>
<td><button @click='shop(index)'>添加购物车</button></td>
</tr>
</table>
<cars :orderlist='orderlist'></cars>
</div>
</body>
<script>
var cars = {
props: ['orderlist'],
template: `
<div>
<table border="1">
<tr>
<th>是否选中</th>
<th>书名</th>
<th>数量</th>
<th>价格</th>
</tr>
<tr v-for='(ord,index) in orderlist' align="center" valign="middle">
<td><input type="checkbox" v-model='ord.active' style="cursor: pointer;"></td>
<td>{{ord.name}}</td>
<td>
<span @click='reduce(index)' style="cursor: pointer;">-</span>
{{ord.num}}
<span @click='add(index)' style="cursor: pointer;">+</span>
</td>
<td>{{ord.price*ord.num}}</td>
</tr>
<tr>
<td colspan='2'>课程:{{acticeCount}}/{{count}}</td>
<td colspan='2'>总价:{{totalprice}}</td>
</tr>
</table>
</div>
`,
watch: {
orderlist: {
handler() {
//序列化成json
window.localStorage.setItem('ordertest', JSON.stringify(this.orderlist))
// window.localStorage.setItem("test", this.orderlist)
},
deep: true
}
},
computed: {
//选中课程的数量
acticeCount() {
//过滤出选中的课程
return this.orderlist.filter(v => v.active).length
},
//全部课程的数量
count() {
return this.orderlist.length
},
//总价格
totalprice() {
let total = 0
this.orderlist.forEach(v => {
if (v.active) {
total += v.price * v.num
}
});
return total
}
},
methods: {
//数量减少
reduce(index) {
if (this.orderlist[index].num <= 1) {
if (window.confirm(`是否删除${this.orderlist[index].name}?`)) {
this.orderlist.splice(index, 1)
}
} else {
this.orderlist[index].num--
}
},
//数量增加
add(index) {
this.orderlist[index].num++
}
}
}
new Vue({
el: '#app',
components: {
cars
},
data() {
return {
name: '',
price: '',
orderlist: [],
booklist: [
// { name: "鲁滨逊漂流记", price: 12 },
// { name: "格林童话", price: 20 },
// { name: "花小猪", price: 22 },
// { name: "大灰狼", price: 15 },
// { name: "小山羊", price: 18 }
]
}
},
watch: {
booklist: {
handler() {
//序列化成json
window.localStorage.setItem('booktest', JSON.stringify(this.booklist))
// window.localStorage.setItem("test", this.orderlist)
},
deep: true
}
},
created() {
if(window.localStorage.getItem('booktest')!==null){
//反序列化
this.booklist = JSON.parse(window.localStorage.getItem("booktest"))
}
if(window.localStorage.getItem('ordertest')!==null){
//反序列化
this.orderlist = JSON.parse(window.localStorage.getItem("ordertest"))
}
},
methods: {
//添加商品
add() {
this.booklist.push({ name: this.name, price: this.price })
this.name = '',
this.price = ''
},
//添加购物车
shop(index) {
const goods = this.booklist[index]
const result = this.orderlist.find(v => v.name == goods.name)
if (result) {
result.num += 1
} else {
this.orderlist.push({ active: true, name: goods.name, num: 1, price: goods.price })
}
},
}
})
</script>
</html>