Vue.js学习笔记

Vue.js学习笔记

1. Vue介绍

1.1 Vue的特点:

  • 遵循mvvm模式
  • 代码简洁 体积小 运行效率高 适合移动或pc开发
  • 它本身只关注UI,可以轻松引入vue插件或其他第三方库开发项目

1.2 Vue的扩展插件

  1. vue-cli:vue 脚手架
  2. vue-resource(axios):ajax 请求
  3. vue-router: 路由
  4. vuex: 状态管理
  5. vue-lazyload: 图片懒加载
  6. vue-scroller: 页面滑动相关
  7. mint-ui: 基于 vue 的 UI 组件库(移动端)
  8. element-ui: 基于 vue 的 UI 组件库(PC 端)\

1.3 Vue的基本使用

  1. 引入Vue.js
  2. 创建Vue对象
    el : 指定根element(选择器)
    data : 初始化数据(页面可以访问)
  3. 双向数据绑定 : v-model
  4. 显示数据 : {{xxx}}
  5. 理解vue的mvvm实现
    在这里插入图片描述在这里插入图片描述
  • MVVM:
    model:模型,数据对象
    view:视图,模板页面
    viewModel:视图模型 vue的实例

v-model本质上是一个语法糖

如下代码<input v-model="test">
本质上是<input :value="test" @input="test = $event.target.value">,
其中@input是对<input>输入事件的一个监听:value="test"是将监听事件中的数据放入到input,
下面代码是v-model的一个简单的例子。
在这边需要强调一点,v-model不仅可以给input赋值还可以获取input中的数据,
而且数据的获取是实时的,因为语法糖中是用@input对输入框进行监听的。
可以在如下div中加入<p>{{ test}}</p>获取input数据,
然后去修改input中数据会发现<p></p>中数据随之改变。

v-model不仅可以给input赋值还可以获取input中的数据,

1.4 强制数据绑定和绑定数据监听

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>01_HelloWorld</title>
    <link rel="stylesheet" href="../layui/css/layui.css">
</head>
<body>

<div id="el1">
    <input id="username" name="username" v-model="username">
    <p>{{username.toUpperCase()}}</p>
    <p>{{sex}}</p>
    <p>{{things}}</p>
    <p v-html="msg"></p><!--相当于是 innerHtml-->
    <p v-text="msg"></p><!--相当于是textContent-->
    <p>{{msg}}</p>
    <!--强制数据绑定-->
    <img :src="imghref"><!--src前面的:  相当于是在强制绑定-->
    <!--绑定事件监听-->
    <br>
    <button type="button" class="layui-btn layui-btn-danger" v-on:click="test">点击一下</button>
    <button type="button" class="layui-btn layui-btn-warm" @click="test1(username)">点击一下</button>
</div>

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

   new Vue({
        el:"#el1",
        data:{
            username:"tjk",
            sex:"男",
            things:"无所事事",
            msg:'<a href="http:/www.baidu.com">I will back</a>',
            imghref:"https://cdn.dragonstatic.com/parking/partner/meiguo.com/images/0.s.jpg"
        },
        methods:{
            test(){
                alert("你把爷点了");
            },
            test1(content){
                alert(content)
            }
        }
    })
</script>
</body>
</html>
  • 强制数据绑定
    在这里插入图片描述
    在这里插入图片描述
  • 绑定事件监听
    在这里插入图片描述
    在这里插入图片描述

1.5 计算属性值的基本使用

在这里插入图片描述
计算属性中的一个方法,方法的返回值作为属性值

1.6 监视

所有vue代码中的this都指的是 vm对象本身
监视是指:所监视的属性中的值发生改变,然后进行回调函数的执行
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>监视</title>
</head>
<body>
<div id="demo">
    <input type="text" placeholder="First Name" v-model="firstName"><br>
    <input type="text" placeholder="last Name" v-model="lastName"><br>
    姓名1:(单向):<input type="text" placeholder="Full Name1"  v-model="FullName1"><br>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
    new Vue({
        el:"#demo",
        data:{
            firstName:"A",
            lastName:"B"
            //FullName1:"AB"
        },
        watch:{
            firstName:function (value) {//对firstName进行监视
                alert(value);   //this 就是vm实例
                this.FullName1=value+""+this.lastName;
            }
        }
    })
    
    //第二种
    vm.$watch('lastName',function (value) {
        this.FullName2=this.firstName+"-"+value;
    });

</script>
</body>
</html>

回调函数:1.你定义的 2.执行了 3.你没有调用

1.7 双向监视

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>getset(双向)</title>
</head>
<body>
<div id="demo">
    <input type="text" placeholder="First Name" v-model="firstName"><br>
    <input type="text" placeholder="last Name" v-model="lastName"><br>
    姓名1:(单向):<input type="text" placeholder="Full Name1"  v-model="FullName1"><br>
    姓名2:(单向):<input type="text" placeholder="Full Name2"  v-model="FullName2"><br>
    姓名3:(双向):<input type="text" placeholder="Full Name3"  v-model="FullName3"><br>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
   var vm=new Vue({
        el:"#demo",
        data:{
            firstName:"A",
            lastName:"B"
            //FullName1:"AB"
        },
       computed:{
           //回调函数:
           //1. 你定义的  2. 你没有调用  3.最终执行了
           //回调函数 (当需要读取当前属性值时回调)  计算并返回当前属性的值
           FullName3:{
               get(){
                   return this.firstName+" "+this.lastName;
               },
               //监视特定属性的属性值,当属性值发生改变时进行回调,更新相关的属性数据
               set(value){
                        const names=value.split(' ');
                       this.firstName=names[0];
                       this.lastName=names[1];
               }
           }
   },
        watch:{
            firstName:function (value) {//对firstName进行监视
                this.FullName1=value+" "+this.lastName;
            }
        }
    });
    //监视的第二种写法
    vm.$watch('lastName',function (value) {
        this.FullName2=this.firstName+" "+value;
    });
</script>
</body>
</html>

计算属性存在缓存,多次读取只执行一次getter计算

1.8 style和 class的强制绑定

  • class动态绑定
  1. :class=”xxx “
  2. xxx是字符串
  3. xxx是对象
  4. xxx是数组
  • style绑定
    1.:style=”{color:red,fontsize:fontsize+‘px’}“
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>class和style的强制绑定</title>
    <link rel="stylesheet" href="../layui/css/layui.css">
    <style type="text/css">
        .aclass{
            color: red;

        }
    </style>
</head>
<body>
<div id="demo">
    <h2>1.class绑定 :class=’xxx‘</h2>
<button type="button" :class="a">显示效果</button><br>
<hr>
    <button type="button" @click="update">点击一下</button>
</div>
<h2>2. style绑定</h2>
<script src="../layui/layui.js"></script>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
   var vm=new Vue({
        el:"#demo",
        data:{
           a:'',//相当于是声明一下
       },
        methods:{
            //此事件是点击事件   所以点击  然后颜色会发生变化
            update(){
              this.a="layui-btn layui-btn-danger"
             }
        }

    });

</script>
</body>
</html>

1.9 条件渲染

  • v-if v-else
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-if v-else</title>
    <link rel="stylesheet" href="../layui/css/layui.css">

</head>
<body>
<div id="dome">
    <p v-if="xxx">床前明月光</p>
    <p v-else>疑是地上霜</p>   <!-- //默认是true-->

    <button class="layui-btn layui-btn-danger" @click='xxx=!xxx'>点击切换</button>

<br>
    <p v-show="xxx">表白呀</p>
    <p v-show="!xxx">还是别了吧</p>
</div>

<script src="../layui/layui.js"></script>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
    el:"#dome",
    data:{
        xxx:true
    }
})
</script>
</body>
</html>

在这里插入图片描述
v-if 和v-show的区别:
v-if是将整个属性进行移除 v-show是将整个控件加载完成后style设置为不显示

1.10 vue的列表渲染

  • v- for 遍历对象
    - v-for 遍历数组
    在这里插入图片描述在这里插入图片描述
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for</title>


</head>
<body>
<div id="dome">
    <h3 >测试:v-for 遍历数组</h3>
    <ul>
        <li v-for="(p,index) in persons" :key="index">
     --------------------------------<br>
    |{{index}}|{{p.name}}|{{p.age}}|<button type="button" @click="deletep(index)">删除该行</button>
            <button @click="updatep(index,{name:'cat' ,age:'25'})">更新该行</button>|
        </li>
    </ul>
    <h3> 测试:v-for 遍历对象</h3>
    <ul>             //属性值  属性名(用处不多)
        <li v-for="(value,key) in persons[1]" :key="key">
            {{value}}:{{key}}
        </li>

    </ul>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
    el:"#dome",
    data:{
        persons:[//vue本身只监视了persos的改变,没有监视数组内部数据的改变
                  //vue重写了数组的一系列改变数组内部数据的方法(先调用原有的方法,然后更新界面)
                  {name:"tjk",age:"13"},
                  {name:"tjk1",age:"131"},
                  {name:"tjk2",age:"132"},
                  {name:"tjk3",age:"133"},
        ]
    },
    methods:{
        deletep(index){
            //删除person中指定index的p
            var i=this.persons.splice(index,1);
            alert(i.persons.name);
            console.log(i);

            //splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。
        },
        updatep(index,newp){
            //this.persons[index]=newp;//数据改变了,但是界面显示不了
            this.persons.splice(index,1,newp);//可以实现增删改操作    当是增加的时候  int=0即可
        }
    }
})



</script>
</body>
</html>

1.11 列表的搜索和排序

  • 搜索:
    在这里插入图片描述
    在这里插入图片描述

  • 排序:
    在这里插入图片描述
    在这里插入图片描述sort (function (a,b){

    });
    在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for</title>
</head>
<body>
<div id="dome">
<input type="text"  v-model="searchName" />
    <ul>
        <li v-for="(p,index) in persons" :key="index">
            {{index}}=={{p.name}}=={{p.age}}
        </li>
    </ul>
    =====================================================================
    <ul>
        <li v-for="(p,index) in filterPersons" :key="index">
            {{index}}=={{p.name}}=={{p.age}}
        </li>
    </ul>
        <button type="button" @click="setOrderType(1)" >按年龄升序</button>
        <button type="button" @click="setOrderType(2)">按年龄降序</button>
        <button type="button"  @click="setOrderType(0)">原有的顺序</button>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
    el: "#dome",
    data: {
        dataType:0,
        searchName: "",
        persons: [//vue本身只监视了persos的改变,没有监视数组内部数据的改变
            //vue重写了数组的一系列改变数组内部数据的方法(先调用原有的方法,然后更新界面)
            {name: "tjk", age: 13},
            {name: "tjk1", age: 131},
            {name: "tjk2", age: 132},
            {name: "tjk3", age: 133},
        ],
    },
    computed: {
        filterPersons() {
            //取出相关的数据
            console.log(this);
           const {searchName,persons,dataType} = this;//解构赋值   相当于是   person=this.person
            //最终需要希纳是的数组
             let  fPersons;
            //对person进行过滤
            //alert(persons[1].name);                                            //将每一个数组的name中查看有无searchNmae的字符  有则赋给fPserson

            fPersons= persons.filter(p=>p.name.indexOf(searchName)!=-1);         //   fPersons= persons.filter(p=>true);  表示不进行过滤
             if(dataType!=0){
                 fPersons.sort(function (p1,p2) {//如果返回负数p1在前,返回正数  p2 在前
                     if(dataType==2){
                         return p2.age-p1.age;
                     }else{
                         return p1.age-p2.age;
                     }
                 })
             }                                                                   // indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
            return fPersons;                                                      //p相当于是persons   =》后面的相当于是匿名函数
                }
    },
    methods: {
        setOrderType(type) {
            this.dataType = type;
        },
    }
})
</script>
</body>
</html>

1.12 事件处理

  • 绑定监听
    在这里插入图片描述
    在这里插入图片描述

该target属性可以是为事件注册的元素或其后代。它往往是比较有用event.target到this,以确定事件是否正在由于事件冒泡处理。当事件冒泡时,此属性在事件委托中非常有用。

  • 事件修饰符

stopPropagation()的用法;
在这里插入图片描述
在这里插入图片描述
@click.stop和event.stopPropagation()的用法是一样的 阻止单击事件继续传播

@click.prevent:
阻止事件的默认行为

  • 按键修饰符
    在这里插入图片描述
    在这里插入图片描述
    每一个event都有一个keycode
    如果按照下面这样写的话,就不用识别keyCode()了会自动识别按钮 “回车键”
    在这里插入图片描述
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件处理</title>
</head>
<body>
<div id="dome">
   <h2> 1.绑定监听</h2>
<button type="button" @click="test1">test1</button>
 <button type="button" @click="test2('tjktjktjk')">test2</button>
    <button type="button" @click="test3">test3</button>
    <button type="button" @click="test4('123',$event)">test4</button>

    <h2> 2. 事件修饰器</h2>
<div style="width:200px;height: 200px;background: #00FF00" @click="test5">
    <div style="width:100px;height: 100px;background: #FFFF00 " @click.stop="test6">
    </div>
</div>
<a href="www.baidu.com" @click="test7">阻止默认事件触发</a>
    <h2> 3.按键修饰器</h2>
    <input type="text" @keyup="test8">
    <input type="text" @keyup.enter="test8">
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
   el:"#dome",
   data:{

    },
    methods: {
        test1() {
            alert("test1");
        },
        test2(msg) {
            alert(msg);
        },
        test3(event) {
            alert(event.target.innerHTML);
        },
        test4(a, b) {
            alert(a + '----' + b.target.innerHTML);

        },
        test5() {
            alert("点击了外面");
        },
        test6() {
            //event.stopPropagation();
            alert("点击了里面");
        },
        test7() {
            alert("这就行了");
        },
        test8(event){
            alert(event.target.value+"event.code:"+event.keyCode);
            }
        

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

完整的key press 过程分为两个部分,按键被按下,然后按键被松开并复位。

当按钮被松开时,发生 keyup 事件。它发生在当前获得焦点的元素上。

keyup() 方法触发 keyup 事件,或规定当发生 keyup 事件时运行的函数

1.13 表单数据的自动收集

主要还是用的 v-mode=““

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自动收集</title>
</head>
<body>
<div id="dome">
  <form action=""  @submit="handSubmit">
      <span> 用户名:</span>
      <input type="text" v-model="username"><br>
      <span> 密码:</span>
      <input type="password" v-model="pwd"><br>
      <span>性别</span>
      <input type="radio" id="female" value="女" v-model="sex" >
      <label  for="female" ></label>
      <input type="radio" id="male" value="男" v-model="sex" >
      <label  for="male" ></label><br>

      <span>爱好;</span>
      <input type="checkbox" id="basket" value="basket" v-model="likes">
      <label  for="basket" >篮球</label>
      <input type="checkbox" id="foot"   value="foot" v-model="likes">
      <label  for="foot" >足球</label>
      <input type="checkbox" id="pingpang"  value="pingpang" v-model="likes" >
      <label  for="pingpang" >乒乓球</label><br>

      <span>城市</span>
      <select v-model="cityId">
          <option >未选择</option>
          <option :value="city.id" v-for="(city,index) in allCitys" :key="index"><!--//添加: 是因为不加的时候相当于是一个字符串-->
          {{city.name}}
          </option>

      </select><br>
      <span>介绍</span>
      <textarea rows="10" v-model="desc"></textarea ><br>
      <input type="submit" value="提交">
  </form>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
     el:"#dome",
    data:{
         username:"",
         pwd:'',
        sex:'男',
        likes:['foot'],
        allCitys:[{id:1,name:'渭南'},{id:2,name:'西安'},{id:3,name:'韩城'}],
        cityId:"3",
        desc:"aaab",
     },
    methods:{
        handSubmit(){
           alert(this.username+"---"+this.pwd+"---"+this.sex+"---"+this.likes+"---"+this.cityId+"---"+this.desc);

        }
    }

})
</script>
</body>
</html>
  • @submit=" "//防止自动提交
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

1.14 vue实例生命周期

实例的生命周期有三个阶段:初始化显示 更新显示 死亡
生命周期的回调函数 也叫做 钩子函数
在这里插入图片描述在这里插入图片描述

  • 启动定时器 —> 关闭定时器
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>生命周期</title>
</head>
<body>
<div id="test">
  <button @click="vmDeatory" >destory Vue</button>
    <p v-show="isShow"> 我骄傲 </p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
    el:"#test",
    data:{
        isShow:true,
    },
    methods:{
        vmDeatory(){//干掉vm
            this.$destroy();
        }
    },
    mounted(){//初始化显示之后立即调用(1次)
        //循环定时器
        this.intervalId=setInterval(()=>{
            this.isShow=!this.isShow;//只要是回调函数就使用箭头函数  箭头函数没有内置对象   不存在自己的this
        },1000);
    },
    //死亡前的回调函数  1次
    beforeDestroy(){
        console.log("--");
        clearInterval(this.intervalId)
    },
})


</script>
</body>
</html>

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>生命周期</title>
</head>
<body>
<div id="test">
  <button @click="vmDeatory" >destory Vue</button>
    <p v-show="isShow"> 我骄傲 </p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
var vm=new Vue({
    el:"#test",
    data:{
        isShow:true,
    },
    methods:{
        vmDeatory(){//干掉vm
            this.$destroy();
        }
    },
    //初始化阶段
    beforeCreate(){
        console.log("beforeCreate");
    },
    created(){
        console.log("created");
    },
    beforeMount(){
       ("beforeMount");
    },
    mounted(){//初始化显示之后立即调用(1次)
        //循环定时器
        this.intervalId=setInterval(()=>{
            this.isShow=!this.isShow;//只要是回调函数就使用箭头函数  箭头函数没有内置对象   不存在自己的this
        },1000);
    },
    //更新阶段
beforeUpdate(){
    console.log("beforeUpdate");
},
    updated(){
        console.log("updated");
    },
    //死亡前的回调函数  1次
    beforeDestroy(){
        console.log("beforeDestroy");
        clearInterval(this.intervalId)
    },
    destroyed(){
        console.log("destroyed");
    }
})


</script>
</body>
</html>

在这里插入图片描述常用的mounted():发送ajax 请求,启动定时器等任务
beforeDestory():做收尾工作:如:清除定时器

1.15 Vue的动画:

(1).操作css的trasition或animation
(2).vue会给目标元素添加/移除特定的class
(3).过度的相关类名

  • xxx-enter-active:指示显示的transition
  • xxx-leave-active:指定隐藏的transition
  • xxx-enter/xxx-leave-to:指定隐藏时的样式

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <style>

     /* 显示、隐藏的过度效guo*/
        .xxx-enter-active, .xxx-leave-active {
            transition: opacity 1s;
        }
      /*  !* 隐藏时的样式*!*/
        .xxx-enter, .xxx-leave-to{
            opacity: 0;
        }
     /* 显示的过度效guo*/
        .yyy-enter-active{
            transition: all 3s;
        }
       /* 隐藏的过渡效果*/
     .yyy-leave-active{
         transition: all 5s;
     }

     /*  !* 隐藏时的样式*!*/
        .yyy-enter,.yyy-leave-to{
            opacity: 0; /*设置元素的不透明级别*/
            transform: translateX(20px);/*向 右移动20px后消失*/
        }


    </style>
</head>
<body>
<div id="test">
  <button @click="isShow=!isShow" >toggle</button>

    <transition name="xxx">
        <p v-show="isShow"> 我骄傲 </p>
    </transition>
</div>

<div id="test2">
    <button @click="isShow=!isShow" >toggle2</button>

    <transition name="yyy">
        <p v-show="isShow"> 我骄傲2 </p>
    </transition>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
new Vue({
    el:"#test",
    data() {
        return {
            isShow:true,

        }
    }
})
new Vue({
    el:"#test2",
    data() {
        return {
            isShow:true,
        }
    }
})
</script>
</body>
</html>

在这里插入图片描述首先将要过渡的元素用transition包裹,并设置过渡的name

  • 设置CSS为opacity:0,说明过渡刚进入和离开的时候透明度为0,即不显示

1.16 过滤器

在这里插入图片描述

  • 过滤器功能: 对要显示的数据进行特定格式化后再显示
  • 注意: 并没有改变原本的数据, 可是产生新的对应的数据
  • 定义和使用过滤器
  1. 定义过滤器 Vue.filter(filterName,function(value[,arg1,arg2,…])
    { // 进行一定的数据处理 returnnewValue })
  2. 使用过滤器
    {{myData|filterName}}
    {{myData|filterName(arg)}}

1.17 Vue的指令

v:text:更新元素的 textContent
v-html:更新元素的 innerHTML
v-if:如果为 true, 当前标签才会输出到页面
v-else:如果为 false, 当前标签才会输出到页面
v-show:通过控制 display 样式来控制显示/隐藏
v-for:遍历数组/对象
v-on:绑定事件监听, 一般简写为@
v-bind:强制绑定解析表达式, 可以省略 v-bind
v-model:双向数据绑定
ref:指定唯一标识,vue 对象通过$els 属性访问这个元素对象
v-cloak:防止闪现, 与 css 配合:[v-cloak]{display:none}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>指令</title>
<style>
    [v-cloak]{
        display: none;
    }
</style>
</head>
<body>
<div id="test">
<p ref="content">什么,你看见我了 </p>
    <button  @click="hint">点一下</button>
    <p>{{msg}}</p>
    <p v-text="msg" v-cloak=""></p>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
new Vue({
    el:"#test",
    data: {
        msg:'tjk',
    },
    methods:{
        hint(){
            alert(this.$refs.content.textContent);
        }
    }
})
</script>
</body>
</html>

在这里插入图片描述纠错 上面的闪光 叫闪屏就是页面没有加载完首先出来{{msg}}
如下:
在这里插入图片描述

  • 自定义指令
    在这里插入图片描述

1.18 插件

  • html文件
    在这里插入图片描述
    在这里插入图片描述

2. Vue组件化编码

在这里插入图片描述

2.1 使用vue-cli创建模板项目

npm install -g vue-cli
vue init webpack vue_demo
cd vue_demo 
npm install
npm run dev 
访问:http://localhost:8080/

github点击下载:
node.js点击下载

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

vue - cli的卸载命令 npm uninstall vue-cli -g

  • npm install -g vue -cli
    在这里插入图片描述如果出现如下错误:可以点win+x 以管理员方式运行 即可避免
    在这里插入图片描述

  • vue
    在这里插入图片描述如果vue显示 不识别该指令 那么就需要配置环境变量
    在计算机全局搜索 vue.cmd
    然后复制路径 粘贴到path中即可

  • 准备创建项目

在这里插入图片描述接下来这一步可能会报错又
如果爆出权限不够,可以点击菜单然后选择cmd 以管理员方式运行即可
npm install 的作用:
在这里插入图片描述
在这里插入图片描述
run dev
在这里插入图片描述在这里插入图片描述

2.2 基于脚手架编写项目

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

在这里插入图片描述

用webstrom 上面创建好的工程
在这里插入图片描述
端口号可以自己修改

打开项目后可以在ws的Terminal平台上进行项目运行 如果输入npm run dev 出现“不是内部或者。。。命令”可以查看一下ws的setting中Node.js是否配置了node 如果配置完成后,重新启动项目还是不行 那么试试以管理员方式运行
在这里插入图片描述

  • components:{App}
    在这里插入图片描述
    开始要创建项目了
  1. mian.js
    入口的js import 是引入实例
/*入口js:: 创建Vue实例*/
import  Vue from 'vue' // 导包
import  App from './App.vue' // 导包
 new Vue({
  el:'#app',
  components:{
    App
  }, // 将组件映射成为指定名称的标签,相当于{App:App}
  template:'<App/>' // 模板插入到el所用
})

  1. App.vue
<!--根组件-->
<template>
  <div>
<img class="logo" src="./assets/2.jpg"/>
<HelloWorld/>
  </div>
</template>
<script>
//1. 引入组件
  import  HelloWorld from './components/HelloWorld.vue'
  export  default  {
    /*2. 映射组件标签*/
    components:{
      HelloWorld
    }
  }

</script>
<style>
  .logo{
    width: 500px;
    height: 800px;
  }

</style>

  1. HelloWorld.vue
<template>
    <div>
         <p class="msg">{{msg}}</p>
    </div>
</template>
<script>
    export default {  //配置对象与Vue一致
         data(){   //data可以写对象也可以写函数,但是在组件中必须写函数
             return{
               msg:"Hello Vue Component"
                    }
                }
    }
</script>
<style>
.msg{
  color:black;
  font-size: 30px;
}
</style>

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>vuedome</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

在这里插入图片描述
template:是使用组件标签
main.js中的el 元素指的是 index.html中的id

  • 项目写完后需要进行运行
    在cmd框中输入 npm run dev 进行运行

2.3 打包发布项目

  1. 打包: npm run build
  2. 发布1:使用静态服务器工具包(安装静态服务器)
    a. npm install -g serve
    在这里插入图片描述
    b. serve dist
    c. 访问:
    在这里插入图片描述- 2. 使用动态web服务器(tomcat)
    修改配置 webpack.prod.conf.js
    在这里插入图片描述
    进行重新的打包编译
    npm run build
    然后将目录结构下的dist 文件复制下来 改名到tomcat的webapp目录下
    在这里插入图片描述
    注意:此名字必须与上面配置文件中修改的一样
    然后进行服务器的运行和工程的访问即可
    http://localhost:8080/vue_demo/

2.4 vue_Eslint编码规范检查

  • 说明:
  1. ESLint是一个代码规范检查工具
  2. 它规定了特定的规则
  3. 基本已经替代了以前的JSlint
  • ESLint 提供以下支持
    1.ES
    2.JSX
    3.style 检查
    4.自定义错误和提示
  • ESLint 提供以下几种校验
  1. 语法错误校验
  2. 不重要或丢失的标点符号,如分号
  3. 没法运行到的代码块(使用过 WebStorm 的童鞋应该了解)
  4. 未被使用的参数提醒
  5. 确保样式的统一规则,如 sass 或者 less
  6. 检查变量的命名
  • 规则的错误等级有三种
  1. 0:关闭规则。
  2. 1:打开规则,并且作为一个警告(信息打印黄色字体)
  3. 2:打开规则,并且作为一个错误(信息打印红色字体)
  • 相关配置文件
  1. .eslintrc.js: 全局规则配置文件 ‘rules’:{ ‘no-new’:1 }
  2. 在 js/vue 文件中修改局部规则 /eslint-disableno-new/ newVue({ el:‘body’, components:{App} })
  3. .eslintignore: 指令检查忽略的文件 *.js *.vue
  • 修改规则
    在这里插入图片描述
  • 组件的含义
    在这里插入图片描述

2.5 组件间的相互通信(1)

Props

2.5.1 练习一
2.5.1.1添加功能
  1. 首先将页面拆分开来
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  2. 编写main.js
/*
创建vue实例
 */
import  Vue from  'vue'
import  App from  './App.vue'
new Vue({
  el:'#app',/*这里需要和index界面的div的id一样*/
  components:{/*相当于是注册组件*/
    App
  },
  template:'<App/>'//使用组件
})

App.vue

<template>
  <div>
    <header class="site-header jumbotron">
      <div class="container">
        <div class="row">
          <div class="col-xs-12">
            <h1>请发表对kunkun的评论</h1>
          </div>
        </div>
      </div>
    </header>
    <div class="container">
      <Add :addComment="addComment"/><!--将此方法传递给子组件-->
      <list :comments="comments"/>
    </div>
  </div>
</template>

<script>
  import Add from './components/Add.vue'
  import  List from './components/List.vue'
    export default {
    data(){
      return {
        comments:[   /*组件间的相互通信最好同名 数据在那个组件,更新数据的行为就在那个组件*/
          {
            name:"张菁",
            content:"偶有还不错哦哦"
          },{
          name:"张十八",
            content:"张菁说得对"
          },{
          name:"宋十五",
            content:"滑行吧"
          }
        ]
      }
    },
      methods:{
      addComment(comment){
        this.comments.unshift(comment);
      }
      },
    components:{
      Add,
      List
    }
    }

</script>

<style>

</style>

add.vue

<template>

    <div class="col-md-4">
      <form class="form-horizontal">
        <div class="form-group">
          <label>用户名</label>
          <input type="text" class="form-control" placeholder="用户名" v-model="name"><!--自动收集数据 <input v-model="data" />-->
        </div>
        <div class="form-group">
          <label>评论内容</label>
          <textarea class="form-control" rows="6" placeholder="评论内容" v-model="content"></textarea>
        </div>
        <div class="form-group">
          <div class="col-sm-offset-2 col-sm-10">
            <button type="button" class="btn btn-default pull-right" @click="add">提交</button>
          </div>
        </div>
      </form>
    </div>
</template>

<script>
    export default {
      props:{
        addComment:{/*要求指定的东西有属性名、属性值的类型和必要性*/
          type:Function,
          required:true,

        }
      },
      data(){
        return{
          name:'',
          content:''
        }
      },
      methods:{
        add (){
          /*检查输入的合法性*/
            const name=this.name.trim();
            const content=this.content.trim();
            if(!name||!content){
              alert("为写入数据");
              return null;
          }
            /*根据输入的数据,封装成comment对象*/
           const  comment={
             name,
             content
           }
          /*添加到comments对象中*/
           this.addComment(comment);
           /*清除输入*/
            this.name='';
            this.content='';
        }
      }
    }
</script>

<style>

</style>

list.vue

<template>
  <div class="container">
  <div class="col-md-8">
    <h3 class="reply">评论回复:</h3>
    <h2 style='display: none'>暂无评论,点击左侧添加评论!!!</h2>
    <ul class="list-group">
      <Item v-for="(comment,index) in comments" :key="index" :comment="comment"/>
    </ul>
  </div>
  </div>
</template>

<script>
  import Item from './Item'
    export default {
      /*声明接受属性 这个属性就会成为组件对象的属性  模板中可以直接使用*/
      props:['comments'],
      components:{
        Item
      }
    }
</script>

<style>
  .reply {
    margin-top: 0px;
  }

</style>

item.vue

<template>
<div>
  <li class="list-group-item">
    <div class="handle">
      <a href="javascript:;">删除</a>
    </div>
    <p class="user"><span >{{comment.name}}</span><span>:</span></p>
    <p class="centence">{{comment.content}}</p>
  </li>
</div>
</template>

<script>
    export default {
      props:{/*指定属性名和属性值类型*/
        comment:Object
      }
    }
</script>

<style>
  li {
    transition: .5s;
    overflow: hidden;
  }

  .handle {
    width: 40px;
    border: 1px solid #ccc;
    background: #fff;
    position: absolute;
    right: 10px;
    top: 1px;
    text-align: center;
  }

  .handle a {
    display: block;
    text-decoration: none;
  }

  .list-group-item .centence {
    padding: 0px 50px;
  }

  .user {
    font-size: 22px;
  }
</style>
  • 注意:

    1. 数据在哪个组件,更新数据的行为就在哪个组件
      比如:父组件的数据要给子组件或者子组件需要获取到父组件的数据,则应该将方法写在父组件中
      在这里插入图片描述
      在这里插入图片描述
    1. 组件间的相互通信组好同名
      将comments数据传递给

在这里插入图片描述

    1. 子组件获取父组件的数据
      a.
      在这里插入图片描述
      b. 在这里插入图片描述
      c. 在这里插入图片描述
    1. 自动收集数据
      在这里插入图片描述
    1. 将父组件中的数据传递给子组件进行遍历
      在这里插入图片描述在这里插入图片描述
2.5.1.2 删除功能
    1. 首先需在App.vue编写删除函数
      在这里插入图片描述
    1. 将函数传递给字组件
      在这里插入图片描述
    1. List组件进行接收函数
      然后将此函数继续向下传递,注意index是数组的下标也需要传递
      在这里插入图片描述
    1. 在item.vue中进行接收并调用
      在这里插入图片描述
2.5.2 练习二

在这里插入图片描述

2.5.2.1 基本功能

App.vue

<template>
  <div class="todo-container">
    <div class="todo-wrap">
      <!---->
<TodoHeader :addTodo="addTodo" />
      <!---->
<TodoList :todos="todos" :delTodo="delTodo"/>
      <!---->
<TodoFooter :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAllTodos="selectAllTodos"/>

    </div>
  </div>
</template>

<script>
  import  TodoHeader from './components/TodoHeader.vue'
  import  TodoFooter from './components/TodoFooter.vue'
  import  TodoList from './components/TodoList.vue'
  export default {
    data(){
      return {
        todos:[
          {tittle:"吃饭",complete:false},
          {tittle:"睡觉",complete:true},
          {tittle:"打豆豆",complete:false}

        ]
      }
    },
    methods:{
      /*添加todo*/
      addTodo(todo){
        this.todos.unshift(todo);
      },
      /*删除选中的todo*/
      delTodo(index){
        this.todos.splice(index,1);
      },
/*
      删除所有选中的todo
*/
      deleteCompleteTodos(){
              this.todos=this.todos.filter(todo=>!todo.complete);

      },
      /*全选或者全部选*/
      selectAllTodos(isCheck){
this.todos.forEach(todo=>todo.complete=isCheck);
      }
    },

    components:{
      TodoHeader,TodoFooter,TodoList
    },


  }

</script>

<style>
  .todo-container {
    width: 600px;
    margin: 0 auto;
  }
  .todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
  }
</style>


TodoList.vue

<template>
  <ul class="todo-main">
    <TodoItem v-for="(todo,index) in todos " :key="index" :todo="todo" :index="index" :delTodo="delTodo"/>
  </ul>
</template>

<script>
  import  TodoItem from './TodoItem.vue'
    export default {
    components:{
      TodoItem
    },
      props:{
        todos:Array,
        delTodo:Function
      }
    }
</script>

<style>
  .todo-main {
    margin-left: 0px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding: 0px;
  }

  .todo-empty {
    height: 40px;
    line-height: 40px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding-left: 5px;
    margin-top: 10px;
  }
  /*item*/
  li {
    list-style: none;
    height: 36px;
    line-height: 36px;
    padding: 0 5px;
    border-bottom: 1px solid #ddd;
  }

  li label {
    float: left;
    cursor: pointer;
  }

  li label li input {
    vertical-align: middle;
    margin-right: 6px;
    position: relative;
    top: -1px;
  }

  li button {
    float: right;
    display: none;
    margin-top: 3px;
  }

  li:before {
    content: initial;
  }

  li:last-child {
    border-bottom: none;
  }

</style>


TodoItem.vue


<template>
    <div>
<!--      进入内部元素 以后onmouseout会执行   出内部元素 onmouseover 会执行
      <li onmouseenter="" onmouseleave="" onmouseover="" onmouseout="">-->
      <li @mouseenter="handleShow(true)"   @mouseleave="handleShow(false)" :style="{background: bgColor}">
        <label>
          <input type="checkbox" v-model="todo.complete"/>
          <span>{{todo.tittle}}</span>
        </label>
        <button class="btn btn-danger" v-show="isShow" @click="deleteItem">删除</button>
      </li>
    </div>
</template>

<script>
    export default {
        props: {
          todo: Object,
          index: Number,
          delTodo:Function
        },
      data(){
          return{
            bgColor:'white',/*默认的背景颜色*/
            isShow:false   /*按钮是否展示*/
          }
      },
      methods:{

        handleShow(bool){
          if(bool){
            this.bgColor="#aaaaaa",
              this.isShow=true
          }else{
            this.bgColor="white",
              this.isShow=false
          }
        },
        deleteItem(){
          const {todo,index,delTodo}=this;
          var result=todo.tittle;
          if(window.confirm('确认删除'+result+'吗?')){
            delTodo(index);
          }
        }
      }
    }
</script>

<style>

</style>

TodoHeader.vue

<template>
  <div class="todo-header">
    <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="tittle" @keyup.enter="addItem"/>
  </div>
</template>

<script>
    export default {
      props:{
        addTodo:{
          type:Function,
          required:true
        }
      },
      data(){
        return {
          tittle:''
        }
      },
      methods:{
        addItem(){
           /* 1.检查输入的合法性*/
         const tittle=this.tittle.trim();
         if(!tittle){
           alert("请您输入信息后在进行提交");
           return null;
         }

          /*2. 根据输入生成一个todo对象*/
               const todo={
                 tittle,
                 complete:false
               }
          /*3.  添加到todos数组中*/
          this.addTodo(todo);
          /*4. 清除输入*/
          this.tittle='';
        }
      }
    }
</script>

<style>
  .todo-header input {
    width: 560px;
    height: 28px;
    font-size: 14px;
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 4px 7px;
  }

  .todo-header input:focus {
    outline: none;
    border-color: rgba(82, 168, 236, 0.8);
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
  }
</style>

TodoFooter.vue

<template>
  <div class="todo-footer">
    <label>
      <input type="checkbox" v-model="isAllCheck"/>
    </label>
    <span>
          <span>已完成{{completeSize}}</span> / 全部{{todos.length}}
        </span>
    <button class="btn btn-danger" v-show="completeSize" @click="deleteCompleteTodos">清除已完成任务</button>
  </div>
</template>

<script>
    export default {
      props: {
        todos: Array,
        deleteCompleteTodos: Function,
        selectAllTodos: Function
      },
      computed:{
        completeSize(){
          return this.todos.reduce((preTotal,todo)=>preTotal+(todo.complete?1:0),0);
        },
        isAllCheck:{
          get(){
            return this.completeSize==this.todos.length && this.completeSize>0;
          },
          set(vlaue){/*vlaue是当前checkbox最新的值*/
            this.selectAllTodos(value);
          }
        }
      }
    }
</script>

<style>
  .todo-footer {
    height: 40px;
    line-height: 40px;
    padding-left: 6px;
    margin-top: 5px;
  }

  .todo-footer label {
    display: inline-block;
    margin-right: 20px;
    cursor: pointer;
  }

  .todo-footer label input {
    position: relative;
    top: -1px;
    vertical-align: middle;
    margin-right: 5px;
  }

  .todo-footer button {
    float: right;
    margin-top: 5px;
  }

</style>

注意:

    1. 注意计算属性的用法
      a.你定义的 b.执行了 c.你没有调用

在这里插入图片描述

在这里插入图片描述

    1. Es6新标准的用法
    1. reduce函数
      reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
      reduce(callback,initiaValue)会传入两个变量,回调函数(callback)和初始值(initiaValue)
    1. === 称为等同符,当两边值的类型相同时,直接比较值,若类型不相同,直接返回false
2.5.2.2 存储数据

将浏览器上输入数据的结果以文件的形式保存在电脑上。

    1. JSON.parse 方法用于将一个 JSON 字符串转换为对象。 JSON.parse( || )如果是空字符串将会执行|| 后面的语句
    1. localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。
    1. 深度监视:一般监听时是不能监听到对象属性值的变化的,数组的值变化可以听到。)
    1. JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串
      在这里插入图片描述产生的效果就是 浏览器上对数据的修改 会进行保存

2.6 组件间的相互通信(2)- 自定义事件

  • 父组件通过使用prop传递数据给子组件
  • 子组件只能通过Vue自定义事件系统将数据传递给父组件
    每个Vue实例都实现了事件接口:
    a. 使用 $ on(eventName)监听事件
    b. 使用 $ emit(eventName,data )触发事件
    在这里插入图片描述

父组件可以在使用子组件的地方直接使用v-on来监听子组件触发的事件
不能用$on监听子组件释放事件,而必须在模板里直接用v-on绑定

2.6.1 @事件名=‘事件名’

父组件:
在这里插入图片描述
子组件
在这里插入图片描述注意: 这种方式只能在父子组件之间传递
此方法用来代替函数属性

2.6.2 利用js代码进行事件的绑定

在这里插入图片描述
js:
在这里插入图片描述
子组件:
在这里插入图片描述

2.7 组件间的相互通信(3)-消息的订阅与发布

  • 1.这个需要下载内库
//下载
npm install --save pubsub-js
//查看版本信息
npm info pubsub-js

注意:

  • 消息的订阅与发布需要引用pubsub.js这个库,哪个vue需要用到消息订阅与发布就需要import
  • 因为消息的订阅与发布是异步的所以需要放在mounted中进行执行
  • 绑定事件监听== 订阅消息
    触发事件==发布消息

订阅消息:
在这里插入图片描述
在这里插入图片描述

   //订阅消息
     PubSub.subscribe('delTodo',(msg,index) =>{   //这个msg相当于是前面的函数名   index相当于是函数的参数
              this.delTodo(index);
     })
  //   用了箭头函数相当取消本函数内的this对象,要找this只能在外面找

发布消息:
在这里插入图片描述
在这里插入图片描述

   //发布消息
            PubSub.publish('delTodo',index);  
//第一个参数是调用的函数名,第二个参数是给函数传递的参数

消息的订阅与发布:好处是组件间传递信息时没有关系限制,父子 祖孙 或者兄弟之间皆可

2.8 组件间的相互通信slot

此方法用于父组件向子组件传递‘标签数据’
1. 此方法只能传递标签,不可以进行数据及参数的传递
2. 此方法中所有标签属性用到的函数方法及参数需要在父组件中

父组件中: 在这里插入图片描述注意:所有子组件中的数据用到的方法都必须 在这里插入图片描述

子组件:
在这里插入图片描述

2.9 数据存储优化

将方法写在外部:
在这里插入图片描述在vue中进行导包:
在这里插入图片描述调用:
在这里插入图片描述
在这里插入图片描述

3. Vue-ajax

3.1 vue项目中的常用的2个ajax库

3.1.1 vue-resource

vue插件 非官方库

3.1.2 axios

通用的ajax请求库,官方推荐

3.2 vue-resource的使用

  • 下载
    npm install vue-resource -save
<template>
  <div>
    <div v-if="!repoUrl">Loading!!!</div>
    <div v-else="repoUrl">most star repo is <a :href="repoUrl">{{repoName}}</a></div>
  </div>
</template>

<script>
export  default {
  data(){
    return{
      repoUrl:'',
      repoName:''
    }
  },
  mounted(){
    //发送ajax请求获取数据  https://api.github.com/search/repositories?q=v&sort=stars
    const url='https://api.github.com/search/repositories?q=v&sort=stars';
  this.$http.get(url).then(
      response=>{
      const  result=response.data;
      //得到最受欢迎的repo
        const  mostRepo=result.items[0];
        this.repoUrl=mostRepo.html_url;
        this.repoName=mostRepo.name;
    }, reponse=>{
            alert("请求失败");
    })
  }
}
</script>
<style>
</style>

3.3 vue-axios的使用

  • 下载
    npm install vue-axios --save
<template>
  <div>
    <div v-if="!repoUrl">Loading!!!</div>
    <div v-else="repoUrl">most star repo is <a :href="repoUrl">{{repoName}}</a></div>
  </div>
</template>

<script>
  import  axios from 'axios'
export  default {
  data(){
    return{
      repoUrl:'',
      repoName:''
    }
  },
  mounted(){
    //发送ajax请求获取数据  https://api.github.com/search/repositories?q=v&sort=stars
    const url='https://api.github.com/search/repositories?q=v&sort=stars';
 
    //使用axios发送ajax请求
    axios.get(url).then( response=>{
      const  result=response.data;
      //得到最受欢迎的repo
      const  mostRepo=result.items[0];
      this.repoUrl=mostRepo.html_url;
      this.repoName=mostRepo.name;
    }).catch(error=>{
      alert("失败了");
    })
  }
}
</script>
<style>
</style>

3.3 vue-anxios实践

  • App.vue
<template>
  <div id="app">
    <div class="container">
     <Search/>
      <UserMain/>
    </div>
  </div>
</template>

<script>
  import Search from './compontents/Search.vue'
  import Main from './compontents/Main.vue'
  export default {

    components:{
      Search,
      UserMain:Main  /*可以起别名*/
    }
  }
</script>
<style>
</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="searchName"/>
     <button @click="search">Search</button>
   </div>
 </section>
</template>

<script>
 import  PubSub from 'pubsub-js'
   export default {
     data(){
       return {
         searchName:''
       }
     },
     methods:{
       search(){
         const  searchName=this.searchName.trim();
         if(searchName){
           //发布搜索的消息
           PubSub.publish('search',searchName);
           alert(searchName);
         }
       }
     }
   }
</script>

<style>

</style>

  • Main.vue
<template>
  <div>
  <h2 v-if="firstView">输入用户名搜索</h2>
  <h2 v-else-if="loading">LOADING...</h2>
  <h2 v-else-if="errorMsg">{{errorMsg}}</h2>
  <div class="row">
    <div class="card" v-for="(user,index) in users" :key="index">
      <a :href="user.url" target="_blank">
        <img :src="user.avatarUrl" style='width: 100px'/>
      </a>
    <p class="card-text">{{user.name}}</p>
    </div>
  </div>
  </div>
</template>
<script>
  import  PubSub from 'pubsub-js'
  import  axios from 'axios'

export default {
    data(){
      return {
           firstView:true,
           loading:false,
           users:null,  /*{url avatar_url name}*/
           errorMsg:''
      }
    },
      mounted(){
      //是否在此发ajax请求   不是,而是在点击search之后
        //订阅搜索的消息
        PubSub.subscribe('search',(msg,searchName)=>{
          //说明需要发ajax请求进行搜索

          //更新状态(请求中的状态)
           this.firstView=false,
             this.loading=true,
             this.users=[],
             this.errorMsg=''
          //发ajax请求
          const  url=`https://api.github.com/search/users?q=${searchName}`
          axios.get(url).then(response=>{
            const  result=response.data;
              const users=result.items.map(item=>({
              url:item.html_url,
              avatarUrl:item.avatar_url,
              name:item.login,
            }));
            //成功,更新成功的状态
            this.users=users;
            this.loading=false;
          }).catch(error=>{
            //失败
            this.loading=false;
            this.errorMsg="请求失败";
          })
        })
      }
    }
</script>
<style>
  .card {
    float: left;
    width: 33.333%;
    padding: .75rem;
    margin-bottom: 2rem;
    border: 1px solid #efefef;
    text-align: center;
  }
  .card > img {
    margin-bottom: .75rem;
    border-radius: 100px;
  }
  .card-text {
    font-size: 85%;
  }

</style>

在这里插入图片描述

4. Vue路由

通过 Vue.js 可以实现多视图的单页Web应用
路由的含义:
一种映射关系 key–value
key:path
value:处理请求的回调函数(后台路由);组件(前台路由)
下载:npm install vue-router --save
在这里插入图片描述

4.1相关Api说明:

  1. VueRouter(): 用于创建路由器的构建函数
    new VueRouter({
    // 多个配置项
    })
  2. 路由配置
    routes: [ {
    // 一般路由
    path: ‘/about’,
    component: About
    },
    {
    // 自动跳转路由
    path: ‘/’,
    redirect: ‘/about’
    } ]
  3. 注册路由器
    import router from ‘./router’
    new Vue({
    router
    })
  4. 使用路由组件标签
 1. <router-link>: 用来生成路由链接
  <router-link to="/xxx">Go to XXX</router-link>
 2. <router-view>: 用来显示当前路由组件界面
  <router-view></router-view>

4.2 基本路由

使用路由的基本步骤:

  1. 定义路由组件
  2. 注册路由
  3. 使用路由
    <router-link>
    <router-view>
  • main.js
import Vue from 'vue'
import App from './App.vue'
import  router from './router'   /*默认暴露可以用任何名字*/

new Vue({//配置对象的属性名都是一些确定的名称,不能随便修改
 el:'#app',
 components:{App},
 template:'<App/>',
 router
})
  • App.vue
<template>
 <div>
   <div class="row">
     <div class="col-xs-offset-2 col-xs-8">
       <div class="page-header"><h2>Router Test</h2></div>
     </div>
   </div>

   <div class="row">
     <div class="col-xs-2 col-xs-offset-2">
       <div class="list-group">
         <!--生成路由链接-->
         <router-link to="/about" class="list-group-item">About</router-link>
         <router-link to="/home" class="list-group-item">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 {
 }
</script>
<style>
</style>

4.3嵌套路由

  • index
/*
* 路由器模块
* */
import Vue from 'vue'
import  VueRouter from 'vue-router'
import About from '../views/About.vue'
import Home from '../views/Home.vue'
import News from '../views/News.vue'
import  Message from '../views/Message.vue'
Vue.use(VueRouter);
export  default new VueRouter({
//n个路由
  routes: [
    {
      path: '/about',
      component: About,
    },
    {
      path: '/home',
      component: Home,
      children:[
        {
          /*path:'/News',//  path最左侧的/永远代表跟路由  直接写/News不对
          */
          path:'/home/News',
          /*path:'News',   简化写法*/
          component:News,

        },
        {
          path:'Message',
          component:Message
        },
        {
          path:'',
          redirect:'News'
        }

      ]
    },
    {
      path:'/',
      redirect:'/about'
    }
  ]
})

path:'/News',// path最左侧的/永远代表跟路由 直接写/News不对
path:'News', 简化写法 代表本级目录下的文件

4.4 缓存路由组件对象

是什么:

  1. 默认情况下, 被切换的路由组件对象会死亡释放, 再次回来时是重新创建的
  2. 如果可以缓存路由组件对象, 可以提高用户体验

编码实现:

<keep-alive>
 <router-view></router-view> 
 </keep-alive>

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

4.4 路由组件传递数据

  • 路由路径携带参数
    (1). 配置路由:
  children:[{
            path:'/home/message/detail/:id',
            component:MessageDetail
          }]

(2). 路由路径:

   <li v-for="(message,index) in messages" :key="message.id" >
            <router-link :to="`/home/message/detail/${message.id}`"> <a >{{message.tittle}}</a></router-link>
 </li>

(3) 路由组件中读取请求参数
this.$route.params.id
index.js

/*
* 路由器模块
* */
import Vue from 'vue'
import  VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import  Message from '../views/Message.vue'
import MessageDetail from '../views/MessageDetail.vue'
Vue.use(VueRouter);
export  default new VueRouter({
//n个路由
  routes: [
    {
      path: '/home',
      component: Home,
      children:[
        {
          path:'/home/News',
          component:News,
        },
        {
          path:'Message',
          component:Message,
          children:[  重点:
            path:'/home/message/detail/:id',
            component:MessageDetail
          }]
        }
      ]
    }
  ]
})

message.vue

<template>
    <div>
       <ul>
         <li v-for="(message,index) in messages" :key="message.id" >
            <router-link :to="`/home/message/detail/${message.id}`"> <a >{{message.tittle}}</a></router-link>  //注意符号``
         </li>
        </ul>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
      data(){
        return{
          messages:[]
        }
      },
      mounted(){
        //模拟ajax请求从后台获取数据
        setTimeout(()=>{
           const messages=[{
             id:1,
             tittle:'message001',
           },
             {
               id:2,
               tittle:'message002',
             },
             {
               id:3,
               tittle:'message003'
             }
           ]
          this.messages=messages;
    },1000);

      }
    }
</script>

<style>

</style>

MessageDetail.vue:

<template>
<div>
  <ul>
    <p>ID:{{$route.params.id}}</p>
    <li>id:{{messageDetail.id}}</li>
    <li>tittle:{{messageDetail.tittle}}</li>
    <li>content:{{messageDetail.content}}</li>
  </ul>
</div>
</template>

<script>
  export  default {
    data(){
      return {
        messageDetail:{},
      }
    },
    mounted(){
      setTimeout(()=>{
        const allMessageDetails=[{
          id:1,
          tittle:'message001',
          content:"massage001Content"
        },
          {
            id:2,
            tittle:'message002',
            content:"massage002Content"
          },
          {
            id:3,
            tittle:'message003',
            content:"massage003Content"
          }];
        this.allMessageDetails=allMessageDetails;
        const id=(this.$route.params.id)*1;       this.messageDetail=allMessageDetails.find(detail=>detail.id===id)   //filter 过滤产生的数据类型是数组类型的
                                                                            //find 查找满足条件的某一个
      },1000)
    },
    watch:{//点击路由连发生改变后,进行修改
      $route:function (value) {//路由路径发生改变
        const id=(value.params.id)*1;
        this.messageDetail=this.allMessageDetails.find(detail=>detail.id===id)
      }
    }
  }
</script>
<style>
</style>
  • 属性携带数据

<router-view msg="abc"></router-view>
接收参数:
在这里插入图片描述

4.5 编程式路由导航

栈的结构进行

  1. 默认情况下, 被切换的路由组件对象会死亡释放, 再次回来时是重新创建的
  2. 如果可以缓存路由组件对象, 可以提高用户体验
    $.router 代表路由器
    $.route 代表当前组件

相关 API :

1) this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面) 
2) this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面) 
3) this.$router.back(): 请求(返回)上一个记录路由 
4) this.$router.go(-1): 请求(返回)上一个记录路由 
5) this.$router.go(1): 请求下一个记录路由
<template>
   <div>
      <ul>
        <li v-for="(message,index) in messages" :key="message.id" >
           <router-link :to="`/home/message/detail/${message.id}`"> <a >{{message.tittle}}</a></router-link>
          <button @click="pushShow(message.id)">push查看</button>
          <button @click="replaceShow(message.id)">replace查看</button>
        </li>
       </ul>
     <button @click="$router.back()">回退</button>
     <hr>
       <router-view></router-view>
   </div>
</template>

<script>
   export default {
     data(){
       return{
         messages:[]
       }
     },
     mounted(){
       //模拟ajax请求从后台获取数据
       setTimeout(()=>{
          const messages=[{
            id:1,
            tittle:'message001',
          },
            {
              id:2,
              tittle:'message002',
            },
            {
              id:3,
              tittle:'message003'
            }
          ]
         this.messages=messages;
   },1000);

     },
     methods:{
       pushShow(id){
         this.$router.push(`/home/message/detail/${id}`)
       },
       replaceShow(id){
         this.$router.replace(`/home/message/detail/${id}`)
       }
     }
   }
</script>

<style>

</style>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值