Vue复习

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/axios.min.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
        <div id="app">
            {{message}}
            <br>
            <!-- v-modle 双向绑定 -->
            <input v-model="message" />
            <!-- v-bind属性绑定,即将模块中的某一属性,如value值等与Vue中的某一数据进行绑定 -->
            <div :title="msg"></div>
            <!-- 三目运算符 -->
            <div class="box" :class="[isA ? classA:'', classB]">三目运算</div>
            <!-- v-if 若是true就对组件进行渲染,否则就不渲染-->
            <p v-if="isA">isA--false</p>
            <p v-if="isB">isB--true</p>
            <!-- v-else 和 v-else-if必须在一块使用 -->
            <!-- vue中的方法有两种写法:A(){方法体};    B:function(){方法体} -->
            <!-- 输入框中的placeholder是默认的内容 -->
            <!-- v-on:clicke === @click  是等价可互换的关系 -->
            <!-- 给组件添加key可以保证该组件的唯一性 如:key="A"-->
            <!-- v-show 和样式属性display的功能类似,与v-if相比,在实际渲染中都会渲染,
            只是根据ture或者false将dispaly值设置为none或者yes-->
            <!-- v-if是真正的条件渲染,有很高的切换开销 -->
            <!-- v-show是都进行渲染,适合频繁的进行切换 -->
            <!--事件修饰符:配置@click使用
              stop 阻止冒泡
                prevent 阻止默认事件
                once 只触发一次
              -->
            <button @click="A">{{message}}</button><br />
            <button @click.once="A">{{message}}</button><br />
            <button @click.stop="A">{{message}}</button><br />
            <button @click.prevent="A">{{message}}</button><br />
            
            <!-- 鼠标修饰符:配合@mouseup. 使用 
            left
            right
            middle
            -->
            <!-- 键盘修饰符:配合@keyup. 使用
             键盘的键位:如:enter;esc;space
             按不同的键位返回不同的事件
             也可以通过时间获取当前的按键:@keyup="show($event)"
             show(e){
                this.message = e.keyCode;
                    }
             -->
             <!-- 表单事件的提交:@submit需要配合事件修饰符prevent使用
              因为,表单在提交时默认刷新页面,使用prevent阻止默认配置-->
              <!-- vue中的method 和 computed的区别,method中是一些逻辑方法,需要某些事件来触发
               而computed中不是单纯的方法,而是当作自行计算的属性来使用,在标签中也是当作属性来编写
               如:
               <p>反转后的数据{{reversedMessage}}</p>
                computed:{
                                 reversedMessage:function(){
                                     return this.message.split('').reverse().join('')
                                 }
                        }
                        任何数据发生变化,计算属性都会重新执行,视图也自行更新-->
                        <!-- vue中watch属性是一个对象,可以用来监控任何方法、属性的变化 -->
                        print:<p>{{print}}</p><br>
                        print:<p>{{print | uppercase}}</p><br>
                        print:<p>{{print | reverse}}</p><br>
        <!--********************************************************************************************************  -->
            <!-- Vue进阶:vue的组件,如下面自定义的Vue过滤器就是一个组件Vue.filter
            为什么使用组件?
            答:组件就是一个个的Vue实例,可以重复使用。
            组件的构成?
            答:如Vue.filter(参数1,参数2);参数一是组件的标签(即名字);参数二:是组件的构造器。
             1、组件分为:全局组件 和 局部组件;
             2、因为组件是Vue实例,因此组件中也可以包含data、method、watch等标签;
             3、注意:组件的data标签与往常的Vue中的data使用不同,组件中的data必须是一个函数,该函数返回一个对象
             如:data(){return msg:"我是一个组件!"}
             4、Vue.component()注册全局组件;    Vue.components()注册局部组件;
             5、Vue.extend()组件的构造器;
             6、自定义组件也可以将上面的4、与 5、连起来;如:Vue.component('aaa':{
                 data(){},method:{},template:"模板的选择器名"
             })
             7、在component组件的构造器中可以定义子组件components()
             8、在Vue中组件实例的作用域是独立的,默认情况下,父子组件之间的数据是不共享的。
             
            *9、子组件获取父组件数据:在子组件中使用props:["名字1"],在外部父组件的模板中对props进行数据绑定,
              <bbb :名字1="msg"></bbb>,这样,子组件就可以获得父组件msg的数据。
             10、props中可以包含任意数量的prop,可以是对象,也可以是数组:
              props:{
                 'm':String,
                 'myMsg':Number
                    }
             11、父组件获取子组件的数据:
                    1、在子组件中定义一个发送数据的事件;
                    2、在该点击事件中使用emit()方法,如:this.$emit('child-msg',this.a);
                    3、第一个参数:是该事件的名字;第二个参数:是要发送的数据;
                    4、在父组件中引用子组件,并获取该事件的数据:<bbb @child-msg="get"></bbb>
                    5、结论:父向子组件传递数据,是通过属性绑定的形式,父数据改变,子也会随之改变;
                            而子向父传递数据是通过emit的方法,需要事件驱动,若没有触发事件,则子数据改变
                            ,父组件的数据并不会有变化。
             12、父子组件之间的通信:子组件不能直接改变父组件中的数据,但是可以通过引用的方式改变;
                    方式一:将从父组件获取的数msg,在子组件的data域中赋值给子组件:b:this.msg;
                    在通过点击事件改变b值:this.b="被改变了";
                    方式二:通过传递对象来实现父子组件的数据通信,将父组件的数据对象传递给子组件的msg;
                    再通过点击事件改变父组件对象中的某个属性值:this.msg.a="被改变了";
             13、单一事件管理组件通信(适用于爷爷孙子通信或兄弟组件通信的情况)
                    1、准备一个空的实例对象 var Event=new Vue();
                    2、发送数据 Event.$emit(事件名称, 数据);
                    3、接收数据 Event.$on(事件名称,function(data){ }.bind(this));
             
             14、父组件访问子组件 $children或$ref
                    1.this.$children  返回该组件的子组件的数组;
                    2.this.$refs.c1.msg 创建索引id:"c1"; 建立索引:
                    <child1 ref='c1'></child1>
                    <child2 ref='c2'></child2>
             15、子组件访问父组件 $parent
                    1、this.$parent.msg
             16、子组件访问根组件 $root ,如果当前实例没有父实例,此实例将会是其自已。
                    this.$parent.msg;
             17、当在父组件的template中编写子组件的数据时,改内容是默认消失的;
                要想保存该部分内容,需要使用插槽标签slot,并且该匿名slot标签只能使用有一次。
                这样,父组件中的内容会自动插入子组件中slot标签的位置。
             18、slot标签中还可以有默认值,当父组件中有内容时,会被自动覆盖;
                若父组件中没有内容时,就会显示默认内容。
             19、相比于匿名slot标签只能使用一次,实名slot的标签可以使用多次
                在子组件中定义实名slot: <slot name="my-header">头部默认值</slot>
                在父组件中: <p slot="my-header">我是头部</p>
             -->
        <!--********************************************************************************************************  -->
            <!-- Vue的路由:本质也是一个组件
             步骤:
                1、定义路由组件
                const Home = { template: '<div>首页</div>' }
                const News = { template: '<div>新闻</div>' }
                
                2、定义路由:为组件添加映射路径
                const routes = [
                        //将/home路径设置为默认路径---路由重定向
                          { path: '/', redirect: '/home' },
                          { path: '/home', component: Home },
                          { path: '/news', component: News }
                        ]
                        
                3、创建 router 实例,然后传 `routes` 配置
                const router = new VueRouter({
                          routes // (缩写)相当于 routes: routes
                        })
                        
                4、创建和挂载根实例
                以上四部可以简化为:
                //1.创建路由实例
                const router = new VueRouter({
                    //2.定义路由
                    routes:[
                        {定义路径,component:{3.定义组件}},
                        {定义路径,component:{3.定义组件}},
                        ......,
                        {定义路径,component:{3.定义组件}}
                    ]
                        })
                
                将路由实例 router 挂载到当前App的Vue中。
                5、使用 router-link 标签来做路由的导航;通过传入 `to` 属性指定链接;<router-link> 默认会被渲染成一个 `<a>` 标签
                <router-link to="/home">home</router-link>
                
                6、使用 router-view 标签来做路由的出口,渲染页面
                7、定义路由的子路径,类似于组件中的子组件;不同的是这里不是使用components标签;
                    而是使用的children标签,children标签是一个数组,里面可能包含若干字子路径。
              **8、注意:组件只能包含一个div标签;并且所有的子路由都需要包含在父路由中,
                即需要在父路由模板中使用 router-link导航 和 router-view渲染。
                9、路由传递参数,类似于http://localhost:8080/get/${id}
                    1、重新创建组件
                    <template id="NewsDetail">
                        <div>
                            新闻详细页面
                            <span>{{$route.params.id}}</span>
                        </div>
                    </template>
                     const NewsDetail = { template: '#NewsDetail' };
                     
                    2、定义路由,增加一个路由
                     { path: '/news/:id', component: NewsDetail },
                     
                    3、 上面两部整合:
                     {
                        path: '/news/:id/', // 通过路由传参
                        name: 'news',
                        component: {
                            template: '<div>新闻:{{$route.params.id}}</div>'
                            }
                    },
                
                10、this.$router.push方法可以实现路由跳转
                // 直接跳转路由地址,参数直接带在路径中。
                    this.$router.push(`/news/${Math.random()}`);
                     
                11、this.$router.replace实现替换当前路由
                // 通过路由名称跳转,配置params参数。
                    this.$router.replace({ name: 'index', params: { id: Math.random() } });
                     
                12、this.$router.go(n)方法可以实现路由的前进后退,n表示跳转的个数,正数表示前进,负数表示后退。
                 this.$router.go(1)
                
                13、this.$router.forward()(前进一页)
                this.$router.forward()
                
                14、this.$router.back()(后退一页)。
                this.$router.back()
                
                15、通过watch实现路由监听
                类似于Vue中wacth对属性、方法进行监听。
                watch:{
                    message:function(val,oldval){
                        this.print = "message的旧值:" + oldval +",新值为:" + val;
                    }
                }    --------------------------对比------------------------------
                watch: {
                  // 监听路由跳转。
                  $route(newRoute, oldRoute) {
                    console.log('watch', newRoute, oldRoute)
                  },
                }
                
                
                16、导航守卫(navigation-guards):用来做登陆验证
                现实应用场景:如在淘宝要付款买东西,若发现未登录,则直接跳转到登陆页面;若已经登录了,则跳转到付款页面。
                const router = new VueRouter({ ... })
                
                //注册全局前置守卫--router.beforeEach
                router.beforeEach((to, from, next) => {
                  // ...
                })
                每个守卫方法接收三个参数:
                    1.to: Route即将要进入的目标 路由对象;
                    2.from: Route当前导航正要离开的路由;
                    3.next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。(类似于管道)
                    4.    next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
                    5.    next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),
                        那么 URL 地址会重置到 from 路由对应的地址。
                    6.    next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
                    7.    next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,
                        则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
                    8.
                            // 全局路由守卫
                            router.beforeEach((to, from, next) => {
                              console.log('navigation-guards');
                              // to: Route: 即将要进入的目标 路由对象
                              // from: Route: 当前导航正要离开的路由
                              // next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
                                
                                //可以登陆哪些页面
                              const nextRoute = ['news','music'];
                              let isLogin = true;  // 是否登录
                              // 未登录状态;当路由到nextRoute指定页时,跳转至login
                              //如果将要取得页面被包含
                              if (nextRoute.indexOf(to.name) >= 0) {
                                  //若未登录
                                if (!isLogin) {
                                  console.log('what fuck');
                                  router.push({ name: 'login' })
                                  //刷新当前页面
                                  location.reload();
                                }
                              }
                              // 已登录状态;当路由到login时,跳转至home
                              if (to.name === 'login') {
                                if (isLogin) {
                                  router.push({ name: 'home' });
                                  location.reload();
                                }
                              }
                              next();//类似于表明该方法是一个事务,若执行错误则回滚到from页面
                            });
                            
                    9、用户未认证(未登录或认证过期)时,重定向到 /login 的示例:
                    router.beforeEach((to, from, next) => {
                       if (to.name !== 'Login' && !isAuthenticated) {
                           next({name: 'Login'})
                       } else {
                           next()
                       }
                     })
                    
                    10、路由独享的守卫:beforeEnter 
                    定义在路由的内部,只有进入了这个路由才会被调用。
                    const routes = [    
                          {
                             path: '/home',  
                             name: 'Home',
                             component: Home,    
                             meta: {
                                 title: '首页'
                             },
                             beforeEnter: (to, from, next) => {
                               // ...
                             }
                           }]
                    11、页面传递信息
                    1、创建发送事件
                    //注意:只能发送字符串
                    sessionStorage.setItem('login',JSON.stringify(user.loginId));
                    window.location.href='index.html';
                    2、接收事件
                    //接受为Json形式数据
                    var obj=JSON.parse(sessionStorage.getItem('login'));    
             -->
        </div>
        <script>
            // 自定义vue过滤器
            Vue.filter("reverse",function(value){
                return value.split("").reverse().join("")
            })
            Vue.filter("uppercase",function(value){
                return value.toUpperCase();
            })
            var app = new Vue({
                el:"#app",
                data:{
                    message:"Hello Word!",
                    msg:"haha",
                    classA:'textColor',
                    classB:'textSize',
                    isA:false,
                    isB:true,
                    print:""
                },
                methods:{
                    A(){
                        this.message = this.message + "vue!";
                    }
                },
                watch:{
                    message:function(val,oldval){
                        this.print = "message的旧值:" + oldval +",新值为:" + val;
                    }
                }
            });
        </script>
    </body>
</html>

2、生命周期的钩子函数

<!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>Document</title>
</head>

<body>
    <div id="app">
        <span id="num">{{num}}</span>
        <button @click="num++">赞!</button>
        <h2>{{name}},有{{num}}个人点赞</h2>
    </div>

    <script src="../node_modules/vue/dist/vue.js"></script>
    
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                name: "张三",
                num: 100
            },
            methods: {
                show() {
                    return this.name;
                },
                add() {
                    this.num++;
                }
            },
            beforeCreate() {
                console.log("=========beforeCreate=============");
                console.log("数据模型未加载:" + this.name, this.num);
                console.log("方法未加载:" + this.show());
                console.log("html模板未加载:" + document.getElementById("num"));
            },
            created: function () {
                console.log("=========created=============");
                console.log("数据模型已加载:" + this.name, this.num);
                console.log("方法已加载:" + this.show());
                console.log("html模板已加载:" + document.getElementById("num"));
                console.log("html模板未渲染:" + document.getElementById("num").innerText);
            },
            beforeMount() {
                console.log("=========beforeMount=============");
                console.log("html模板未渲染:" + document.getElementById("num").innerText);
            },
            mounted() {
                console.log("=========mounted=============");
                console.log("html模板已渲染:" + document.getElementById("num").innerText);
            },
            beforeUpdate() {
                console.log("=========beforeUpdate=============");
                console.log("数据模型已更新:" + this.num);
                console.log("html模板未更新:" + document.getElementById("num").innerText);
            },
            updated() {
                console.log("=========updated=============");
                console.log("数据模型已更新:" + this.num);
                console.log("html模板已更新:" + document.getElementById("num").innerText);
            }
        });
    </script>
</body>

</html>                                                                                                                                                  

3、Vue脚手架安装

1、安装node.js
2、安装淘宝镜像加速器
npm install --registry=http://registry.npm.taobao.org

3、全局安装webpack npm install webpack -g
  
使用命令查看webpack配置:vue inspect > output.js

4、全局安装vue脚手架

npm install -g @vue/cli
npm i @vue/cli-service
卸载命令:npm uninstall vue-cli -g

5、
查看是否安装成功
vue -V   
6、Vue-cli目录说明:

build 和 con?g:WebPack 配置文件
node_modules 安装的依赖
src: 项目源码目录
static: 静态资源文件
.babelrc:Babel 配置文件,主要作用是将 ES6 转换为 ES5
.editorcon?g:编辑器配置
eslintignore: 需要忽略的语法检查配置文件
.gitignore:git 忽略的配置文件
.postcssrc.js: css 相关配置文件,其中内部的 module.exports 是 NodeJS 模块化语法
index.html: 首页,仅作为模板页,实际开发时不使用
package.json:项目的配置文件
name: 项目名称
version: 项目版本
description:项目描述
author: 项目作者
scripts:封装常用命令
dependencies:生产环境依赖
devDependencies: 开发环境依赖


初始化vue项目 vue init webpack appname:vue脚手架使用webpack模板初始化一个appname项目 启动vue项目 项目的package.json中有scripts,代表我们能运行的命令 npm start = npm run dev: 启动项目 npm run build:将项目打包
原文地址:https://www.cnblogs.com/Ao0216/p/15310233.html