(1)一个轻量级的mvvm框架,双向绑定,数据动态更新

(2)是一个渐进式框架

(3)优点显而易见,从而屏蔽了使用复杂晦涩难记的dom结构api。

(4)vue核心是vue.js

Ⅰ  Vue基础

一、data三种写法 

<!--三种data值的写法-->

data : {
  msg : "hello vueeee~~~"
}

data:function(){
  return {
      msg:"hi~vue"
  }
}

data(){
    return {
        msg:"vue hi~"
    }
}

二、插值语法

<body>
  <div id="app">
      <p>较大的那一个值为:{{num>num1?num:num1}}</p>
      <!-- split:将字符串变为数组  reverse:数组反转  join:将数组元素无缝拼接,变为字符串-->
      <p>将字符串反转{{str.split("").reverse().join("")}}</p>   
  </div>

  <script>
    new Vue({
      el: "#app",
      data: {
        num: 100,
        num1: 200,
        str: "helloWord"
      }
    })
  </script>
</body>

 三、计算属性

作用:将一个计算结果缓存起来的属性,对于任何复杂逻辑(当一个结果受多个属性影响的时候),你都应当使用计算属性

<body>
  <div id="app">
        <p>总价为:{{total}}</p>
  </div>

  <script>
    let vm = new Vue({
      el: "#app",
      data: {
        arr: [
            {name: 'vue入门', print: 99, count: 3},
            {name: 'vue进阶', print: 29, count: 3},
            {name: 'vue大神', print: 9, count: 3}
        ]
      },
      computed: {
        // 计算属性第一种格式
        // total() {
        //     let ret = this.arr.reduce((pre, current)=>{
        //         return current.print * current.count + pre
        //     }, 0)
        //     return ret + "元"
        // }
        
        // 计算属性第二种格式
        total: {
            // 在模板里第一次获取total这个计算属性的时候执行这里的代码一次
            get() {
                let ret = this.arr.reduce((pre, current)=>{
                    return current.print * current.count + pre
                }, 0)
                return ret + "元"
            },
            set(newVal) {
                // 参与计算属性的变量值发生变化,会触发这个方法.将新值传给newVal
                console.log("触发了" , newVal)
            }
        }
      }
      
    })

  </script>
</body>

四、侦听器

作用:虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

(1)立即侦听

<template>
   <div>
      <button @click="num ++">点击加一{{ num }}</button>
   </div>
</template>

<script>
export default {
   name: "VdemoComp2",

   data() {
      return {
         num: 0,
      };
   },

   // 监听器,在数据发生变化时触发监听器
   watch: {
      // 第一种写法,参数一为新值,参数二为旧值
      // num(newVal, oldVal) {
      //    console.log('num被修改了',newVal, oldVal);
      // }
      // 第二种写法
      num: {
         handler(newVal, oldVal) {
            console.log("num被修改了", newVal, oldVal);
         },
         //立即监听
         immediate: true 
      },
   },
};
</script>

(2)深度侦听和侦听一个对象

<template>
   <div>
      <button @click="obj.age++">点击加一{{ obj.age }}</button>
   </div>
</template>

<script>
export default {
   name: "VdemoComp2",

   data() {
      return {
         obj: {
            name: "vue",
            age: 19,
         },
      };
   },

   watch: {
      // 1、当侦听的属性为对象,就需要使用深度侦听
      obj: {
         // 得到的老数据没有意义,两个参数都是最新值
         handler(newVal, oldVal) {
            // 当对象中name或value中任意属性被修改,都会触发侦听器
            console.log("obj被修改了", newVal, oldVal);
         },
         // 深度侦听
         deep: true,
      },
      // 2、也可以侦听对象中某一个属性
      "obj.age": {
         handler(newVal, oldVal) {
            console.log("obj对象中age属性被修改了", newVal, oldVal);
         },
      },
   },
};
</script>

(3)计算属性和侦听器的区别

五、过滤器

(1)局部过滤器,只能在一个模板内使用

<body>
   <div id="app">
      {{price | RMBformat}}
   </div>
   <script>
      new Vue({
         el: "#app",
         data: {
            price: 100
         },
         filters: {
            // 自定义局部过滤器
            RMBformat(value) {
               return value.toFixed(2) + '元'
            }
         }
      })
   </script>
</body>

(2)全局过滤器,在所有模板中都可用

<body>
   <div id="app">
      {{price | RMBformat}}
   </div>
   <script>
      Vue.filter("RMBformat", value=>{
         return value.toFixed(2) + '元'
      })
      new Vue({
         el: "#app",
         data: {
            price: 100
         }
      })
   </script>
</body>

Ⅱ  V-  命令

 一、v-bind 

<body>
  <div id="app">
    // 作用:当属性的值是变量而不是字符串时,通过v-bind进行标识,Vue会自动处理
    <p><a v-bind:href="url">跳转百度</a></p>    
    <p><a :href="url">跳转百度</a></p>
  </div>

  <script>
    new Vue({
      el: "#app",
      data: {
        url: "https://www.baidu/"
      }
    })
  </script>
</body>

 二、事件处理 v-on

1、一个简单的点击事件

<body>
  <div id="app">
    <p>{{num}}</p>
    <p><button v-on:click="num++">点击加一</button></p>
    <p><button @click="add('hello')">点击加一</button></p>

    .left    <!-- 鼠标左键事件 -->
    .right   <!-- 鼠标右键事件 -->
    .middle  <!-- 鼠标中间滑轮事件 -->
    <div v-on:click.left="submit" >helloworld</div>

    <!--   鼠标悬停事件          鼠标移开事件 -->
    <td @mouseenter="onEnterTd"  @mouseleave="onLeaveTd">哈哈哈</td>
  </div>
  <script>
    new Vue({
      el: "#app",
      data: {
        num: 30
      },
      methods : {
        add: function(id) {
          this.num ++
          alert(id)
        }
      }
    })
  </script>
</body>

2、v-bind和v-on使用,点击修改按钮颜色

<!DOCTYPE html>
<html lang="en">

<head>
    <title></title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="css/style.css" rel="stylesheet">
    <script src="D:\JAVA\前端js包\前端js包\vue.js"></script>
</head>

<body>
    <div id="app">
        <button @click="buttonClick(1)" :class="buttonIndex == 1?'bgcolor':''">月</button>
        <button @click="buttonClick(2)" :class="buttonIndex == 2?'bgcolor':''">季</button>
        <button @click="buttonClick(3)" :class="buttonIndex == 3?'bgcolor':''">年</button>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                buttonIndex: 1,
            },
            methods: {
                buttonClick(buttonIndex) {
                    this.buttonIndex = buttonIndex
                }
            }
        })
    </script>
</body>

</html>
<style scoped>
    .bgcolor {
        background-color: #0066FF;
        border: 0;
        outline: none;
    }

    button {
        padding: 0.2rem 1.2rem;
        background: #4E6FFF;
        border: 0;
        color: white;
        border-radius: 0;
    }

    button:focus {
        outline: 0;
    }
</style>

三、条件渲染

(1)v-if 的基本使用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../前端js包/vue.js"></script>
</head>

<body>

    <div id="app">
        <div v-if="msg === 'one'">这是one</div>
        <div v-else-if="msg === 'two'">这是two</div>
        <div v-else>啥也不是</div> <br>
        <!-- 将msg与输入框进行绑定 -->
        <input type="text" v-model="msg">
    </div>

    <script>
        var app = new Vue({
            el: "#app",
            data() {
                return {
                    msg: ""
                }
            },

        })
    </script>
</body>

</html>

(2)v-if与v-show

v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

注意,v-show 不支持 <template> 元素,也不支持 v-else

<h1 v-show="ok">Hello!</h1>

(3)在<template>元素上使用 v-if

因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素。

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

(4)用key管理可复用元素

当按照第一个样式展现时,输入值之后,接着转换成第二个样式,第二个样式输入框内的值还会保持与第一个框内的值一样。这是Vue为了提高渲染效率,如果要避免这种情况,加入key值

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../前端js包/vue.js"></script>
</head>

<body>

    <div id="app">
        <template v-if="msg == 'one'">
            <div>qq号登录</div>
            <input type="text"  key="key1">
        </template>
        <template v-else>
            <div>微信号登录登录</div>
            <input type="text"  key="key2">
        </template>

        <button type="button" v-on:click="show()">点击转换样式</button>
    </div>

    <script>
        var app = new Vue({
            el: "#app",
            data() {
                return {
                    msg: "",
                    num: 0
                }
            },
            methods: {
                show: function() {
                    this.num++
                        if (this.num % 2 == 0) {
                            this.msg = "one"
                        } else {
                            this.msg = "two"
                        }
                }
            },

        })
    </script>
</body>

</html>

四、列表渲染

(1)使用v-for遍历对象

<body>
    <div id="app">
        <!-- 如果便利数组,有两个参数,参数一为值,参数二为下标 -->
        <!-- 如果便利对象,可以有三个参数,参数一为值,参数二为键,参数三为下标 -->
        <template v-for="(item, name, index) in user" v-bind::key="item.id">
            <!-- v-for中 key值使用注意: -->
            <!-- (1)建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
                 (2)因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。 
                 (3)key值尽量使用String或者int类型
                 (4)key的值,在数组不修改时使用item,修改时使用id-->
            <div>{{index}}:{{name}} + {{item}}</div>
        </template>
    </div>

    <script>
        var app = new Vue({
            el: "#app",
            data() {
                return {
                    user: {
                        username: "sunyh",
                        password: "1234",
                        age: "18"
                    }
                }
            },
        })
    </script>
</body>

(2)v-for和v-if一起使用

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>) 上

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

(3)v-fof用在组件上

<body>

    <div id="todo-list-example">
        <ul>
            <!-- 注意这里的 is="todo-item" attribute。这种做法在使用 DOM 模板时是十分必要的,因为在 <ul> 元素内只有 <li> 元素会被看作有效内容。 -->
            <!-- 这样做实现的效果与 <todo-item> 相同,但是可以避开一些潜在的浏览器解析错误。 -->
            <li is="todo-item" v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:title="todo.title"
                v-on:remove="todos.splice(index, 1)"></li>
        </ul>
    </div>

    <script>
        Vueponent("todo-item", {
            props: ['title'],
            template: '\
                        <li>\
                        {{ title }}\
                        </li>\
                    '
        })
        new Vue({
            el: '#todo-list-example',
            data: {
                todos: [
                    {
                        id: 1,
                        title: 'Do the dishes',
                    },
                    {
                        id: 2,
                        title: 'Take out the trash',
                    },
                    {
                        id: 3,
                        title: 'Mow the lawn'
                    }
                ]
            }
        })
    </script>
</body>

五、v-modle

表单输入绑定 — Vue.js

v-model 指令在表单 <input><textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

<div id="app">
    {{mag}}<br />
    <input type="text"  v-model="mag" />
</div>

<script>
    new Vue({
        el:"#app",
        data(){
            return{
                mag:"100"
            }
        }
})

</script>

六、其他v-命令

<body>
  <div id="app">
    <!-- 将p标签内的内容覆盖掉 -->
    <p v-text="str">p标签</p>  
    <!-- 解析html语句 -->
    <p v-html="str1"></p>
    <!-- 避免闪现 -->
    <p v-clock>{{str}}</p>
  </div>

  <script>
    new Vue({
      el: "#app",
      data: {
        num: 10,
        str: "hello",
        str1:'<a style="color: red;">hello world</a>'
      }
    })

  </script>
  <style>
    [v-cloak]{
      display: none;
    }
  </style>
</body>

七、自定义v-命令

(1)局部自定义指令-bind和局部自定义指令-update方法

<body>
   
      <dib id="app">
         <button @click="isShow = !isShow">按钮</button>
         <P v-myshow = 'isShow'>哈哈哈哈</P>
      </dib>

      <script>
         new Vue({
            el: "#app",
            data: {
               isShow: false
            },
            // 自定义指令
            directives: {     
               myshow: {
                  // 在v-myshow指令绑定到p标签身上的时候,执行这里的代码,只执行一次
                  // el是被绑定的这个元素,binding是一个对象,记录了绑定的一些信息
                  bind(el, binding){
                     console.log("触发自定义指令", el, binding)
                     // 页面刷新,隐藏按钮
                     el.style.display = binding.value ? "block" : "none"
                  },
                  // 被绑定标签的子节点发生变化的时候执行update
                  update (el, binding, vnode, oldVnode) {
                     el.style.display = binding.value ? "block" : "none"
                     console.log('更新:', vnode, oldVnode)
                  }
               }
            }
         })
      </script>

   </body>

(2)全局自定义指令

<body>
   <dib id="app">
      <button @click="isShow = !isShow">按钮</button>
      <P v-myshow='isShow'>哈哈哈哈</P>
   </dib>
   <script>

      Vue.directive("myshow", {
         // 在v-myshow指令绑定到p标签身上的时候,执行这里的代码,只执行一次
         // el是被绑定的这个元素,binding是一个对象,记录了绑定的一些信息
         bind(el, binding) {
            console.log("触发自定义指令", el, binding)
            // 页面刷新,隐藏按钮
            el.style.display = binding.value ? "block" : "none"
         },
         // 被绑定标签的子节点发生变化的时候执行update
         update(el, binding, vnode, oldVnode) {
            el.style.display = binding.value ? "block" : "none"
            console.log('更新:', vnode, oldVnode)
         }
      })
      new Vue({
         el: "#app",
         data: {
            isShow: false
         }
      })
   </script>
</body>

 

Ⅲ  Class 与 Style 绑定

作用:操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

一、绑定Html Class

1、对象/数组语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名

<body>
    <div id="app">
      <!-- 对象语法 -->
        <div v-bind:class="{style1:isStyle1, style2: isStyle2}"
             class="text"
             style="width: 200px; height: 200px; text-align: center; line-height: 200px;">对象语法</div>
        <div>=====================================================================</div>
        <!-- 数组语法一 -->
        <div :class="['style1','text']">数组语法一</div>
        <div>==========================================================================</div>
        <!-- 数组语法二 -->
        <div :class="[isStyle1?'style2':'',{text:isText}]">数组语法二</div>
    </div>
    <script>
        var app = new Vue({
            el:"#app",
            data : {
                 // true为显示该class样式,fals为隐藏,动态控制样式
                isStyle1:true,    // 关闭该样式
                isStyle2:false,
                isText:true
                
            }
        })
    </script>
    <style>
        .style1{
            background: rgb(17, 0, 255);     /*背景颜色*/
        }
        .style2{
            background: tomato;
        }
        .text{
            font-size: 30px;    /*字体大小*/
        }
    </style>
</body>

2、用在组件上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>class与组件绑定用在组件上</title>
    <script src="../前端js包/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-component v-bind:class="{ active: isActive }" class="baz boo"></my-component>
    </div>

    <script>
        Vueponent('my-component',{template: '<p class="foo bar">Hi</p>'})
        var app = new Vue({
            el:"#app",
            data() {
                return {
                    isActive:true
                }
            },
        })
    </script>

    <style>
        .active{
            font-size: 50px;
        }
    </style>
</body>
</html>

二、绑定内联样式(行内样式)

1、对象/数组语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名

<body>
  <div id="app">
    <div :style="{color:isColor?'red':'green', background:'rgb(17, 0, 255)', width:'200px' }">v-bind控制行内样式</div>
    <div>===============================================================================</div>
    <div :style="[{color:isColor?'red':'green', background:'rgb(17, 0, 255)' }, {width: '200px'}]">v-bind控制行内样式</div>
  </div>

  <script>
    new Vue({
      el: "#app",
      data: {
        isColor: true
      }
    })
  </script>

  <style>

  </style>
</body>

Ⅳ  组件

一、局部组件

1、实例

<body>

   <dib id="app">
      <my-header title="购物车"></my-header>
   </dib>

   <template id="temp1">
      <div>
         <h1>大标题</h1>
         <h1>{{title}}</h1>
      </div>
   </template>

   <script>
      new Vue({
         el: "#app",
         data: {
            isShow: false
         },
         components: {
            myHeader: {
               template: '#temp1',
               // 声明myHeader这个组件有一个标签属性
               props: ['title']
            }
         }
      })
   </script>

</body>

2、子组件抽取

<body>

   <dib id="app">
      <my-header :title="tit1"></my-header>
      <my-header :title="tit2"></my-header>
   </dib>

   <template id="temp1">
      <div>
         <h1>{{title}}</h1>
      </div>
   </template>

   <script>
      // 子组件抽取的内容
      let myHeader = {
         template: '#temp1',
         // 声明myHeader这个组件有一个标签属性
         props: ['title'],

      }

      new Vue({
         el: "#app",
         data: {
            tit1: '购物车',
            tit2: '分类'
         },
         components: {
            // 当名字相同可以省略
            //myHeader: myHeader
            myHeader
         }
      })
   </script>

</body>

3、子组件自己的方法和数据

<body>
   <div id="app">
      <my-header title="标题"></my-header>
   </div>

   <template id="temp">
      <div>
         <div>title的值:{{title}}</div>
         <div>{{number}}</div>
         <button @click="add">点击加一</button>
      </div>
   </template>

   <script>
      let myHeader = {
         props: {
            //     类型         默认值
            title: { type: String, default: "默认值" },
         },
         template: '#temp',
         // 子组件的数据,此处data只能使用对象
         data() {
            return {
               number: 20
            }
         },
         methods: {
            add() {
               this.number++
            },
         },
      }

      new Vue({
         el: "#app",
         data() {
            return {
            }
         },
         components: {
            myHeader
         }
      })

   </script>
</body>

4、父传子

<body>

   <dib id="app">
      <my-header :title="tit1"></my-header>
      <my-header :title="tit2"></my-header>
   </dib>

   <template id="temp1">
      <div>
         <h1>{{title}}</h1>
      </div>
   </template>

   <script>
      new Vue({
         el: "#app",
         data: {
            // 父组件中数据传给子组件
            tit1: '购物车',
            tit2: '分类'
         },
         components: {
            myHeader: {
               template: '#temp1',
               // 声明myHeader这个组件有一个标签属性
               props: ['title']
            }
         }
      })
   </script>

</body>

5、子传父

<body>

   <div id="app">
      <!-- 2、第二步定义一个自定义事件,将事件的函数名就是父组件中的函数 -->
      <my-head :number="father" @fn="methodName"></my-head>
      <p>父组件的father值为:{{father}}</p>
   </div>

   <!-- 子组件模板 -->
   <template id="temp">
      <div>
         <p>{{number}}</p>
         <button @click="add">点击加一</button>
      </div>
   </template>
   <script>

      // 子组件数据
      let myHead = {
         template: '#temp',
         props: ["number"],
         methods: {
            add() {
               // 3、在vue中提供了触发自定义事件的函数(相当于此处调用了父组件的方法,给变量加上10)
               // this.$emit('自定义事件', 参数);
               this.$emit('fn', 10);
            },
         }
      }

      new Vue({
         el: "#app",
         data() {
            return {
               father: 20,
            };
         },
         components: {
            myHead
         },
         methods: {
            // 1、第一步在父组件中定义一个修改父组件数据的方法
            methodName(val) {
               this.father = this.father + val
            },
         },
      })

   </script>
</body>

 二、全局组件

1、示例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="../js包/vue.js"></script>
	</head>
	<body>
		<div id="app">
			<button-number title="第一个按钮"></button-number>   <!--二:全局组件的使用-->
			<button-number title="第二个按钮"></button-number>  
		</div>
		<script>
			/* 一:全局组件的注册 */
			Vueponent("button-number",{  /* 参数一为组件的名字,参数二为组件的内容*/
				props: ["title"],   /* 组件的属性*/
				data:function(){
					return {
						count: 0
					}
				},
				template:"<div><h1>h1...</h1><button v-on:click='count++'>{{title}}点击加1 {{count}}</button></div>"  /* 1.1:组件的表现形式*/  
								/* 多个元素,必须具备一个根节点 */          /* 组件属性的使用*/
			})
			
			var app = new Vue({
				el:"#app",
				data: {
					
				}
			})
		</script>
	</body>
</html>

2、实际开发写法

<body>

   <dib id="app">
      <my-header></my-header>
   </dib>

   <template id="temp1">
      <h1>大标题</h1>
   </template>

   <script>
      // 实际调用格式
      Vueponent('myHeader', {
         template: "#temp1"
      });
      new Vue({
         el: "#app",
         data: {
            isShow: false
         }
      })
   </script>

</body>

三、组件的Prop属性

用于接收父组件的传值;命名规则:对大小写不敏感,浏览器会把大写解释成小写,定义的时候使用驼峰命名法(nameSunyh),使用的时候会解释成短横线连接的全小写(name-sunyh)

1、porp属性为数组

<body>

   <div id="app">
      <my-header :name="name1" :age="age1"></my-header>
   </div>

   <template id="temp">
      <h2>我的名字叫{{name}},我今年{{age}}岁了</h2>
   </template>

   <script>
      let myHeader = {
         props: ['age', 'name'],
         template: '#temp',
      }

      new Vue({
         el: "#app",
         data: {
            name1: 'sunyh',
            age1: 12
         },
         components: {
            myHeader
         }
      })
   </script>
</body>

2、prop属性为对象,并且验证数据类型,添加默认值

注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 datacomputed 等) 在 default 或 validator 函数中是不可用的。

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

<body>
    
    <div id="app">
        <bolg-post v-bind:prop-a="19" prop-b="这里是B" prop-c="这里是C" prop-f="success"></bolg-post>
    </div>

    <template id="temp">
      <div>
         <h2>这里是A的值:{{propA}}</h2>
         <h2>{{propB}}</h2>
         <h2>{{propC}}</h2>
         <h2>{{propD}}</h2>
         <h2>{{propE}}</h2>
         <h2>{{propF}}</h2>
      </div>
    </template>

    <script>
        Vueponent("bolg-post", {
            props: {
                // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
                propA: Number,
                // 多个可能的类型
                propB: [String, Number],
                // 必填的字符串
                propC: {
                    type: String,
                    required: true
                },
                // 带有默认值的数字
                propD: {
                    type: Number,
                    default: 100
                },
                // 带有默认值的对象
                propE: {
                    type: Object,
                // 对象或数组默认值必须从一个工厂函数获取
                    default: function () {
                        return { message: 'hello' }
                    }
                },
                // 自定义验证函数
                propF: {
                    validator: function (value) {
                    // 这个值必须匹配下列字符串中的一个
                        return ['success', 'warning', 'danger'].indexOf(value) !== -1
                    }
                }
            },
            template: '#temp'
        })

        var app = new Vue({
            el:"#app",
            
        })
    </script>
</body>

3、非Porp的Attribute

理解:传入非Porp的Attribute,表示调用这个组件的时候,传入type、class、style、id 等等属性。type会自动覆盖,而class和style会自动合并。id会根据 inheritAttrs: false 的值来确定是否继承,而inheritAttrs: false 选项不会影响 style 和 class 的绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>非prop属性</title>
    <script src="../前端js包/vue.js"></script>
</head>
<body>                                          
    <div id="app">
        <show-test id="121" style="color: blue;" class="abb"></show-test>
    </div>
    <script>

        Vueponent("show-test", {
            inheritAttrs: false,  // 表示不继承
            // props:{
            //     author: Number,
            //     author1: String,
            // },
            template:"<input type='date' style='border-style: dotted;'  class='form-control' id ='1111'>"
        })
        var app = new Vue({
            el:"#app",
        })
    </script>
</body>
</html>

四、解决兄弟组件传参问题

1、兄弟组件传值方式

①子传父,然后再父传子(不推荐)

②中央事件总线(空的vue对象)

③Vuex状态管理



2、中央事件总线

<body>
   <div id="app">
      <child1></child1>
      <child2></child2>
   </div>

   <template id="temp1">
      <button :style="{backgroundColor:bac}">按钮一</button>
   </template>

   <template id="temp2">
      <button @click="hdClick">按钮二</button>
   </template>

   <script>

      // 1、创建一个空的vue对象用来监听和触发自定义事件
      let bus = new Vue()

      let child1 = {
         template: '#temp1',
         data() {
            return {
               bac: 'red',
            };
         },
         created() {
            // 2、开启事件监听
            bus.$on("changeBgc", val=>{
               this.bac = val
            })
         },
         
      }

      let child2 = {
         template: '#temp2',
         methods: {
            hdClick() {
               // 修改按钮一的颜色
               // 3、触发第二步中自定义事件
               bus.$emit("changeBgc", "skyblue")
            },
         },
      }

      new Vue({
         el: "#app",
         data() {
            return {
            };
         },
         components: {
            child1,
            child2
         }
      })

   </script>
</body>

五、子组件继承css样式

子组件默认继承父组件的某些css样式,是因为css本身特性决定的,scoped属性关闭该继承关系,隔绝父子组件css样式

<style lang="scss" scoped>
</style>

Ⅴ  插槽

slot译为插槽,组件的插槽是为了让我们封装的组件更加具有扩展性(给自定义组件插入标签)。

一、匿名插槽

<body>

   <div id="app">
      <!-- 1、默认情况下,浏览器不会渲染子组件中手动添加的标签
           2、如果想要在子组件中添加标签,需要在子组件中添加slot标签来接收
           3、slot标签上没有name属性就是匿名插槽 -->
      <child>
         <a>这是a标签</a>
      </child>
   </div>

   <template id="temp1">
      <div>
         <h1>这是一个组件</h1>
         <slot></slot>
      </div>
   </template>

   <script>

      let child = {
         template: '#temp1',
      }

      new Vue({
         el: "#app",
         components: {
            child
         }
      })
   </script>
</body>

二、具名插槽

<body>

   <div id="app">
      <!--指定标签在子组件中的位置 -->
      <child>
         <a slot="like">这是a标签</a>
         <button slot="like1">按钮</button>
      </child>
   </div>

   <template id="temp1">
      <div>
         <slot name="like"></slot>
         <h1>这是一个组件</h1>
         <slot name="like1"></slot>
      </div>
   </template>

   <script>

      let child = {
         template: '#temp1',
      }

      new Vue({
         el: "#app",
         components: {
            child
         }
      })
   </script>
</body>


三、使用插槽写导航栏

<body>
   <dib id="app">
      <my-header>
         <input slot="input"></input>
         <h3 slot="h3">购物车</h3>
         <ul slot="ul">
            <li>商品</li>
            <li>评价</li>
            <li>详情</li>
         </ul>
      </my-header>
   </dib>

   <template id="temp">
      <div>
         <header>
            <div class="l">&lt;</div>
            <div class="c">
               <slot :name="slotName"></slot>
            </div>
            <div class="r">...</div>
         </header>
         <button @click="transition('input')">搜索</button>
         <button @click="transition('h3')">购物车</button>
         <button @click="transition('ul')">标题列表</button>
      </div>
   </template>

   <script>

      let myHeader = {
         template: '#temp',
         data() {
            return {
               slotName: 'input',
            };
         },
         methods: {
            transition(val) {
               this.slotName = val
            },
         },
      }

      new Vue({
         el: "#app",
         components: {
            myHeader
         }
      })
   </script>
</body>

<style>
   * {
      margin: 0;
      padding: 0;
      list-style: none;
   }

   header {
      width: 350px;
      height: 50px;
      background-color: brown;
      display: flex;
      text-align: center;
   }

   .l,
   .r {
      width: 50px;
      height: 50px;
      line-height: 50px;
      background-color: aquamarine;
      font-size: 30px;
   }

   .r {
      line-height: 30px;
   }

   .c {
      flex: 1;
      line-height: 50px;
   }

   ul {
      display: flex;
      justify-content: space-around;
   }
</style>

四、作用域插槽

<body>
   <div id="app">
      <my-header>
         <!-- 如果不做处理,这个num的作用域在父组件 -->
         <!-- slot-scpp专门收集所在标签(button)对应的slot身上的标签属性,作为自己的属性 -->
         <button slot="btn" slot-scope="obj">按钮{{num}}   {{obj.mynum}}  {{obj.title}}</button>
      </my-header>
   </div>

   <template id="temp1">
      <div>
         <h1>111</h1>
         <slot name="btn" :mynum="num" title="哈哈"></slot>
      </div>
   </template>

   <script>

      let myHeader = {
         template: '#temp1',
         data() {
            return {
               num: 100,
            };
         },
      }

      new Vue({
         el: "#app",
         components: {
            myHeader
         },
         data() {
            return {
               num: 200,
            };
         },
      })
   </script>

</body>

五、作用域插槽的四种写法

<body>

   <div id="app">
      <!-- 第二种格式 -->
      <my-header>
         <template slot="btn" slot-scope="obj">
            <button>按钮 {{obj.mynum}} </button>
         </template>
      </my-header>

      <!-- 第三种格式 -->
      <!-- 八原先slot="btn" slot-scope="obj" 用v-slot:btn="obj" 代替 -->
      <my-header v-slot:btn="obj">
         <button>按钮 {{obj.mynum}} </button>
      </my-header>

      <!-- 第四种格式 -->
      <my-header>
         <template v-slot:btn="obj">
            <button>按钮 {{obj.mynum}} </button>
         </template>
      </my-header>
   </div>

   <template id="temp1">
      <div>
         <h1>sssss</h1>
         <slot name="btn" :mynum="num"></slot>
      </div>
   </template>

   <script>

      let myHeader = {
         template: '#temp1',
         data() {
            return {
               num: 100,
            };
         },
      }

      new Vue({
         el: "#app",
         components: {
            myHeader
         }
      })

   </script>
</body>

Ⅵ  自定义事件

子主键触发父组件的事件

<!-- 父子组件组成一个无序列表,子组件触发父组件事件,删除列表内容 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>插槽</title>
    <script src="../前端js包/vue.js"></script>
</head>
<body>
    <div id="app">
        <todo>
            <todo-title slot="todo-title" v-bind:title="title"></todo-title>
                                                                            <!-- 拿到数据,绑定到组件 -->
            <todo-items slot="todo-items" v-for="(item, index) in items" v-bind:item="item" v-bind:index="index"  v-on:remove-one="removeItem()"></todo-items>
        </todo>
    </div>

    <script>
        // 代办事项 组件
        Vueponent("todo", {
            template:'<div> <slot name="todo-title"></slot> <ul><slot name="todo-items"></slot></ul> </div>'
        })

        // 代办事项-标题 组件
        Vueponent("todo-title", {
            props:["title"],
            template:"<div>{{title}}</div>"
        })

        // 代办事项-内容 组件
        Vueponent("todo-items", {
            props:["item","index"],
            template:"<li>{{item}}<button @click='remove(index)'>删除</button></li>",
            methods: {
                remove: function(index){
                    this.$emit("remove-one", index)
                }
            },
        })

        var app = new Vue({
            el: "#app",
            data() {
                return {
                    title:"标题1",
                    items:["古力娜扎", "马儿扎哈", "虚空掠夺则"],
                }
            },
            methods: {
                removeItem: function(index){
                    this.items.splice(index, 1);
                }
            }
        })
    </script>
</body>
</html>

 调用流程

Ⅶ  路由

VUE的路由: 根据用户的请求URL地址,展现特定的组件(页面)信息. (控制用户程序跳转过程)

1、路由元信息

(1)设置路由元信息

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
    // 路由的元信息,里面可以自定义一些配置
    mata: {
      isKepp: true
    }
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

(2)在组件中获取路由元信息

created() {
   console.log(this.$route.meta.isKepp);
}

2、路由的加载方式和魔法值注释

const routes = [
  {
    path: '/',
    name: 'home',
    // 路由全加载
    component: HomeView,
    meta: {
      num: 50,
      isKepp: true
    }
  },
  {
    path: '/about',
    name: 'about',
    // 路由懒加载,点击触发     // 魔法注释,打包使用
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    meta: {
      num: 60,
      isKepp: false
    }
  }
]

3、路由的跳转方式

4、动态路由(路由传参方式)

(1)方式一 查询字符串

methods: {
      btn() {
         // 第一种传参方式:查询字符串

         // 通过指定路由的路径
         this.$router.push("/about?page=1&size=10")
         this.$router.push({path: "/about", query: {page: 1, size: 10}})

         // 通过指定路由name属性
         this.$router.push({name: "about", query: {page: 1, size: 10}})
      }
   }

参数获取 

created() {
      console.log(this.$route)
   },

(2)方式二  路径信息参数

先更改路由路径

{
    path: '/about/:id',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    meta: {
      num: 60,
      isKepp: false
    }
  }
btn() {
         // 第二种传参方式:路径信息参数
         this.$router.push("/about/10")
         // 只能通过路由的name属性
         this.$router.push({name: "about", params: {id: 1})
      }

参数获取

created() {
      console.log(this.$route)
   },

5、路由重定向

// 路由重定向,当用户访问/,重定向到home
  {
    path: '/',
    redirect: "/home"
  },
  {
    path: '/home',
    name: 'home',
    component: HomeView,
    meta: {
      num: 50,
      isKepp: true
    }
  },

6、路由导航守卫

(1)全局前置守卫

每次发生路由的导航跳转时,都会触发全局前置守卫

// router文件夹下index文件
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

// 为router实例对象,声明全局前置导航守卫
// 每次发生路由的导航跳转时,都会触发beforeEach指定的function回调函数
// to是将要访问的路由的信息对象  
// from是将要离开的路由的信息对象
// next是一个函数,调用next()表示放行,允许这次路由导航
router.beforeEach((to, from, next) => {
  console.log(to, from)
  next()
})

next三种调用方式

router.beforeEach((to, from, next) => {
  // 直接放行
  next()
  // 跳转到其他页面
  next("/Tabbar")
  // 保持在本页面不动
  next(false)
})

7、路由其他知识

(1)路由tag属性

<router-view />
<ul class="tabbar">
    <!-- 将router-link标签,变成li标签 -->
    <router-link tag="li" to="/home">分类</router-link>
    <router-link tag="li" to="/home">购物车</router-link>
    <router-link tag="li" to="/home">我的</router-link>
</ul>

(2)子集路由(嵌套路由)

{
    path: '/Tabbar',
    name: 'Tabbar',
    component: () => import(/* webpackChunkName: "Tabbar" */ '../views/Tabbar.vue'),
    // 子集路由
    children: [
      {
        path: '/Tabbar/Category',
        name: 'Category',
        component: () => import(/* webpackChunkName: "Tabbar" */ '../components/Category.vue'),
      }
    ]
  }

(3)声明式导航 和 编程式导航

声明式导航:点击链接的方式,如a标签和<router-link>

编程式导航:在浏览器中,调用api方式实现导航

Ⅷ  Vue生命周期

生命周期函数,是VUE针对与用户提供的扩展的功能.如果编辑了生命周期函数,则vue对象自动执行,无需手动调用.

1.vue生命周期过程

组件用例

<template>
   <div>
      <p ref="op">{{ num }}</p>
      <button @click="add()">按钮</button>
   </div>
</template>

<script>
export default {
   name: "VdemoComp4",

   data() {
      return {
         num: 10,
      };
   },

   methods: {
      add() {
         this.num++;
      },
   },
};
</script>

<style lang="scss" scoped>
</style>

(1)初始

beforeCreate:在组件实例初始化完成之后立即调用(实例刚刚在内存中被创建出来,模板创建完成,还没有填数据)。

created:在组件实例处理完所有与状态相关的选项后调用(实例在内存中创建好,模板数据已填好,标签不可获得)。

// 初始
   beforeCreate() {
      // undefined undefined undefined
      console.log("属性num:", this.num, "方法add:", this.add, "元素p标签:", this.$refs.op) 
   },
   created() {
      // 一般情况下,数据请求写在这个函数中
      // 获得变量 获得方法 undefined
      console.log("属性num:", this.num, "方法add:", this.add, "元素p标签:", this.$refs.op) 
   },

(2)挂载

beforeMount:在组件被挂载之前调用(data的数据可以访问和修改,而此时的模板已经编译好,还没有更新到页面中)。

mounted:在组件被挂载之后调用(这个时候已经吧把编译好的模板更新到页面上了)。

// 挂载
   beforeMount() {
      // 获得变量 获得方法 undefined
      console.log("属性num:", this.num, "方法add:", this.add, "元素p标签:", this.$refs.op) 
   },
   mounted() {
      // 获得变量 获得方法 获得标签
      console.log("属性num:", this.num, "方法add:", this.add, "元素p标签:", this.$refs.op) 
   },

(3)更新

beforeUpdate:在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。

updated:在组件因为一个响应式状态变更而更新其 DOM 树之后调用。

 // 更新
   beforeUpdate() {
      // 获得新数据11  获得方法  打印标签内的值结果10旧数据,但是在内部已经将数据修完完成,但是还未渲染
      console.log("属性num:", this.num, "方法add:", this.add, "元素p标签内的数据:", this.$refs.op.innerHTML) 
   },
   updated() {
      // 获得新数据11  获得方法  打印标签内的值结果11新数据,说明数据更新并且渲染
      console.log("属性num:", this.num, "方法add:", this.add, "元素p标签内的数据:", this.$refs.op.innerHTML) 
   },

(4)销毁

beforeDestroy:在一个组件实例被卸载之前调用。

destroyed:在一个组件实例被卸载之后调用。

父组件中销毁子组件前,清除定时器实例
父组件
<template>
   <div>
      <button @click="add()">按钮</button>
      <br/>
      <Comp4sun v-if="bool"></Comp4sun>
   </div>
</template>

<script>
import Comp4sun from '@/components/Comp4sun' 

export default {
   name: "VdemoComp4",

   data() {
      return {
         bool: true,
      };
   },

   methods: {
      add() {
         this.bool = !this.bool
      },
   },

   components: {
      Comp4sun
   },

};
</script>

<style lang="scss" scoped>
</style>




子组件
<template>
   <div>
      <p>这是Comp4的子组件</p>
   </div>
</template>

<script>
export default {
   data() {
      return {
         timr: null,
      };
   },
   name: 'VdemoComp4sun',
   mounted() {
      // 在页面渲染完,开启一个定时器,在子组件被销毁后,定时器不会被销毁,还会执行
      this.timr = setInterval(()=> {
         console.log('执行了子组件中的定时器')
      },1000)
   },
   // 销毁
   beforeDestroy() {
      // 组件销毁之前做一些回收和清理工作,比如:清理定时器。全局事件
      console.log('销毁之前')
      clearInterval(this.timr)
   },
   destroyed() {
      console.log('销毁之后');
   }
};
</script>

<style lang="scss" scoped>

</style>

Ⅸ  Ajax原理及使用

 Ajax 局部刷新,异步访问。

1.原理图

2、axios请求格式

<template>
   <div>
      axios测试
   </div>
</template>

<script>
import axios from "axios";
export default {
   name: "VdemoCategory",
   data() {
      return {
         user: {
            age: 18,
            sex: "女",
         },
      };
   },
   created() {
      // get不传参   http://localhost:8080/getUserName1
      axios.get("/getUserName1").then((res) => {
         console.log(res.data);
      });

      // get传参  http://localhost:8080/getUserName2?id=111&name=syh
      axios
         .get("/getUserName2", {
            params: this.user,
         })
         .then((res) => {
            console.log(res.data);
         });

      // post传参方式一  http://localhost:8080/getUserName3
      axios
         .post("/getUserName3", {
            data: {
               num: 19,
            },
            num: 10,
         })
         .then((res) => {
            console.log(res);
         });

      // post传参方式二  http://localhost:8080/getUserName4
      axios.post("/getUserName4", this.user).then((res) => {
         console.log(res);
      });
   },
};
</script>

 Ⅰ+Ⅸ   vue的修饰符

 一、事件修饰符


    .stop
    .prevent
    .capture
    .self
    .once
    .passive

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,
用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 
只会阻止对元素自身的点击。

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,
同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器
你不想阻止事件的默认行为。

1、事件修饰符stop举例

<template>
   <div>
      <!-- 如果不添加stop属性,则点击小盒子的,会同时触发小盒子和大盒子的事件 -->
      <!-- 大盒子 -->
      <div class="big" @click="bc">
         <!-- 小盒子 -->
         <div class="small" @click.stop="sc"></div>
      </div>
   </div>
</template>

<script>
export default {
   name: "VdemoComp1",
   methods: {
      bc() {
         console.log("点击了大盒子");
      },
      sc() {
         console.log("点击了小盒子");
      },
   },
};
</script>

<style lang="less" scoped>
.big {
   width: 300px;
   height: 300px;
   background-color: aqua;
   .small {
      width: 150px;
      height: 150px;
      background-color: rgb(255, 42, 0);
   }
}
</style>

二、按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符

键位码
    .enter
    .tab
    .delete (捕获“删除”和“退格”键)
    .esc
    .space
    .up
    .down
    .left
    .right


<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

<!-- 13相当于Enter,键位码可查 vm.submit()` -->
<input v-on:keyup.13="submit">

<!-- 只有在 `key` 是 `Enter` + ‘Alt’ 时调用 `vm.submit()` -->
<input v-on:keyup.alt.enter="submittwo">

你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
<body>
    <div id="app">
        <input v-on:keyup.112="submit">
    </div>
    <script>
        Vue.config.keyCodes.f1 = 112
        var app = new Vue({
            el:"#app",
            methods: {
                submit: function() {
                    alert("f1键位");
                }
            }
        })
    </script>
</body>

三、系统修饰键

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
    .ctrl
    .alt
    .shift
    .meta


<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">

<!-- Ctrl + Click 触发方式,先点击ctrl,然后点击这些文字,就会触发函数doSomething-->
<div v-on:click.ctrl="doSomething">Do something</div>

.exact 修饰符
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<div v-on:click.ctrl="doSomething">Do something</div>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

四、表单修饰符

(1).lazy修饰符

vue中lazy修饰符的作用是提高性能,不需要实时监视属性值的变化,等到回车或者失去焦点的时候,更新data内的值

<input v-model.lazy="name">
<p>{{ name }}</p>
<script>
    new Vue({
        el: '#app',
          data: {
             name: ""
         }
    })
</script>

(2).number修饰符

vue中number修饰符的作用是将输入框内的字符串类型转换成数字类型。

<input v-model.number="number">

(3).trim修饰符

vue中trim修饰符的作用是将输入框内中前后的空格去掉。

<input v-model.trim="search_text">

Ⅱ+Ⅸ  ref属性 与 $refs对象

$refs可以收集带有ref属性的标签或者组件的信息

<template>
   <div>
      <p>=================ref属性标签实验start========</p>
      <p ref="op">这是p标签</p>
      <button @click="butt">ref属性放在标签</button>

      
      <p>=================ref属性放在组件start========</p>
      <Comp3sun ref="comp3sun"></Comp3sun>
      <button @click="butt1">ref属性放在组件</button>
   </div>
</template>

<script>
import Comp3sun from "@/components/Comp3sun.vue";

export default {
   name: "VdemoComp3",

   data() {
      return {};
   },

   components: {
      Comp3sun,
   },

   methods: {
      butt() {
         // this.$refs获得某个标签(此处获得带有ref属性为op的标签)
         console.log(this.$refs.op);
         // 获得p标签内部的文字
         console.log(this.$refs.op.innerHTML);
         // 点击修改p标签颜色
         this.$refs.op.style.color = "red";
      },
       butt1() {
         // this.$refs获得某个组件
         console.log(this.$refsp3sun);
         // 获得comp3sun组件内部的属性
         console.log(this.$refsp3sun.num);
         // 触发comp3sun组件内部的sun方法
         this.$refsp3sun.sun()
      },
   },
};
</script>
<template>
   <div>
      这是Comp3的子组件
   </div>
</template>

<script>
export default {
   name: 'VdemoComp3sun',

   data() {
      return {
         num: 3
      };
   },

   methods: {
      sun() {
         console.log('这是Comp3的子组件的方法');
      }
   }
};
</script>

<style lang="scss" scoped>

</style>

Ⅲ+Ⅸ  mixins

mixins可以用来抽取一些生命周期函数和一些公共方法,mixins中的生命周期函数会优先于组件中的生命周期函数执行

(1)创建mixins

(2)在组件中使用mixins

<template>
   <div>
      <p>Comp5组件</p>
   </div>
</template>

<script>
// 1、引入mixins
import mixins1 from "@/api";
export default {
   name: "VdemoComp5",

   data() {
      return {};
   },

   mounted() {},
   // 2、组注册mixins1
   // mixins可以用来抽取一些生命周期函数和一些公共方法
   // mixins中的生命周期函数会优先于组件中的生命周期函数执行
   mixins: [mixins1],
   created() {
      console.log("组件中的created");
   },
   methods: {},
};
</script>

<style lang="scss" scoped>
</style>

Ⅳ+Ⅸ  keep-alive标签

keep-alive保证在本页面的组件切换不会被销毁,也就是做了组件级别的缓存

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>

    <!-- keep-alive保证在本页面的组件切换不会被销毁 -->
    <keep-alive>
      <router-view/>
    </keep-alive>
  </div>
</template>

1、通过路由元信息设置设置是否缓存

一个页面通过路由显示不同的两个组件

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
    // 路由的元信息,里面可以自定义一些配置
    meta: {
      isKepp: true
    }
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    meta: {
      isKepp: false
    }
  }
]

通过拿到路由的元信息判断是否缓存该组件

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <!-- 通过路由元信息设置设置是否缓存 -->
    <keep-alive>
      <router-view v-if="$route.meta.isKepp"/>
    </keep-alive>

    <router-view  v-if="!$route.meta.isKepp"></router-view>
  </div>
</template>

2、通过keep-alive标签的include属性设置组件是否缓存

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <!-- include数组中的内容为组件的名称,exclude与include的作用相反-->
    <keep-alive :include = "['HomeView']">
      <router-view />
    </keep-alive>
  </div>
</template>

3、设置缓存的组件生命周期函数

如果设置了缓存,组件切换不会被销毁和重新创建,那么组件之间切换就不会触发生命周期函数。vue提供了组件激活触发的方法(activated)和组件沉睡触发的方法(deactivated),只适用于设置了缓存的组件

activated() {
    console.log('组件被激活时触发的方法');
},
deactivated() {
    console.log('组件沉睡时触发的方法');
}

Ⅴ+Ⅸ  Vuex

1、vuex中state和mutations

state是储存数据的地方,mutations是修改数据的地方

(1)state数据第一种获取方式

设置共享数据

在组件中访问数据

<button @click="$store.state.count ++">按钮{{$store.state.count}}</button>

(2)组件通过计算属性访问State中数据

(3)通过mutations操作State中的数据(官方推荐)

参数可以携带也可以不携带,需要注意的是mutations函数中的方法不能是异步的,如果需要异步,看(2、Action)

(4)通过mapMutations访问mutations中的方法

2、Action

用于处理异步任务。如果通过异步操作变更数据,必须通过Action,而不能使用Mutation,但是在Action中还是要通过触发 Mutation的方式间接变更数据。

在actions中必须通过触发mutations修改state中的数据

(1)不带参数执行异步

 (2)带参数执行异步

 (3)触发Action的第二种方式

3、Getter

 注意:Getter只起到包装的作用,不会改变state中的值

(1)getters的使用方式

4、vuex按功能模块化

(1)在store下创建新的分区

 (2)将数据存入新的分区,并且设置属性namespaced为true

 (3)将新分区注册到modules中

5、vuex按功能模块化后数据的获取

6、vuex最后一次拆分

将每一部分再单独拆分成一个文件夹 

Ⅵ+Ⅸ  vue知识补充

  一、vue的Style标签属性

(1)普通的 style 标签只支持普通的样式,如果想要启用 scss 或 less ,需要为 style 元素,设置 lang 属性
(2)vue组件中的style标签官方推荐开启 scoped属性。表示只在当前组件域中生效

<style lang="less" scoped>
  .login-title {
    text-align: center;
    margin: 0 auto 40px auto;
    color: #303133;
  }
</style>

二、vue中路径问题

1、组件引入路径

// @符号表示src路径
import Comp from "@/components/Comp5.vue";

2、图片路径

../  代表上一级目录    ./代表同级目录    直接写img/aa.jpg代表同级目录   

<template>
   <div>
      <!-- 图片引入方式一 -->
      <img src="../assets/image/logo.png">
      <!-- 图片引入方式二 -->
      <img :src="image01">
      <!-- 图片引入方式三 -->
      <img :src="image02">
      <!-- 图片引入方式四 -->
      <img :src="require('@/assets/image/logo.png')">
   </div>
</template>

<script>
import image01 from "@/assets/image/logo.png"
export default {
   name: "VdemoCategory",

   data() {
      return {
         image01,
         image02: require("@/assets/image/logo.png")
      };
   }
};
</script>

三、在vue中,export default { name: ‘xxx’} 中的name属性作用

四、vue2中双向绑定修改数组,页面不会重新渲染

vue提供了$set

<template>
   <div>
      {{arr}} <br>
      <button @click="updateArr">修改数据</button>
   </div>
</template>

<script>
export default {
   name: "VdemoCar",

   data() {
      return {
         arr: [10, 20 ,30]
      };
   },

   mounted() {},

   methods: {
      updateArr() {
         // this.arr[0] = 1000   可以成功修改数据,但是页面渲染不会更改
         // this.$set(数组名, 要修改的元素下标, 新的值)
         this.$set(this.arr, 0, 1000)
      }
   },
};
</script>

五、环境变量配置

1、开发环境 

(1).env.development文件内容

NODE_ENV=development
VUE_APP_BASE_URL="http://localhost:3000"

(2)开发环境启动项目

2、生产环境 

(1).env.production文件内容

NODE_ENV=production
VUE_APP_BASE_URL="http://localhost:3000"

(2)生产环境启动项目 

3、获取环境变量,在vue.config.js中获取

4、使用环境变量发送axios请求

add() {
    axios.get(process.env.VUE_APP_BASE_URL + "/EasyPoiController/getUserName1").then((res) => {
    console.log(res.data);
});

Ⅱ+Ⅸ  软件配置

 1、vue浏览器调试插件

Vue.js devtools ax

2、其他插件

(8条消息) vscod_CV小能手,的博客-CSDN博客

3、node.js

(8条消息) nodejs安装和环境配置_CV小能手,的博客-CSDN博客_nodejs安装及环境配置

Ⅲ+Ⅸ  创建vue项目

  一、Vue-cli安装

npm install -g @vue/cli       #安装vue-cli脚手架

vue -V       #查看版本

where vue      #vue安装在哪里

二、创建vue项目

(1)vue create hello-world   #创建vue项目

(2)vue模板创建,第一次选择自定义 

(3) 

(4) 

(5)

三、启动vue项目

npm run serve

Vue项目目录结构

四、在ui界面下载项目

(1) 启动ui界面

(2)如图

更多推荐

Vue2框架