Java:57-Vue介绍

Vue介绍

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架
与其它大型框架不同的是,Vue 被设计 为可以自底向上逐层应用
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
另一 方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动
自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发(即插即用)
官方网站: https://cn.vuejs.org/v2/guide/ 作者 尤雨溪是中国人
为甚么使用Vue:
声明式渲染:前后端分离是未来趋势
渐进式框架:适用于各种业务需求
简单易学:国人开发,中文文档,不存在语言障碍,易于理解和学习
Vue.js的使用:
//与jquery一样也要引入js文件
//远程CDN
//<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
//本地
//<script src="vue.min.js"></script>
Vue-CLI脚手架:使用vue.js官方提供的CLI脚本架很方便去创建vue.js工程雏形
vsCode插件

在这里插入图片描述

上面括起来的,作用是,当你右键一下

在这里插入图片描述

出现Open with Live Server,打开,虽然也是打开一个浏览器,但是这个浏览器以端口来访问这个资源,一般是5000端口
我们每次保存一下在这个端口的网页文件时,他都会重新请求,相当于保存一下,刷新页面,而其他的插件作用自己去测试,这里就不多说了,一般ctrl+shift+p可以使用插件的一些命令,其实就是调出用于执行命令的输入框,这些命令通常来自VSCode已经使用或者说现在自带(一般不包括禁用的或者卸载的)当前有的插件扩展的命令,自己可以去看一看(禁用代表还在,但不使用,可以解除使用,但他存在,卸载代表不在了,不使用,可以安装后使用)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <!-- 1.引入vue.js -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> -->
    <script src="./js/vue.min.js"></script>
  </head>
  <body>
    <!-- 2.创建 id为 app 的div -->
    <div id="app">
      <!--  就与js一样,实际上Vue也是js,且开始就执行
      会查看自己操作的元素中有那些语法,如下面的{{}},这个可以理解为jsp中的<%的解析
      就会将自己的内容与之匹配从而替换
      如innerHTML = school.name(Vue有的属性,相当于变量)
      先看名称,然后直接这样,因为会找自己内容,且只得到内容
      所以一般写在开始标签里的基本不会解析,因为解析不到或者没有这样的解析
      -->
      {{name}} <br />
      {{school.name}} {{school.mobile}}<br />
      <ul>
        <li>{{names[0]}}</li>
        <li>{{names[1]}}</li>
        <li>{{names[2]}}</li>
      </ul>
    </div>
  </body>

  <script>
      //{{}}: 插值表达式 通常用来获取Vue实例中定义的数据(data)
      //属性节点中 不能够使用插值表达式
      /*
      el的作用 ?
		定义 Vue实例挂载的元素节点,表示vue接管该区域
		Vue的作用范围是什么 ?
		Vue会管理el选项命中的元素,及其内部元素
		el选择挂载点时,是否可以使用其他选择器 ?
		可以,但是建议使用 ID选择器
	*/
      /*
      是否可以设置其他的DOM元素进行关联 ?
	可以但是建议选择DIV, 不能使用HTML和Body标签
      */
      /*
      data: 数据对象 
	Vue中用到的数据定义在data中
	 data中可以写复杂类型
	渲染复杂类型数据的时候,遵守js语法
      */


      
      
      
    //3.创建Vue实例
    var VM = new Vue({ //键值对形式
      el: "#app",  //指定该对象对哪个元素操作,注意:从上往下的找这个元素
      //找到就不找了,即多个相同id或者class只有第一个才会被操作
      data: {   //指定该对象中存放值的位置,也是键值对形式
        name: "你好世界 我不好",
        //对象类型
        school: {
          name: "拉钩教育",
          mobile: "1001001",
        },
        //数组类型
        names: ["尼古拉斯", "赵四", "凯撒"],
      },
    });
    
    //之前学js的时候,我们知道,我们都是对整个页面进行操作,无论是js还是jq都只是对页面的一个操作
    //没有规则化,jq也就是一个好的框架,但是当我们需要改变某一个div或者其他元素时,很难发现对应的js操作
    //于是就出现了vue,他规定只对一个元素进行操作
    //其中创建的Vue对象都是在Window中,而他们都可以叫做Object类
      //前面我们说过单纯的创建方法是以名称来进行的,因为没有赋值,使得名称为这个,所以用这个名称可以调用
      //而当方法对象赋值时
      //赋值变量可以用,但实际上只是赋值,有默认的名称,但调用始终是变量来调用
      //而方法赋值给变量若没名称则用赋值变量名称,否则就是自己定义的名称,实际看name
      //这是js的语法,一切的对象,基本由赋值的变量来调用,其他语言基本也是如此
      //所以js的匿名函数如(function(){}),只所以加括号,是为了让自己变成一个变量,该变量的值就是自己内部的值
      //如a = a,或者说这是js的语法操作,就如java中的匿名内部类的直接使用一样,只是他并不是new开头的,那么js需要使得()使得不是{}后面的,而是认为是整体
      //注意:Vue不能操作HTML和Body标签

  </script>
</html>

声明式渲染的好处:
Vue中的声明式渲染,简单理解就是我们声明数据,Vue帮我们将数据渲染到HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h2>{{name}}</h2>
    </div>
  </body>

  
  <!-- <script src="./js/jquery-1.8.3.min.js"></script>
  <script>
    $(document)选择所有元素的集合
    当 DOM(文档对象模型) 已经加载,就是文档流,并且页面(包括图像)已经完全呈现时,会发生 ready 事件
    $(document).ready(function () {
      $("#app").append("<h2>Hello Word! !</h2>");
    });
  </script> -->

  <script src="js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app", //挂载点
      data: {
        name: "Hello Word! !",
      },
    });

    //可以看出,在某个元素里,Vue比jQ更方便和简洁
    //但jQ可以操作多个元素,而Vue只能对el的元素进行操作,但这个虽然相对于jQ来说是不足,因为功能原因
    //但对项目来说,这样的操作是非常好的,因为好维护,分工明确
  </script>
</html>

Vue常用指令:
根据官网的介绍,指令 是带有 v- 前缀的特殊属性,通过指令来操作DOM元素
v-text 指令:
作用:获取data数据,设置标签的内容
注意:默认写法会替换全部内容,使用插值表达式{{}}可以替换指定内容
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 插值表达式 不会覆盖原来的内容体 -->
      <h2>{{message}}高薪训练营</h2>
      <!-- 单纯的获得内容进行赋值,不符合好的扩展,即扩展性不高,于是,Vue就有解析开始标签中的属性操作
      这个属性观察v-的开始,只解析属性里v-后面的内容属性,没有解析{{}}的操作,他只在内容里解析
在某个开始标签里找到v-,那么通过后面的内容操作,Vue会进行这个标签的渲染,这是Vue的底层操作
    
      -->
      <!-- v-text 获取data数据,设置标签的内容, 会覆盖之前的内容体
      当Vue找到这个属性时,通过对应属性值,实现text操作,即对该元素的内容进行添加值
      类似于innerText = message(Vue有的属性,相当于变量),即标签不会被识别
      message的值使用eval方法来获得,vue大多数语法都是如此
      这就是为什么使用键值对的原因
      因为键值对在js中var a ={"a":1},和var a = {a:1},都可以使用a.a来获得对应的值
      使得只要获得属性值,那么就可以直接获得Vue设置的键值对的值
      因为js里的key是不做很多要求的,最后都会变成字符串
      所以不受其他变量影响

比如:
eval("var a = 'Java程序员'")
    console.log(a) //a会打印
所以可以这样:
    var message ="Java程序员" //相当于vue中的data数据
    eval(`var a = '${message}'+1`)
    console.log(a) //a相当于需要加上的内容

然而eval是危险的,vue底层自然不会使用他,而是非常复杂的逻辑(虚拟dom),相当于重新建立dom,只是这个虚拟的dom每一层都进行与vue交替替换,这非常麻烦,所以了解即可(所以在一定程度上,vue对单纯使用js的效果有一定的延迟,虽然非常少,可以忽略不计(因为js自身也是一个dom,多一个dom和一部分计算,影响不大))

当然了,为了理解,后面我们可以认为是使用eval,虽然本质上是更加复杂的处理

      -->
      <h2 v-text="message">高薪训练营</h2>

      <!-- 上面说了,实际上是对HTML的改变,在js中,父标签设置的Text或者HTML设置值时
        对应的子标签就没了,被替换了
      所以这里若在div上设置v-text(先观察到这个v-属性,类似于Text的操作,实际上差不过就是),那么就先执行
      那么子标签无论怎么设置,都找不到原来的子标签
      而我们手动的去找时,当然会报错的,提示没有这个元素,而Vue只找v-的属性,找到后直接使用
      继续找这个标签内容,这时被改变了,所以就没有v-属性了,这样的操作下来,就不会报错
    
      -->

      <!-- 拼接字符串 -->
      <h2 v-text="message+1"></h2>
      <h2 v-text="message+'abc'"></h2>
      <!-- 
        注意abc必须要用''包括,否则由于Vue没有对应的abc属性,那么会报错
        上面解释过是因为变量得到,那么这里只所以可以这样操作,是因为+的原因,被分割
      分割后左右两边都变成字符串,判断是否为数字,数字直接连接,不是,使用属性,若是分号(引号)连接,则直接连接
      -->
    </div>
  </body>
  <script src="js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        message: "Java程序员", //可以加逗号,因为js的键值对不严谨
      },
    });
  </script>
</html>

上面是设置innerText的值,下面是设置innerHTML的值
v-html 指令:
作用: 设置元素的 innerHTML (可以向元素中写入新的标签)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 
        v-html指令: 设置元素的innerHTML, 向元素中写入标签
       */
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 获取普通文本 -->
      {{message}}
      <h2 v-text="message"></h2>
      <h2 v-html="message"></h2>

      <!-- 设置元素的innerHTML -->
      <h2 v-html="url"></h2>
      <h2 v-text="url"></h2>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        message: "Java程序员",
        url: "<a href='https://www.baidu.com'>百度一下</a>",
      },
    });
  </script>
</html>

v-on 指令:
作用: 为元素绑定事件,比如: v-on:click,可以简写为 @click=“方法”
绑定的方法定义在 VUE实例的,method属性中
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 
        v-on指令: 作用是为元素绑定事件

     */
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 绑定点击事件 vue找到v-后查看到是on属性,这里不像其他的一样只有固定操作
        而是有多种操作,那么就要指定操作什么,如:click(点击时操作)
        那么满足时,就直接调用属性值的方法,这样的我称为指定型操作,其他的我称为固定型操作
		指定型操作一般有简写,因为操作多
        如show(),等,括号是添加的
      -->
      <input type="button" value="点击按钮" v-on:click="show" />

      <!-- 简写方式,这个点击事件,vue也设置了简写模式,因为点击事件非常普遍,于是就将v-on:理解为@-->
      <input type="button" value="点击按钮" @click="show" />

      <!-- 绑定双击事件 dbclick就是双击事件-->
      <input type="button" value="双击按钮" @dblclick="show" />

      <!-- 绑定点击事件,修改内容 -->
      <h2 @click="changeFood">{{food}}</h2>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        food: "麻辣小龙虾",
      },
      //通过methods 专门存放Vue的方法
      //因为键值对中本来就可以存放方法,参考Window,直接写console.log(this)
      methods: {
        show: function () {
          alert("程序员在加班!!");
        },
        changeFood: function () {
          console.log(this.food);
          //使用this获取data中的数据,因为this是调用对象,这里就是Vue对象(实际是Ot对象)
            //当你导入vue.js时并创建对应对象时,该js文件里会创建一个Vue的属性和对应方法(就是Ot)
            //创建这个方法的对象,也就是Ot对象,里面有设置的属性,属性之间有方法来进行绑定操作
           //其中传入的参数里,有些值会变成该对象的一些存在的值,使得data的值是Ot对象的直系,方法也算如此
            //所以在调用时,是Ot对象在调用对应方法,那么this就是Ot对象,而传入的键值对只是进行赋值操作
          //写在data的值,基本都会变成Vue的直系值(其他也类似),也就可以使用this.来获得
          //一般这样的值,在Vue其实是会执行方法后才可看到,因为本来就是执行方法而得到的值
          //而data当然也有
            //相当于创建了新的变量以及属性值(键值对可以传入对应变量名,使得变为属性值(字符串)
          //这样就可以使得写在data的属性,变成了this里的属性,由于从上到下,那么这里就可以直接获得
          //所以data的值,是被其他方法获得的而赋值给新属性的(因为键值对)
          //而到这里,就不得不说一下,html的元素存放,一般的浏览器解析html后,可通过元素来改变数据
          //而js的代码实际上生效后,改变也算无用的,这是一种保护
          //但会影响提交(因为识别元素的值)

          //而Vue的出现可以改变这个东西,因为值与Vue绑定(vue的js设置绑定事件的操作)
          //调用方法,当你进行改变值时
          //对应Vue的语法获得值,都会进行改变,调用方法改变
          //由于html在浏览器进行解析时,浏览器会时刻观察元素的变化,基本是元素的变化
          //而Vue也算类似如此
          //但无论vue是怎么操作的,实际上都是js在操作,就如你在改变某个值时
            //会调用某个方法,如字面意思的get和set
          //这就是vue数据绑定的原因,后续会细讲
          //所以只要记住vue.js也是js,离不开js的操作,只是很复杂而已

          //在vue中 不需要考虑如何更改DOM,重点放在修改数据上,数据更新后 使用数据的那个元素也会同步更新
          this.food += "真好吃";
          //get和set,改变的同时,set执行,js里有类似操作,如Object.defineProperty方法的操作等
        },
      },
    });
    console.log(VM)
  </script>
</html>

计数器案例:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./css/inputNum.css" />
  </head>
  <body>
    <div id="app">
      <!-- 计算功能区域 -->
      <div>
        <input type="button" class="btn btn_plus" v-on:click="add" />
        <span>{{num}}</span>
        <input type="button" class="btn btn_minus" @click="sub"/>
      </div>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        num: 1,
      },
      methods: {
        add:function(){
          if(this.num < 10){
            this.num++;
          }else{
            alert("别点了!最大了!");
          }
        },
        sub:function(){
          if(this.num > 0){
            this.num--;
          }else{
            alert("别点了! 最小了!");
          }
        }
      },
    });
  </script>
  <script>
    /*
      案例总结
        1.创建Vue实例时: el(挂载点), data(数据),methods(方法)
        2.v-on 指令 作用是绑定事件, 可以简写为 @事件名
        3.方法中,使用this关键字 获取data中的数据
        4.v-text 和 {{}} 都可以获取data中的数据,设置到元素中
    */
  </script>
</html>

v-show指令:
作用: v-show指令,根据真假值,切换元素的显示状态
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
      v-show: 根据真假值.切换元素的显示状态
        原理就是修改display 实现显示和隐藏,可以在修改时,查看元素的变化,会出现display样式的对应添加
        值为true 显示,false隐藏
        数据改变后,显示的状态会同步更新
    */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="切换状态" @click="changeShow" />
      <img v-show="isShow" src="./img/car.gif" />
      <img v-show="age > 18" src="./img/car.gif" />
    </div>
    <!-- 先找到v-然后根据show进行对应操作,判断属性值是否为true(运算符也算),js进行字符串运算符的操作
      如eval方法,对字符串的表达式进行操作并返回结果,可以是Number类型或者Boolean类型,进行显示操作
      但也要记住,使用变量时,需要有声明,如var s = "a<9";eval(s),如果a没有声明,那么会报错
      undefined和null在进行运算时,基本会将结果变为false
    从这里可以看出data的值是进行绑定(实际上是get和set的即时操作)
    -->
  </body>

  <script src="js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        isShow: true,
        age: 19,
      },
      methods: { //注意:被挂在的元素若对应vue键值对的键是错的可能不会显示,其他的错误可能会显示,但不起左右
        changeShow: function () {
          //触发方法, 对isShow进行取反
          this.isShow = !this.isShow;
        },
      },
    });
  </script>
</html>

<!-- vue的数据会改变虚拟dom,然后在与真实的进行替换处理(认为一样的,代表对这个部分的完全替换也未尝不可)-->


v-if 指令:
作用: 根据表达值的真假,切换元素的显示和隐藏( 操纵dom 元素 )
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
      v-if指令: 根据表达式的真假,切换元素的显示和隐藏 (操作是dom)
        频繁切换就使用 v-show,反之 v-if,效率问题
        因为v-if本质上是通过操作dom元素来切换状态,可以打开元素查看一下
        是直接将元素删掉,即<img src="img/car.gif" />变成了<!---->
        且这时可以看到,一般我们写属性时,元素会显示出来
        而vue的属性不会,因为在操作完后,会删除对应操作的属性和对应的值
        即<img v-if="isShow" src="img/car.gif" />变成了<img src="img/car.gif" />
        所以上面说明的是<img src="img/car.gif" />
        
    */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="切换状态" @click="changeShow" />
      <img v-if="isShow" src="img/car.gif" />

      <!-- 找到v-实现if的对应操作,值为true就不删除该元素即该元素的dom,否则删除最后变为空注释,即下面的 -->
                                                                                           <!---->
      
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        isShow: false,
      },
      methods: {
        changeShow: function () {
          this.isShow = !this.isShow;
        },
      },
    });
      //可以操作这样的v-if,v-else,v-else-if,他们的值都是对应boolean,其中后面两个
      //前面必须要有v-if被识别,否则被删除,注释都没有出现
      //实际上是vue删除对应注释的(不符合语法才会删掉注释,其他的基本会留下注释)
      //而报错会使得操作的元素被删掉,留下注释(符号语法会留下),上面说的注释是空注释
      //有v-if时,v-else的值是否为boolean不重要,都会执行
  </script>
</html>

v-bind 指令:
作用: 设置元素的属性 (比如:src,title,class)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
      v-bind : 设置元素的属性 src class
      语法: v-bind:属性名=表达式

      作用: 为元素绑定属性
      完整写法: v-bind:属性名 = 表达式 ,简写 :属性=表达式
    */
    </style>
  </head>
  <body>
    <div id="app">
      <img src="img/lagou.jpg" alt="" />

      <!-- 使用 v-bind 设置src属性,找到v-判断bind属性,是指定型属性,指定一个属性(注意:要标签有的)
  否则就是一个自定义属性,不起作用
  由这里看出,指定符号是:
      设置对应属性
      -->
      <img v-bind:src="imgSrc" />

      <!-- v-bind: 可以简写为 : ,指定型属性基本都有简写-->
      <img v-bind:src="imgSrc" :title="imgTitle" />

      <!-- 设置class样式,这是一种操作,平常我们获得的值是字符串值,这里直接是键值对值,这样的值,相当于多次获得 
      就如data的值也是键值对一样,如imgSrc:{ fontSize: size+'px' }
      由于只会认识分号(引号)里的值,使用eval去除了,那么直接使用字符串时,就要这样写
      如"'font-size:60px'"的,其中的值必须是存在的,一切都是因为eval的存在
      -->
      <div :style="{ fontSize: size+'px' }">v-bind指令</div>
         <!--注意:当操作:class时,对应的key-value的value一般是对应的false和true,来代表是否使用该class-->
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        imgSrc: "img/lagou.jpg",
        imgTitle: "拉钩教育",
        size: 50,
      },
    });
  </script>
</html>

v-for 指令:
作用: 根据数据生成列表结构
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
      v-for指令:根据数据生成列表结构
        1.数组经常和v-for结合使用
        2.语法格式: (item,index) in 数据
        3.数组的长度变化,会同步更新到页面上, 响应式的
    */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="添加数据" @click="add" />
      <input type="button" value="移除数据" @click="remove" />

      <ul>
        <!-- 在li标签中 获取数组的元素 
        先找到v-根据for属性进行操作,这里没有使用eval了,因为for属性
判断格式,如()或者单个,进行赋值,()里面第二个参数代表下标,从0开始
判断是in arr,分开使用in后面的使用eval取出对应值,设置对应变量值,用参数当key

每取出一个,对应的标签就多一个(内容也算),即这里有多个标签(如li)
        
        -->
        <li v-for="(item,index) in arr">
          {{index+1}}城市: {{item}}
        </li>
      </ul>

      <!-- 使用h2标签显示
      
      -->
      <h2 v-for="p in persons">
        {{p.name}}
      </h2>
    </div>
  </body>

  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        //数组
        arr: ["上海", "北京", "广东", "深圳"],

        //对象数组
        persons: [
          { name: "尼古拉斯·赵四" },
          { name: "莱昂纳多·小沈阳" },
          { name: "多利安·刘能" },
        ],
      },
      methods: {
        add: function () {
          //向数组添加元素 push
          this.persons.push({ name: "小斌" });
        },
        remove: function () {
          //移除数据,移除第一个数据
          this.persons.shift();
        },
      },
    });
  </script>
</html>

v-on 指令补充:
传递自定义参数:函数调用传参
事件修饰符:对事件触发的方式进行限制
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        1.函数调用传参
          事件绑定方法后,可以传递参数
          定义方法时,需要定义形参,来接收参数
          
        2.事件修饰符
          可以对事件进行限制, .修饰符
          .enter 可以限制触发的方式为 回车
    */
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 函数传参 -->
      <input
        type="button"
        value="礼物刷起来"
        @click="showTime(666,'爱你老铁!')"
      />

      <!-- 事件修饰符 指定哪些方式可以触发事件 
      v-on:指定属性keyup操作,在vue里面可以通过.的查找
      进行对应键位判断,如这里的enter判断你按下的键的值是否与之对应而触发
      -->
      <input type="text" @keyup.enter="hi" />
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {},
      methods: {
        showTime: function (p1, p2) {
          console.log(p1);
          console.log(p2);
        },
        hi: function () {
          alert("你好吗?");
        },
      },
    });
  </script>
</html>

MVVM模式:
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式
MVVM模式将页面,分层了 M 、V、和VM,解释为:
Model:负责数据存储
View:负责页面展示
View Model:负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示

在这里插入图片描述

首先,我们将上图中的DOM Listeners和Data Bindings看作两个工具,它们是实现双向绑定的关键
从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据
从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素
MVVM的思想,主要是为了让我们的开发更加的方便,因为MVVM提供了数据的双向绑定
v-mode 指令:
作用:获取和设置表单元素的值(实现双向数据绑定)
双向数据绑定:
单向绑定:就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新
双向绑定:用户更新了View,Model的数据也自动被更新了
这种情况就是双向绑定(得值,改值,设置值,上面说过的get和set类似的操作,双方都有)
什么情况下用户可以更新View呢:
填写表单就是一个最直接的例子
当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态
那就相当于我们把Model和View做了双向绑定:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 
        v-model: 实现双向数据绑定
        bind:单向数据绑定: 将model绑定到view上,当model发生变化时,view会随之变化
        改变model值,得到,然后设置,改变view不会进行操作,没有监听
        双向数据绑定: view视图发生变化时,model也会随之改变
        改变model值,得到,然后设置,也可以改变view的值,得到,然后设置,有监听
        即bind是单向
        model是双向
       */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="修改message" @click="update" />

      <!-- View 视图 -->
      <!-- <input type="text" v-bind:value="message" /> -->

      <!-- v-model 实现双向数据绑定,找到v-识别model,可以加上:,:后面的再怎么写,都会是认为value的值
      其他的属性加上可能会使得属性不起作用
      -->
      <input type="text" v-model="message" />
      <input type="text" v-model="password" />
      <h2>{{message}}</h2>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //VM 业务逻辑控制
    var VM = new Vue({
      el: "#app",
      //Model 数据存储
      data: {  //注意:其实Vue里的键值对是可以不写的,但el还是要,即他们互不干扰,如data不写,方法照样执行
        message: "拉钩教育训练营",
        password: 123,
      },
      methods: {
        update: function () {
          this.message = "拉钩";
        },
      },
    });

    //从这里可以看出vue的好处,对某个元素操作的方便之处,并且可以动态的操作值,非常高效
  </script>
</html>

v-model指令总结:
v-model 指令的作用是便捷的设置和获取表单元素的值
绑定的数据会和表单元素值相关联
双向数据绑定
实现简单记事本 :
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>小黑记事本</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex, nofollow" />
    <meta name="googlebot" content="noindex, nofollow" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" type="text/css" href="../css/index.css" />
  </head>

  <body>
    <!-- VUE示例接管区域 -->
    <section id="app">
      <!-- 输入框 -->
      <header class="header">
        <h1>VUE记事本</h1>
        <input
          autofocus="autofocus"
          autocomplete="off"
          placeholder="输入日程"
          class="new-todo"
          v-model="inputValue"
          @keyup.enter="add"
        />
      </header>

      <!-- 列表区域 -->
      <section class="main">
        <ul class="listview">
          <!-- 1.使用v-for指令 生成列表结构 -->
          <li class="todo" v-for="(item,index) in list">
            <div class="view">
              <span class="index">{{index+1}}</span> <label>{{item}}</label>
              <!-- 2.删除操作 传递index -->
              <button class="destroy" @click="remove(index)"></button>
            </div>
          </li>
        </ul>
      </section>
      <!-- 统计和清空 -->
      <footer class="footer">
        <span class="todo-count">
          <strong>{{list.length}}</strong> items left
        </span>
        <button class="clear-completed" @click="clear()">
          Clear
        </button>
      </footer>
    </section>
  </body>
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        list: ["写代码", "吃饭", "睡觉", "打豆豆"],
        inputValue: "996还是997",
      },
      methods: {
        //新增日程方法
        add: function () {
          //将用户输入的内容添加到list
          this.list.push(this.inputValue);
        },
        remove: function (index) {
          console.log(index);
          //使用 splice(元素的索引,删除几个)
          this.list.splice(index, 1);
        },
        //清空操作
        clear: function () {
          this.list = [];
        },
      },
    });
  </script>
</html>

/*index.css的样式*/
html,
body {
  margin: 0;
  padding: 0;
}
body {
  background: #fff ;
}
button {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 100%;
  vertical-align: baseline;
  font-family: inherit;
  font-weight: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
  line-height: 1.4em;
  background: #f1b7b7;
  color: #4d4d4d;
  min-width: 230px;
  max-width: 550px;
  margin: 0 auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 300;
}

:focus {
  outline: 0;
}

.hidden {
  display: none;
}

#app {
  background: #fff;
  margin: 180px 0 40px 0;
  position: relative;
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}

#app input::-webkit-input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#app input::-moz-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#app input::input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: gray;
}

#app h1 {
  position: absolute;
  top: -160px;
  width: 100%;
  font-size: 60px;
  font-weight: 100;
  text-align: center;
  color: rgba(175, 47, 47, .8);
  -webkit-text-rendering: optimizeLegibility;
  -moz-text-rendering: optimizeLegibility;
  text-rendering: optimizeLegibility;
}

.new-todo,
.edit {
  position: relative;
  margin: 0;
  width: 100%;
  font-size: 24px;
  font-family: inherit;
  font-weight: inherit;
  line-height: 1.4em;
  border: 0;
  color: inherit;
  padding: 6px;
  border: 1px solid #999;
  box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.new-todo {
  padding: 16px;
  border: none;
  background: rgba(0, 0, 0, 0.003);
  box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}

.main {
  position: relative;
  z-index: 2;
  border-top: 1px solid #e6e6e6;
}

.toggle-all {
  width: 1px;
  height: 1px;
  border: none; /* Mobile Safari */
  opacity: 0;
  position: absolute;
  right: 100%;
  bottom: 100%;
}

.toggle-all + label {
  width: 60px;
  height: 34px;
  font-size: 0;
  position: absolute;
  top: -52px;
  left: -13px;
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg);
}

.toggle-all + label:before {
  content: "❯";
  font-size: 22px;
  color: #e6e6e6;
  padding: 10px 27px 10px 27px;
}

.toggle-all:checked + label:before {
  color: #737373;
}

.listview {
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 420px;
  overflow: auto;
}

.listview li {
  position: relative;
  font-size: 24px;
  border-bottom: 1px solid #ededed;
  height: 60px;
  box-sizing: border-box;
}

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

.listview .view .index {
  position: absolute;
  color: gray;
  left: 10px;
  top: 20px;
  font-size: 16px;
}

.listview li .toggle {
  text-align: center;
  width: 40px;
  /* auto, since non-WebKit browsers doesn't support input styling */
  height: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto 0;
  border: none; /* Mobile Safari */
  -webkit-appearance: none;
  appearance: none;
}

.listview li .toggle {
  opacity: 0;
}

.listview li .toggle + label {
  /*
		Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
		IE and Edge requires *everything* to be escaped to render, so we do that instead of just 
    the `#`
    - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
	*/
  background-image: 
      
      
      url("data:image/svg+xml;utf8,
          %3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22
          %20height%3D%2240%22%20viewBox%3D%22-10%20-
          
          18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%
          3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20
          stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center left;
}

.listview li .toggle:checked + label {
  background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/
      svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-
      18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%
      3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%
      20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%
      235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E");
}

.listview li label {
  word-break: break-all;
  padding: 15px 15px 15px 60px;
  display: block;
  line-height: 1.2;
  transition: color 0.4s;
}

.listview li.completed label {
  color: #d9d9d9;
  text-decoration: line-through;
}

.listview li .destroy {
  display: none;
  position: absolute;
  top: 0;
  right: 10px;
  bottom: 0;
  width: 40px;
  height: 40px;
  margin: auto 0;
  font-size: 30px;
  color: #cc9a9a;
  margin-bottom: 11px;
  transition: color 0.2s ease-out;
}

.listview li .destroy:hover {
  color: #af5b5e;
}

.listview li .destroy:after {
  content: "×";
}

.listview li:hover .destroy {
  display: block;
}

.listview li .edit {
  display: none;
}

.listview li.editing:last-child {
  margin-bottom: -1px;
}

.footer {
  color: #777;
  padding: 10px 15px;
  height: 20px;
  text-align: center;
  border-top: 1px solid #e6e6e6;
}

.footer:before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 50px;
  overflow: hidden;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6,
    0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6,
    0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

.todo-count {
  float: left;
  text-align: left;
}

.todo-count strong {
  font-weight: 300;
}

.filters {
  margin: 0;
  padding: 0;
  list-style: none;
  position: absolute;
  right: 0;
  left: 0;
}

.filters li {
  display: inline;
}

.filters li a {
  color: inherit;
  margin: 3px;
  padding: 3px 7px;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 3px;
}

.filters li a:hover {
  border-color: rgba(175, 47, 47, 0.1);
}

.filters li a.selected {
  border-color: rgba(175, 47, 47, 0.2);
}

.clear-completed,
html .clear-completed:active {
  float: right;
  position: relative;
  line-height: 20px;
  text-decoration: none;
  cursor: pointer;
}

.clear-completed:hover {
  text-decoration: underline;
}

.info {
  margin: 50px auto 0;
  color: #bfbfbf;
  font-size: 15px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  text-align: center;
}

.info p {
  line-height: 1;
}

.info a {
  color: inherit;
  text-decoration: none;
  font-weight: 400;
}

.info a:hover {
  text-decoration: underline;
}

/*
	Hack to remove background from Mobile Safari.
	Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio: 0) {
  .toggle-all,
  .listview li .toggle {
    background: none;
  }

  .listview li .toggle {
    height: 40px;
  }
}

@media (max-width: 430px) {
  .footer {
    height: 50px;
  }

  .filters {
    bottom: 10px;
  }
}

/*inputNum.css的样式*/
.inputNum {
  vertical-align: middle;
  height: 22px;
  border: 1px solid #d0d0d0;
  text-align: center;
}

.btn {
  display: inline-block;
  vertical-align: middle;
  background: #f0f0f0 no-repeat center;
  border: 1px solid #d0d0d0;
  width: 50px;
  height: 50px;
  border-radius: 2px;
  box-shadow: 0 1px rgba(100, 100, 100, 0.1);
  color: #666;
  transition: color 0.2s, background-color 0.2s;
}

.btn:active {
  box-shadow: inset 0 1px rgba(100, 100, 100, 0.1);
}

.btn:hover {
  background-color: #e9e9e9;
  color: #333;
}

.btn_plus {
  background-image: linear-gradient(to top, currentColor, currentColor),
    linear-gradient(to top, currentColor, currentColor);
  background-size: 20px 2px, 2px 20px;
}

.btn_minus {
  background-image: linear-gradient(to top, currentColor, currentColor);
  background-size: 20px 2px, 2px 20px;
}

实际上并非要完全按照上面的说明双向绑定,其实你可以认为vue是利用的js的某些功能在原来的从js中获取的信息是否改变原来给他的信息,就如b =c ,d=b,其中d是浏览器的显示,c是数据的渲染,但是d=b的这个b并不是指向c的,所以d和b都是一个数,其中d和b给的数或者说备份的变量是双向的,那么双向绑定就是说明b和d是否绑定的意思,具体如何实现,二进制肯定帮我们完成了,我们了解即可
在设置同步和异步时,false不能加上分号(引号),因为加上分号(引号)认为是true
所以直接写false,但是ajax本来就是用来异步的,所以false现在虽然可以用,但被弃用了,所以可能以后会没有这个操作方式了
axios介绍:
VUE中结合网络数据进行应用的开发
目前十分流行网络请求库,专门用来发送请求,其内部还是ajax,进行封装之后使用更加方便
axios作用:在浏览器中可以帮助我们完成 ajax异步请求的发送
Vue2.0之后,尤雨溪推荐大家用axios替换JQuery ajax
axios入门:
使用步骤:
导包:
<!-- 官网提供的 axios 在线地址 -->
 <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
请求方式,以GET和POST举例
GET:
//axios.get(地址?key=value&key2=value2).then(function(response){},function(error){});

在这里插入图片描述

POST:
//axios.post(地址,{key:value,key2:value2}).then(function(response){},function(error){})
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        axios总结
          1.axios必须要导包
          2.使用get或者post方式发送请求
          3.then方法 中的回调函数,会在请求成功或者失败的时候被触发
          4.通过回调函数的形参,可以获取响应的内容
      */

    </style>
  </head>
  <body>
    <input type="button" value="get请求" id="get" />
    <input type="button" value="post请求" id="post" />
  </body>
  <script src="./js/axios.min.js"></script>
    <!-- 可以导入远程的
如<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
-->
  <script>
    /*
    随机笑话接口测试
      请求地址:https://autumnfish.cn/api/joke/list
      请求方法:get
      请求参数:num(笑话条数,数字)
      响应内容:随机笑话
  */
    document.getElementById("get").onclick = function () {
      axios.get("https://autumnfish.cn/api/joke/list?num=1").then(
        function (resp) {
          //调用成功
          console.log(resp);
        },
        function (err) {
          //调用失败
          console.log(err);
        }
      );
    };

    /*
    用户注册
      请求地址:https://autumnfish.cn/api/user/reg
      请求方法:post
      请求参数:username:"用户民"
      响应内容:注册成功或失败
    */
    document.getElementById("post").onclick = function () {
      axios
        .post("https://autumnfish.cn/api/user/reg", { username: "张abc" })
        .then(
          function (resp) {
            console.log(resp);
          },
          function (error) {
            console.log(error);
          }
        );
    };
  </script>
</html>

通过vue+axios 完成一个获取笑话的案例:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vue+axios获取笑话</title>
    <style>
      /*
        1.axios回调函数中,this的指向已经改变,无法访问data中的数据
        2.解决方案: 将this进行保存
      */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="点击获取一个笑话" @click="getJoke" />
      <p>{{joke}}</p>
    </div>
  </body>

  <script src="../js/vue.min.js"></script>
  <script src="../js/axios.min.js"></script>
  <script>
    /*
        请求地址:https://autumnfish.cn/api/joke
        请求方法:get
        请求参数:无
        响应内容:随机笑话
    */
    var VM = new Vue({
      el: "#app",
      data: {
        joke: "笑口常开",
      },
      methods: {
        getJoke: function () {
          //把this进行保存
          var that = this; //使得that是方法里的全局变量

          //异步访问
          axios.get("https://autumnfish.cn/api/joke").then(
            function (resp) {
              console.log(resp.data);
              //在回调函数内部 ,this无法正常使用,需要提前保存起来
              console.log(that.joke); //undefined 因为this是调用者
              that.joke = resp.data;
            },
            function (error) {}
          );
        },
      },
    });
  </script>
</html>

现在说明Vue的作用:可以将数据进行对元素的基本随意改动,方法的基本随意调用,语法简洁,数据集中,数据绑定,重在单体
天气查询案例 :
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>天气查询</title>
    <link rel="stylesheet" href="css/reset.css" />
    <link rel="stylesheet" href="css/index.css" />

    <style>
      /*
        1.应用的逻辑代码 建议与页面进行分离,使用单独的JS编写
        2.axios中 回调函数中的this 需要先保存 再使用
        3.服务器返回的数据比较复杂,获取数据的时候 要注意层级结构
      */
      [v-cloak]{ 
        display: none;
      }
        /*
        使用属性选择器将对应隐藏
        最后vue执行时,找到v-cloak,使得显示,即避免了闪烁
        */
    </style>
  </head>

  <body>
    <div class="wrap" id="app" v-cloak>
      <div class="search_form">
        <div class="logo">天气查询</div>
        <div class="form_group">
          <input
            type="text"
            class="input_txt"
            placeholder="请输入要查询的城市"
            v-model="city"
            @keyup.enter="searchWeather"
          />
          <button class="input_sub">回车查询</button>
        </div>
      </div>
      <ul class="weather_list">
        <!-- 展示数据 -->
        <li v-for="item in weatherList">
          <div class="info_type">
            <span class="iconfont">{{item.type}}</span>
          </div>
          <div class="info_temp">
            <b>{{item.low}}</b>
            ~
            <b>{{item.high}}</b>
          </div>
          <div class="info_date"><span>{{item.date}}</span></div>
        </li>
      </ul>
    </div>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 官网提供的 axios 在线地址 -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <!-- 自己的js -->
    <script src="./js/main.js"></script>
  </body>
</html>

/**
 * 
 *  请求地址:http://wthrcdn.etouch.cn/weather_mini
    请求方法:get
    请求参数:city (要查询的城市名称)
    响应内容:天气信息
 */

var VM = new Vue({
  el: "#app",
  data: {
    city: "",
    //定义数组保存 天气信息
    weatherList: [],
  },
  //编写查询天气的方法
  methods: {
    searchWeather: function () {
      console.log("天气查询");
      console.log(this.city);

      var that = this;

      //调用接口
      axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + this.city).then(
        function (resp) {
          console.log(resp.data.data.forecast);
          //获取天气信息 保存到weatherList
          that.weatherList = resp.data.data.forecast;
        },
        function (error) {}
      );
    },
  },
});

解决页面闪烁问题 :
我们发现访问天气预报案例页面时,使用插值表达式的地方出现了闪烁问题
是因为vue.js太多加载缓慢,使得原来的语法如{{}}还没有进行找到,即识别替换,造成刷新时{{}}会出现一下
我们可以使用下面的指令来防止这种情况(其实也可以将vue.js放在前面)
v-cloak指令:
作用: 解决插值表达式闪烁问题
当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码
我们可以使用 v-cloak 指令来解决这一问题
<style>
    /* 通过属性选择器,设置 添加了v-cloak */
   [v-cloak] {
        display: none;
   }
</style>
<div class="wrap" id="app" v-cloak> <!--基本上vue.js加载完后,才会去找v-cloak属性,即最后处理才替换(真正的dom是动态的,在body,你改变自然会发生改变)-->



computed 计算属性:
什么是计算属性:
在Vue应用中,在模板中双向绑定一些数据或者表达式,但是表达式如果过长,或者逻辑更为复杂时
就会变得臃肿甚至难以维护和阅读,比如下面的代码:
<div>
    <!--
 写在双括号中的表达式太长了,不利于阅读
 {{text.split(',').reverse().join(',')}}
    -->
</div>.
<!--
将这段操作text.split(',').reverse().join(',')  放到计算属性中,最终返回一个结果值就可以
-->
computed 的作用:减少运算次数,缓存运算结果,运用于重复相同的计算
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=<device-width>, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        1.计算属性可以 减少运算次数,用于重复相同的计算
        2.定义函数也可以实现与计算属性相同的效果,但是计算属性可以简化运算
      */
    </style>
  </head>
  <body>
    <div id="app">
      <!-- <h1>{{a*b}}</h1>
      <h1>{{a*b}}</h1> -->
      <!-- 
      <h1>{{res()}}</h1>
      <h1>{{res()}}</h1> -->

      <h1>{{res2}}</h1>
      <h1>{{res2}}</h1>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        a: 10,
        b: 20,
      },
      methods: {
        res: function () {
          console.log("res方法执行了! !");
          return this.a + this.b;
        },
      },
      //使用计算属性 进行优化,减少运算次数,用于重复的运算
      computed: {
        res2: function () {
          console.log("res2方法执行了! !");
          return this.a + this.b;
        },
      },
    });

    //注意computed的方法不要与methods的方法一样,因为会被methods的方法覆盖,使得computed的方法不起作用
    //并打印出对应信息(源代码),实际上computed不是执行然后调用方法
    //而是先调用方法,重新赋值给自己,然后其他的可以直接获得这个数了,所以在控制台中,只有一次调用方法的显示
    //但也导致不能使用对应名称(),来调用方法了,如果调用,会报错,并说明这不是一个方法(因为赋值了)
    //之后只要对应data的值改变,那么就会重新赋值,即调用方法
    //对应的get和set(set里面调用了该方法,然后设置页面数据),{{}}解析后,剩下的就是设置了
  </script>
</html>

computed总结:
定义函数也可以实现与计算属性相同的效果,都可以简化运算
不同的是计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值
filter 过滤器:
什么是过滤器:
过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示,值得注意的是过滤器并没有改变原来的数据
只是在原数据的基础上产生新的数据
数据加工车间,对值进行筛选加工
过滤器使用位置:
双括号插值内:
<!--
{{ msg | filterA }} 
msg是需要处理的数据, filterA是过滤器, | 这个竖线是管道,通过这个管道
将数据传输给过滤器进行过滤 加工操作
-->
v-bind绑定的值的地方:
<!--
<h1 v-bind:id=" msg | filterA"> {{ msg }} </h1>
-->
过滤器:
局部过滤器:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 使用插值表达式,调用过滤器 -->
      <p>电脑价格: {{price | addIcon}}</p>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //局部过滤器 在vue实例的内部创建filter
    var VM = new Vue({
      el: "#app", //挂载点
      data: {
        //model
        price: 200,
      },
      methods: {
        //方法
      },
      computed: {
        //计算属性
      },

      //局部过滤器
      filters: {
        //定义处理函数 value = price
        //在键值对里可以将key:value合一起(方法基本这样),相当于addIcon:function(){...},这是键值对独有的
          //直接写的不可以,因为没有这方面的解析
        addIcon(value) { //这个参数是进行过滤的参数,也就是上面的price,可以将price | addIcon看成执行方法
          //即返回的结果就是上面的结果
          return "$" + value;
        },
      },
    });
  </script>
</html>

全局过滤器:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        需求: 将用户名开头字母大写
        总结:
          1.过滤器经常被用来处理文本格式化操作
          2.过滤器使用的两个位置: {{}} 插值表达式中, v-bind表达式中
          3.过滤器是通过管道传输数据的 |
      */
    </style>
  </head>
  <body>
    <div id="app">
      <p>{{user.name | changeName}}</p>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>

    //在创建vue实例之前,创建全局过滤器
    //可以给然后Vue的挂载使用,但要注意:由于创建的实例是按照vue的值来进行获得
      //所以要将这个全局过滤器放在前面
    //只所以这样,是如果放在后面,那么先创建的实例,是创建没有添加该全局过滤器的实例,所以用不到
    //即可以看出,创建全局过滤器,实际上就是改变Vue方法的本来存有的过滤器,使得其他创建的实例可以得到
    //形成了全局过滤器
    Vue.filter("changeName", function (value) {
      //将姓名的开头字母大写
      return value.charAt(0).toUpperCase() + value.slice(1);
    });
      //上面调用后,并没有改变new原来的指向,即constructor,所以可以这样操作,具体可以百度
    var VM = new Vue({
      el: "#app",
      data: {
        user: { name: "jack" },
      },
    });

   
  </script>
</html>

总结:
过滤器常用来处理文本格式化的操作
过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
过滤器应该被添加在 JavaScript 表达式的头部(如全局),局部一般是尾部,由"管道"符号指示
全局是给所有el所对应的,而局部只有一个el所对应的
watch 侦听器:
什么是侦听器 :
Vue.js 提供了一个方法 watch,它用于观察Vue实例上的数据变动
作用:当你有一些数据需要随着其它数据变动而变动时,可以使用侦听属性
案例演示:

在这里插入图片描述

先看计数器:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h2>计数器:{{count}}</h2>
      <input type="button" @click="count++" value="点我+1" />
      <!-- 
        从这里更加的可以看出,分号(引号)里的就是key(即可以是data的,也可以是方法的,只要是key都可以)
        这里进行改变后,值改变调用设置值方法(set)
      -->
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        count: 1,
      },
      watch: {
        //监测属性的值的变化
        count: function (nval, oval) { //key的值要与监听的值一致,否则监听不到,因为执行不了这个方法
          //参数2:原来的值 参数1:新的值,注意:是参数2是原来的值,第一个是改变的值
            //可以说先新后旧
          alert("计数器发生变化: " + oval + " 变化为 " + nval);
        },
      },
    });

    //从这里可以看出,监听器和set方法类似,都是需要对应值改变
      
  </script>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <label>名:<input type="text" v-model="fristName" /></label>
      <label>姓:<input type="text" v-model="lastName" /></label>
      {{fullNameComputed}}
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        fristName: "",
        lastName: "",
        fullName: "",
      },
      //侦听器
      watch: {
        fristName: function (nval, oval) {
          //参数 1.新值,2.旧值
          this.fullName = nval + " " + this.lastName;
        },
        lastName: function (nval, oval) {
          this.fullName = this.fristName + " " + nval;
        },
      },
    });
  </script>
</html>

Component 组件 :
组件介绍:
组件(Component)是自定义封装的功能
在前端开发过程中,经常出现多个网页的功能是重复的
而且很多不同的页面之间,也存在同样的功能
我们将相同的功能进行抽取,封装为组件,这样,前端人员就可以在组件化开发时,只需要书写一次代码,随处引入即可使用
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树

在这里插入图片描述

vue的组件有两种:全局组件和局部组件
全局组件:
语法格式:
<!--
Vue.component("组件名称", {
    template: "html代码",  // 组件的HTML结构代码
    data(){ //组件数据
        return {}
   },
    methods: {  // 组件的相关的js方法
        方法名(){
            // 逻辑代码
       }
   }
})
-->
注意:
<!--
组件名以小写开头,采用短横线分割命名: 例如 hello-Word
组件中的data 必须是一个函数,注意与Vue实例中的data区分
在template模板中,只能有一个根元素
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 使用组件 -->
      <lagou-header></lagou-header>
      
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //定义全局组件
    //组件的命名规则: 一般用短横线进行连接,左边是公司名 右边组件的作用名称
    Vue.component("lagou-header", { //全局,所有挂载点都可使用(他们找不到,继续往上走,知道window的vue实例也找不到)
      template: "<div>HTML <h1 @click='hello'>{{msg}}</h1> </div>", 
      //template模板中 只能有一个根元素(且必须有一个根元素,否则不起作用)
        //否则后面的同级元素不会显示,即不会加上,只加上第一个元素
      //组件中的data是一个函数
      //vue里的data若是方法,则进行覆盖,而这里只能是方法
      //进行获得数据,不能是{},否则报错,即vue什么都不显示
      data() { //其中上面template进行添加,然后再让data进行解析
        return {
          msg: "这lagou-header是组件中的数据部分", //只在对应组件里找
        };
      },
      methods: {
        hello() { 
          alert("你好");
        },
      },
    });

    var VM = new Vue({
      el: "#app",
      data: {},
      methods: {},
    });
  </script>
</html>

Ot对象内部是其他的对象,即this._init()方法,有特别的知识使得方法里自带一些参数
就如Window一样,如window.创建的对象.a=9,那么你创建的对象里面,就有a这个属性(key)了
这就是Vue有属性(key)的原因
局部组件:
相比起全局组件,局部组件只能在同一个实例内才能被调用
局部组件的写法和全局组件差不多
唯一不同就是:局部组件要写在Vue实例里面
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <web-msg></web-msg>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //创建局部组件
    var VM = new Vue({
      el:"#app",
      components:{
        //组件名
        "web-msg":{
          template:"<div><h1>{{msg1}}</h1><h1>{{msg2}}</h1></div>",
          data() {
            return {
              msg1:"开发ing...",
              msg2:"开发完成!"
            }
          },
        }
      }

    })
  </script>
</html>

注意:
创建局部组件,注意 components,注意末尾有 “s”,而全局组件是不用+ “s” 的
这意味着,components 里可以创建多个组件,从结构上可以看出,是用键值对形式的(即可以加多个)
组件与模板分离 :
由于把html语言写在组件里面很不方便,也不太好看所以将它们分开写
这样就出现了一个固定的方式可以给多个地方使用
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 使用组件 -->
      <web-msg></web-msg>
    </div>

    <!-- 将模板写在 HTML中,给模板一个id -->
    <template id="t1"> 
      <!--
        这个标签就是一个模板标签,指定id,即属于id的挂载点可以使用这里面的内容
      这时只要挂载点使用对应标签,那么相当于就是这个标签的内容(或者就是这个标签)
      其实可以理解为这些内容放在template里面,id只是用来指定模板标签的位置,所以这里也就不能有同级的根元素
      否则除第一个根元素外,其他根元素不起作用

      这样我们就不用写很多元素写到template了,只需要一个地址
      这个标签不再页面上起作用,设置display也是没用的,这时标签的语法
      -->
      <div>
        <button @click="show">{{msg}}</button>
        
      </div>
      
    </template>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      components: {
        "web-msg": {
          template: "#t1", //这里指定选择器了,用来确定固定地方
          data() {
            return {
              msg: "点击查询",
            };
          },
            //这些方法和操作只能再模板里使用,且基本用不到外边的值,因为this不是外面的Vue了
          methods: {
            show() {
              alert("正在查询,请稍后...");
            },
          },
        },
      },
    });
  </script>
</html>

满足语法的同时,组件是可以有组件的,因为实际上就是对应html的添加和替换,只注重内容(一般全局来识别,因为他在任何时候都识别,而不像局部一样,只识别一次)
总结:
上面这种写法,浏览器会把 html 里的 template 标签过滤掉
所以 template 标签的内容是不会在页面中展示的,直到它被 JS 中的 Vue 调用。
在 html 中,template 标签一定要有一个 id,因为通过 id 是最直接被选中的
data 和 methods 等 参数,全部都要放到 Vue 实例里面写
注意: </6>代表 <!–/6>,在浏览器中,一般数字会这样,而<1>就代表<1>显示在浏览器中,一般数字会这样,这应该是浏览器的原因
Vue生命周期:
生命周期图示:
每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是vue的生命周期
了解生命周期的好处:
找错误
解决需求
下图展示了实例的生命周期,你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高

在这里插入图片描述

钩子函数介绍:
生命周期中的钩子函数
钩子函数:钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作

在这里插入图片描述

可以这样的认为:
beforeCreate():创建Vue实例,参数中这个最先被设置,即先调用这个方法,其他参数还没设置
created():其他参数被设置了,浏览器的所以内容被隐藏,这时调用这个方法后,之后显示出来
beforeMount():找到了对应的Vue的属性,但是就只是找到了而已,并没有进行操作,即设置页面内容
这时调用这个方法,可以说是还没直接使用这个key值来设置页面内容
mounted():我们已经操作完了,设置了内容,即调用这个方法,就如js设置完innerHTML或者innerText后的操作方法
beforeUpdate():当data的值进行更新时,即被修改了
但是还没有进行相关的set设置,即网页上还没有改变,那么就执行这个方法
updated():data的值更新,且set设置了页面内容,即调用了这个方法,就如js设置完innerHTML或者innerText后的操作方法
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h2 id="msg">{{message}}</h2>
      <button @click="next">获取下一句</button>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        message: "想当年,金戈铁马",
      },
      methods: {
        show() {
          alert("show方法执行了!");
        },
        next() {
          this.message = "气吞万里如虎!";
        },
      },
      // beforeCreate() {  通过生命周期来说,可以明显看到,这个是先进行的,其他的属性后执行,这时调用方法
      //   alert("1.beforeCreate函数,在Vue对象实例化之前执行");
      //   console.log(this.message); //undefined
      //   this.show(); //this.show is not a function
      // },
      // created() { 相当于将浏览器的所有内容进行隐藏,执行后显示出来,这时调用方法
      //   alert("2.created函数执行时,组件的实例化完成,但是DOM页面还未生成")
      //   console.log(this.message);
      //   this.show();
      // },
      // beforeMount() {
      //   alert(  //找到了对应语法,但没有进行渲染,即只是找到了,这时调用方法
      //     "3.beforeMount函数执行时,模板已经在内存中编辑完成了,但是还没有被渲染到页面中"
      //   );
      //   console.log(
      //     "页面显示的内容" + document.getElementById("msg").innerText
      //   );
      //   console.log("data中的数据: " + this.message);
      // },
      // mounted() { //进行渲染,即替换了,但还没进行显示,即设置,这时调用方法
        //就如js中进行改变时后面的方法操作
      //   alert("4.mounted函数执行时,模板已经被渲染到页面,执行完就会显示页面");  //也可以认为是因为他的存在才没有显示的
      //   console.log(
      //     "页面显示的内容" + document.getElementById("msg").innerText
      //   );
      // },
      // beforeUpdate() { 当data的值进行改变时,但还没有进行set设置,这时调用方法
      //   alert("5.beforeUpdate执行时,内存中的数据已经更新,但是还没有渲染到页面");
      //   console.log(
      //     "页面显示的内容" + document.getElementById("msg").innerText
      //   );
      //   console.log("data中的数据: " + this.message);
      // },
      updated() { //设置了,最后要显示页面时,调用方法,就如js中进行改变时后面的方法操作
        alert("6.updated执行时,内存中的数据已经更新,此方法执行完显示页面");
        console.log(
          "页面显示的内容" + document.getElementById("msg").innerText
        );
        console.log("data中的数据: " + this.message);
      },
    });
  </script>
</html>

<!--
在说明之前要明白,他们是异步的,也就是说,会先提交没有改变的数据,即可能会在浏览器中看到没有替换的东西(他们只是使得改变而已)
简单来说就是:
1:执行到js中,他创建vue实例
2:在创建的过程中,执行beforeCreate(beforeCreate)
3:vue实例创建完毕,内部操作一些方法,可以认为是vue自己执行,类似于经过js实现的java操作的自旋
4:在操作完毕后,然后执行created,所以他这个地方在大多数情况下我们都会使用,因为vue已经操作完毕了(created)
5:进行模板的替换,如{{}}的识别
6:替换后,执行beforeMount(beforeMount)
7:提交整个代码,在这个过程中,执行方法
8:执行mounted(mounted)
9:执行后,经过一段时间,浏览器显示完毕
10:当我们修改vue里面的data数据时,在改变页面数据之前进行执行
11:执行beforeUpdate(beforeUpdate)
12:设置后,准备提交进行替换,执行后,才提交
13:执行updated
要知道浏览器和备份的是同步的
-->

Vue Router 路由:
什么是路由:
在Web开发中,路由是指根据URL分配到对应的处理程序
路由允许我们通过不同的 URL 访问不同的内容
通过 Vue.js 可以实现多视图单页面web应用(single page web application,SPA)

在这里插入图片描述

什么是SPA:
单页面Web应用(single page web application,SPA),就是只有一张Web页面的应用
是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序
单页应用不存在页面跳转,它本身只有一个HTML页面
我们传统意义上的页面跳转在单页应用的概念下转变为了 body 内某些元素的替换和更新,举个例子:

在这里插入图片描述

整个body的内容从登录组件变成了欢迎页组件, 从视觉上感受页面已经进行了跳转
但实际上,页面只是随着用户操作,实现了局部内容更新,依然还是在index.html 页面中
单页面应用的好处:
用户操作体验好,用户不用刷新页面,整个交互过程都是通过Ajax来操作
适合前后端分离开发,服务端提供http接口,前端请求http接口获取数据,使用JS进行客户端渲染
缺点:功能全部放在一个页面中,不好维护,简单来说组件是单页面的基础操作,替换组件就是单页面的核心功能
路由相关的概念:

在这里插入图片描述

这些路由并不是真正的路由,只是一个作用而已,所以可以称为Vue的路由
实际上这样的单页面的其他页面就是组件的变化
方法里参数少些的那些值,一般是undefined
使用路由:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        1.router 是VUE中路由管理器对象,用来管理路由
        2.route 是路由对象,一个路由就对应了一条访问路径,一组路由用 routes
        3.每个路由对象,都有两部分: path路径, component组件
        4.router-link 是对a标签的封装,通过to属性 指定链接
        5.router-view 路由访问到指定的组件,进行页面展示
      */
    </style>
  </head>
  <body>
    <div id="app">
      <h1>渣浪.com</h1>

      <p>
        <!-- 添加超链接, router-link 组件来进行导航, to属性指定链接 
        值对path,然后将对应的component的值写到下面的出口,这两个参数不可变,会检查的,否则不起作用
        -->
        <router-link to="/home">go to home</router-link>
    
        <router-link to="/news">go to news</router-link>
      </p>

      <!-- 路由的出口, 路由匹配到组件之后,要渲染到这里 -->
      <router-view></router-view>

      <!-- 这样就导致了path和component的结合,通过path来决定对应component的渲染
      一般使用router-link来决定,router-view来获得渲染数据
      to属性就是决定对应的path的值,从而获得component的渲染值
      其中component的渲染是{}里面的对应key的值进行操作的
      若template有多个,则是后面的覆盖前面的,即最后一个起作用
      -->
    </div>
    
  </body>
  <!-- 导入vue 与 router库 -->
  <script src="./js/vue.min.js"></script>
  <script src="./js/vue-router.min.js"></script>
  <script>
    //1.定义路由所需的组件
    const home = { template: "<div>首页</div>" };
    const news = { template: "<div>新闻</div>" };

    //2.定义路由 每个路由有两部分 path(路径),component(组件)
    const routes = [
      { path: "/home", component: home },
      { path: "/news", component: news },
    ];

    //3.创建路由管理器实例
    const router = new VueRouter({
        //这个routes的key也必须要对应的key,不能随便设置,就如Vue的{}一样,他们都有对应的解析的
        //这里可以写routes和route
      routes: routes,
    });

    //4.创建Vue实例 ,将router注入到 vue实例中,让整个应用都拥有路由的功能
    var VM = new Vue({
      //注意:这个名称必须要是router,否则不起作用,会解析,且只操作routes,其中routes的对象是route
        //所以单独使用的route是操作不了的,需要routes被解析
      router,   //这里与方法一样,在键值对里,=连接的可以用变量代替因为本身代表有值
      //如var a = function(){},可以是a(){},而上面的创建对象,也就可以直接router表示
      //这是键值对的语法解析
    }).$mount("#app"); //代替el,当然也可以使用el,逗号隔开就行,键值对中没有顺序
      //因为没有下标,只有key来对应(因为不是数组,而是对象)

    //到这里,可以得出,Vue的东西也基本只能在Vue里起作用
  </script>
</html>

<!--简单来说,通过给组件设置路径参数,并给vue,然后vue可以将这些东西开始像html标签进行识别,从而完成对应的替换,当然,一般都会将他们的名称改为<router-view></router-view>,使得可以替换
很明显,这里以及是一个前端项目的雏形了,在vue-cli脚手架中,就是利用这些信息来完成的,并借助导出,使得各个页面可以这样操作了,于是,为了进行组件化的开放,vue内部进行大量的功工程操作,使得出现了vue后缀的文件来代替组件,当然,vue的文件,可能是js自身会识别而完成的,或者也是js开发人员进行改变的,这里了解即可
-->

路由总结:
路由可以指定的出现组件(页面)
router是Vue中的路由管理器对象,用来管理路由
route是路由对象,一个路由就对应了一条访问路径,一组路由用routes表示
每个路由对象都有两部分 path(路径)和component (组件)
router-link 是对a标签的封装,通过to属性指定连接
router-view 路由访问到指定组件后,进行页面展示
这时当你运行时,会在倒数第二个路径位置加上一个#,代表这个有路由操作,操作时无论怎么刷新,都不会变
即他们操作的值,已经固定的,即操作后,就永久的在那里了,实际上是路径的变化,因为刷新的是路径
当你点击一个地址时,会在原来的#/后面加上对应地址,所以刷新的就是这个地址,所以不会变
即也可以手动的添加路径来操作(访问)
这样的一些操作,使得多个页面,真正的变成了单页面了
最后注意:Vue的渲染,都是js造成的,虽然也可以认为是浏览器的处理(他来操作js的)
这里我们可以测试一下:
将template标签的js进行导出,由上面的路由接收,看看可不可以使用,可以发现在html中script一般是操作不了导入导出的,因为他是在node.js环境上处理的,具体来说是他里面的CommonJS 模块语法(具体来说,组件之间只有全局可以嵌套,且路由不能加组件(说的不是单纯的代码,是组件这个整体,不是上面的路由的例子),这是建立在单纯的script中的,也就是没有在node.js中操作,在下一章博客会说明的)
当然,可以考虑组件的嵌套,虽然基本只能是全局,具体可以考虑下一章的具体说明,这里就不给出了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值