Vue基础知识

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>

1

核心知识

留坑

即留一个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隐藏是增加了一个样式

image-20211126212725716

v-if隐藏是在这里留了个空位

image-20211126212827729

vue指令

v-text不可解析html标签

v-html 可解析html标签

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

v-else-if

v-else

v-show display:nonedisplay: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:'男'
                }

              };
          },
      })

image-20211126214034691

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中的区别

image-20211126223314116

数据监听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>
    • 然后在子组件就可以使用父组件传来的值了
 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” 不会创建**,**而是激活
    • 避免频繁创建组件对象的性能损耗
  • 组件的激活和停用

    • activateddeactivated 使用时 需要把组件包裹在内置组件中 就是第一条 keep-aive
  • 成对比较

    • createdbeforeCreate 组件创建前和 创建后

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

      mountedbeforeMount DOM挂载前后挂载后

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

      updatedbeforeUpdate

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

      destroyedbeforeDestroy

    • 性能调优:频繁销毁创建的组件使用内置组件包裹

<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>
  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论

打赏作者

张一峰615

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值