zoukankan      html  css  js  c++  java
  • Vue

    快速上手Vue

    官方文档:点击 

    一、npm

    npm文档:点击 

    1、npm的安装

    • 去官网 https://nodejs.org/en/download/ 下载安装,Node.js是运行在服务端的JavaScript,基于Chrome V8 引擎的。

    • 打开终端 cmd : 执行node -v 如果出现版本号,证明安装node成功

    • 下载完node之后,会自带包管理器npm,好比是python中 pip3包管理器。pip3 install xxx

    • 查看安装版本信息:

      1. node -v 查看Node.js 版本信息

      2. npm -v 查看npm版本信息

      3. npm install npm@5.3.0 -g 更新npm到指定版本

      4. npm install npm@latest -g 更新最新版本

    2、npm 常用操作

    之前用JQuery,Bootstrap的cdn或者直接手动下载并放入项目,而且要管理版本。 有了npm,我们管理自己的依赖包以及版本更加简单。

    • cd到项目目录 :

    • 初始化npm的项目 :

      npm init --yes 使用默认配置项 生成package.json文件。 -yes可简写-y

    • 下载依赖包

      npm install vue --save
      npm install vue@1.0.1 --save       --save:把依赖包的名称和版本写到项目的依赖信息里

      npm install vuex -S
      npm install vue-router -S
      npm install axios -S
      npm i webpack@3.12.0 -D 在项目下 npm init 后再下载webpack就是局部安装 保存为开发环境依赖
      npm install css-loader -D
      npm install style-loader -D
      npm install html-webpack-plugin -D
      npm install webpack-dev-server@2.9.0 -D
      npm install vue-loader@14.1.1 -D
      npm install vue-template-compiler@2.5.17 -D
      npm i jquery --save简写install 为 i 下载依赖 不写@ 默认最新版本

      npm i webpack@3.12.0 -g 全局安装

    • 卸载包 npm uninstall vue

    • 更新包 npm update jquery

    • 下载所有的依赖包 npm install

    • npm list 列出已安装的依赖

    • 老版本需要 --save 参数 现在不需要了

    项目目录下会生成一个 node_modules 目录,npm下的包会在这个目录中。

    所有的依赖以及版本信息放在package.json文件中,

    如果删掉 node_modules目录,可以使用 npm i 来下载所有依赖。

    3、npm 常用配置项

    当我们用npm init 的时候用了参数 -y,如果不用-y我们可以进行一些配置。

    • package.json文件中有很多配置项

      -- name 项目名字 中间不能有空格只能用小写
      -- version 项目版本
      -- description 项目描述信息
      -- main 项目的入口文件
      -- scripts 指定命令的快捷方式 npm run test test是scripts里的键名 值为具体命令
      -- author 作者
      -- license 许可证
      -- dependencies 生成环境依赖的包以及版本信息
      -- devDependencies 开发环境的依赖

    <body>
        <div id="app">
            <!-- 模板语法 主要的作用是插值{{}}   angualr {{}}   react {}-->
            <h3>{{ msg }}</h3>
            <h3>{{ msg+ 'hello'}}</h3>
            <h4>{{1< 1 ? '真的':'假的'}}</h4>
            <!-- 可以插入字符串 -->
            <h5>{{'hello'}}</h5>
            <p>{{'hello world'.split('').reverse().join('')}}</p>
            <h3>{{ {name:'role'} }}</h3>
            <!-- 不能使用if - else -->
            <!-- {{}}模板语法的设计 只是为了简单的运算 -->
        </div>
    
        <!-- 1.先引包 -->
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
        // 2.创建vue实例化对象
            var app  = new Vue({
                // 发生行为的目的地,
                // 在vue的内部运行机制中,需要根据你传递的字符串进行判断,比如看你传递的字符串是#xxx还是.xxx还是 div元素查找
                // el:document.getElementById('#app'),使用这种方式更为优化,将元素直接找到,避免vue来进行判断
                el:'#app',
                // 装载的模板
                template:``,
                // 先声明数据属性
                data:{
                    // data在Vue实例化中可以是一个对象,也可以是一个函数,但是在组件中,data必须是一个函数 函数内容一定return 一个对象
    				// template中要使用的数据
                    // 数据驱动视图
                    msg:'hello Vue',
                }
            });
            app.a = 10;
            console.log(app.$el);
            console.log(app.a);
            console.log(app);  //Vue对象
            console.log(app.$el===document.getElementById('app')); //true
            // 在vue实例化对象之后,这个对象中属性 前面会有$,主要是跟我们自己定义的属性区分
        </script>
    </body>
    Vue demo

    二、指令系统

    1、常用指令

    Vue的指令directives很像我们所说的自定义属性,指令是Vue模板中最常用的功能, 它带有v-前缀,功能是当表达式改变的时候,相应的行为作用在DOM上。

    • v-test
      相当与js中innerText

    • v-html
      相当与js中innerHTML

    • v-if v-else-if v-else
      v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

    • v-for
      v-for = '(item,index) in menuList'
      v-for = '(value,key) in object'

    • v-show
      不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

    • v-bind
      使用v-bind:class = '{}||[]||变量名||常量' 对我们的页面中标签的属性进行绑定 所有的属性都可以进行绑定
      注意只要使用了v-bind 后面的字符串一定是数据属性中的值.
      :id 等价于v-bind:id

    • v-on
      v-on:click对当前DOM绑定click事件 注意:所有的原生js的事件使用v-on都可以绑定
      v-on:click 等价于 @click = '方法名'

    • v-model

    2、$属性

    • $refs获取组件内的元素
    • $parent:获取当前组件的父组件
    • $children:获取当前组件的子组件
    • $root:获取New Vue的实例化对象
    • $el:获取组件对象的DOM元素
    • 获取更新之后的dom添加事件的特殊情况:
      $nextTick 是在下次Dom更新循环结束之后执行的延迟回调,在修改数据之后使用$nextTick ,则可以在回调中获取更新之后的DOM

    <body>
        <div id="app">
            <h3>{{msg}}</h3>
            <h2 v-text='msg2'></h2>
            <p v-html='msg2'></p>
    
            <div class="box" v-if='isShow'></div>
            <div class="box" v-show='isShow'></div>
    
            <button @mouseenter="on_mouse()" @mouseleave="on_mouse()">鼠标移入移出</button>
            <p v-show="show">提示文本</p>
    
            <!--  v-if  -->
            <div v-if='Math.random() > 0.5'>此值大于0.5</div>
            <div v-else>此值小于0.5</div>
    
            <div>
            <div v-if="role == 'admin' || role=='super_admin' ">管理员你好</div>
            <div v-else-if="role == 'hr'">待查看简历列表</div>
            <div v-else> 没有权限</div>
            </div>
    
            <ul>
                <li v-for='(item,index) in menuList'>
                    <h3>{{index}}--菜名:{{item.name}}--价格{{item.price}}</h3>
                </li>
            </ul>
    
            <ul>
                <li v-for='item in menuList'>
                    <h3>价格{{item.price}}--菜名:{{item.name}}</h3>
                </li>
            </ul>
    
            <ul>
                <li v-for='(value,key) in object'>
                    {{key}}--{{value}}
                </li>
            </ul>
    
            <ul>
                <li v-for="hobby in hobby_list">{{hobby}}</li>
            </ul>
    
            <div class="wrap" v-bind:class='{active:isGreen}'></div>
            <a v-bind:href="href">路飞</a>
    
            <!-- v-on -->
            <button v-on="{mouseenter: onMouseenter, mouseleave: onMouseleave}" v-on:click="onClick(1)">点我</button>
            <input type="text" v-on="{keyup: onKeyup}">
    
        </div>
    
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript">
        // innerHTML innerText
        new Vue({
            el: '#app',
            template: ``,
            data: {
                // 数据属性
                msg: 'hello 指令系统',
                msg2: '<a href="#">这是我的数据</a>',
                isShow: false,
                show: false,
                menuList: [
                    // 数据驱动视图
                    { id: 1, name: '大腰子', price: 60 },
                    { id: 2, name: '宫保鸡丁', price: 30 },
                    { id: 3, name: '炸黄花鱼', price: 70 },
                    { id: 4, name: '炸黄花鱼2', price: 30 }
                ],
                hobby_list: ["王者毒药","LOL","吃鸡"],
                object: {
                    name: 'alex',
                    age: 19,
                },
                isGreen:true,
                href:'https://www.luffycity.com/course',
                role: 'hr',
            },
            methods: {
            on_mouse: function () {
                this.show = !this.show
            },
            onClick: function (a) {
                alert(a)
            },
            onMouseenter: function () {
                console.log("mouse enter")
            },
            onMouseleave: function () {
                console.log("mouse leave")
            },
            onKeyup: function () {
                console.log("key up")
            }
        },
        });
        </script>
    </body>
    指令系统
    <body>
        <div id="app">
            <label>
                足球
                <input type="checkbox" v-model="hobby" value="football">
            </label>
            <label>
                篮球
                <input type="checkbox" v-model="hobby" value="basketball">
            </label>
            {{hobby}}
    
            <label><input type="radio" v-model="sex" value="male">
            </label>
            <label><input type="radio" v-model="sex" value="female">
            </label>
            {{sex}}
    
            <textarea v-model="article"></textarea>
            {{article}}
    
            <select v-model="color">
                <option value="1">单选1</option>
                <option value="2">单选2</option>
            </select>
            {{color}}
    
            <select v-model="goods" multiple="">
                <option value="1">多选1</option>
                <option value="2">多选2</option>
                <option value="3">多选3</option>
            </select>
            {{goods}}
    
            <!-- v-model这个指令很好理解,其实它就是一个语法糖 它是oninput事件和绑定value的实现 -->
            <input type="text"  :value = 'text' @input = 'valueChange'>
            <h3>{{ text }}</h3>
    
            <input type="text" v-model="con">
            <h3>{{ con }}</h3>
    
            <input type="text" v-model = 'alexDesc'>
            <h4>{{alexDesc}}</h4>
    
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript">
    var app = new Vue({
        el: '#app',
        data: {
            //sex: "male",
            sex: '',
            //hobby:['football'],
            hobby:['football','basketball'],
            article:'这是一段文本。',
            color:'1',
            goods: ['2'],
            text:'alex',
            con:'hello',
            myName:'',
        },
        methods:{
            valueChange(event){
                console.log(event.target.value);
                this.text = event.target.value
            }
        },
        computed:{
            alexDesc:{
                set:function(newValue) {
                    this.myName = newValue;
                },
                get:function() {
                    return this.myName;
                }
            }
        }
    });
    </script>
    </body>
    v-model 数据的双向绑定
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
    
        Vue.component('subComp',{
            template:`<div></div>`
        })
    
        var App = {
            data(){
                    return{
                        isShow:false
                    }
            },
            template: `<div>
                        <subComp ref = 'subc'></subComp>
                        <button ref = 'btn'>我是按钮</button>
                        <p ref = 'sb'>alex</p>
                        <input type="text"  v-if = 'isShow' ref = 'fos'/>
                    </div>`,
            beforeCreate() {
                 console.log(this.$refs.btn);//undefined
            },
            created() {
                   console.log(this.$refs.btn);//undefined
            },
            beforeMount() {
                console.log(this.$refs.btn); //undefined
            },
            mounted() {
               console.log(this);  // VueComponent 组件对象
               console.log(this.$refs.btn);  // <button>我是按钮</button>
               // 如果是给组件绑定的ref  = 'subc'属性那么this.$refs.subc取到的是组件对象
               console.log(this.$refs.subc); // VueComponent 组件对象
    
               var op = this.$refs.sb;
               this.$refs.btn.onclick = function() {
                   console.log(op.innerHTML);
               };
    
                // vue实现响应式并不是数据发生变化之后DOM立刻发生变化,而是按一定的策略进行DOM的更新
                // $nextTick 是在下次Dom更新循环结束之后执行的延迟回调,在修改数据之后使用$nextTick ,则可以在回调中获取更新之后的DOM
    
                this.isShow = true;
                console.log(this.$refs.fos)  // undefined
    
                this.$nextTick(function() {
                    // 获取更新之后的DOM
                      this.$refs.fos.focus()
                });
    
            }
        }
    
        new Vue({
            el: '#app',
            data() {
                return {
                }
            },
            template: `<App />`,
            components: {
                App
            }
        });
        </script>
    </body>
    
    <!--ref
    <body>
        <div id="app">
         <div  class="box" ref="my_box">
            这是一个盒子
        </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript">
        var app = new Vue({
            el: "#app",
            mounted(){
                this.$refs.my_box.style.color = "blue";
            }
        })
    </script>
    </body>
    -->
    Vue获取DOM元素
    <body>
    <p>
    在vue中方法和计算属性达到的效果是一样的
    但是计算属性是基于依赖进行缓存的,只有依赖的数据发生改变的时候,
    才会重新执行计算属性的函数,每次调用都会从缓存中拿之前算好的数据。
    而方法是每调用一次,执行一次。</p>
    <div id="app">
    <table border="1">
            <thead>
                <th>学科</th>
                <th>分数</th>
            </thead>
            <tbody>
                <tr>
                    <td>数学</td>
                    <td><input type="text" v-model.number="math"></td>
                </tr>
                <tr>
                    <td>物理</td>
                    <td><input type="text" v-model.number="physics"></td>
                </tr>
                <tr>
                    <td>英语</td>
                   <td><input type="text" v-model.number="english"></td>
                </tr>
                <tr>
                    <td>总分</td>
                   <!--<td>{{math+physics+english}}</td>-->
                    <td>{{sum}}</td>
                </tr>
                <tr>
                    <td>平均分</td>
                   <!--<td>{{Math.round((math+physics+english)/3)}}</td>-->
                    <td>{{average}}</td>
                </tr>
            </tbody>
        </table>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript">
    var app = new Vue({
        el: '#app',
        data: {
            math: 90,
            physics:88,
            english: 78,
        },
        computed: {
            sum: function () {
                var total = this.math + this.physics + this.english
                return total
            },
            average: function () {
                var average_num = Math.round(this.sum/3)
                return average_num
            }
        }
    });
    </script>
    </body>
    Vue计算属性computed
    <body>
        <div id="app">
            <h4>{{alexDesc}}</h4>    <!--alex它的年龄是18岁   点击修改后  ALEX is SB!!!它的年龄是18岁-->
            <button @click='clickHandler'>修改</button>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
            new Vue({
                el:'#app',
                template:``,
                data(){
                    return {
                        myName:'alex',
                        age:18
                    }
                },
                methods:{
                    clickHandler(){
                        console.log(this.alexDesc);
                        this.alexDesc = 'ALEX is SB!!!';
                    }
                },
                computed:{
                    alexDesc:{
                        set:function(newValue) {
                            console.log(newValue);
                            this.myName = newValue;
                        },
                        get:function() {
                            var str = `${this.myName}它的年龄是${this.age}岁`;
                            // 默认只有getter
                            return str;
                        }
                    }
                }
            });
        </script>
    
    </body>
    Vue计算属性setter
    <body>
        <div id="app">
            <input type="text" v-model='myName'>
            <h3>{{ myName}}</h3>
            <button @click='clickHandler'>修改</button>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
            new Vue({
                el:'#app',
                template:``,
                data(){
                    return {
                        myName:'',
                        firstName:'wusir'
                    }
                },
                methods:{
                    clickHandler(){
                        this.myName = 'alex';
                    }
                },
                watch:{
                    // 检测单个属性 命令式
                    myName:function(value) {
                        console.log(value);
                        if (value === 'alex') {
                            console.log(value +' '+this.firstName+'是sb')
                        }
                    }
                }
            });
        </script>
    
    </body>
    Vue侦听属性watch
    <body>
    <p>过滤器是在数据到达用户的最后一步进行简单的过滤处理,复杂的还是要用计算属性或者方法。</p>
        <div id="app">
            <input type="text" v-model = 'price'>
            <h3>{{ price | currentPrice}}</h3>
            <h3>{{ price | rmb}}</h3>
            <h4>{{msg | reverse}}</h4>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
    
        // 注册全局的过滤器
        Vue.filter('reverse',function(value) {
            return value.split('').reverse().join('');
        });
    
        Vue.filter('rmb', function (value) {
        return value + ""
        });
    
        new Vue({
            el: '#app',
            data() {
                return{
                    price:0,
                    msg:"hello luffy"
                }
            },
            // 局部过滤器  在当前组件中声明过滤器
            filters:{
                currentPrice:function (value) {
                    // 参数1就是纯涤的元数据
                    console.log(value);
                    return '$' + value;
                }
            }
        });
        </script>
    </body>
    Vue过滤器
    <body>
        <div id="slider">
            <img :src='currentImgSrc' alt="">
            <ul>
                <li v-for = '(item,index) in imgArr' :class="{active:currentIndex==index}" @click='clickHandler(index)'>
                    {{ index +1 }}
                </li>
            </ul>
        </div>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
            // 数据驱动视图
            var imgArr = [
                {id:1,imgSrc:'./images/1.png'},
                {id:2,imgSrc:'./images/2.png'},
                {id:3,imgSrc:'./images/3.png'},
                {id:4,imgSrc:'./images/4.png'}
    
            ];
            new Vue({
                el:'#slider',
                template:``,
                data(){
                    return{
                        imgArr:imgArr,
                        currentIndex:0,
                        currentImgSrc:'./images/1.png'
                    }
                },
                methods:{
                    clickHandler(index){
                        this.currentIndex = index;
                        this.currentImgSrc = this.imgArr[index].imgSrc;
                    }
                }
            });
        </script>
    
    </body>
    轮播图

    三、Vue组件

    组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。是可复用的Vue实例。

    <body>
        <div id="app">
    
        </div>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
    
        <script type="text/javascript">
            var Vheader = {
                template:`
                    <header class='head'>
                        <span>{{title}}</span>
                    </header>
                `,
                data(){
                    return {
    
                    }
                },
                props:['title'],                              //2.在子组件中通过props声明需要传递的参数有哪些
    
            };
            var Vmain = {
                data(){
                    return{
    
                    }
                },
                template:`
                    <div class='main'>
                        <Vheader v-bind:title = 'title'></Vheader>    <!--// 1.在父组件的子组件中通过v-bind 给子组件传值-->
                    </div>
    
                `,
                components:{
                    Vheader,
                },
                props:['title']                          //2.在子组件中通过props声明需要传递的参数有哪些
            }
            new Vue({
                el:"#app",
                template:`<Vmain  :title = "text" />`,   // 1.在父组件的子组件中通过v-bind 给子组件传值
                data:{
                    text:"alex是SB",
                },
                components:{
                    Vmain:Vmain
                }
            });
        </script>
        
    </body>
    父组件-->子组件传值
    <body>
        <div id="app">
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
            var Vheader = {
                template:`
                    <header class='head'>
                        <span>123</span>
                    </header>
                `,
            };
    
            var Vaside = {
                template:`
                    <div class='aside'>
                        我是侧边栏
                    </div>
                `
            };
            var Vcontent = {
                template:`
                    <div class='content'>
                        <p>内容</p>
                        <button @click='changeSize'>改变字体大小</button>
                    </div>
                `,
                methods:{
                    changeSize(){
                        this.$emit('postChangeSize',3)   // 1.给子组件中的某个按钮绑定原生事件,调用内建的 this.$emit('自定义的事件名','传递的数据'),来向父级组件触发一个自定义的事件.
                    }
                }
            };
    
            var Vmain = {
                data(){
                        return{
                            fontsize:18
                        }
                    },
    
                template:`
                    <div class='main' :style  = '{fontSize:fontsize+"px"}'>
    
                        <Vheader></Vheader>
                        <div class='wrap'>
                            <Vaside />
                            <Vcontent @postChangeSize = 'clickHandler'/>      // 2.在父组件中的子组件标签中,用v-on绑定自定义的事件,监听子组件,并且接受传值
                        </div>
                    </div>
                `,
                methods:{
                    clickHandler(value){
                        this.fontsize  = this.fontsize+value;
                    }
                },
                components:{
                    Vheader,
                    Vaside,
                    Vcontent
                },
            }
    
            new Vue({
                el:"#app",
                template:`<Vmain/>`,
                data:{
                },
                components:{
                    Vmain:Vmain
                }
            });
        </script>
    </body>
    子组件-->父组件传值
    <body>
        <div id="app">
        </div>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
        <script type="text/javascript">
    
        let bus=new Vue();                                     // 1.借助一个空Vue对象let bus=new Vue()
        let A={
            template:`
                        <div>
                            <h1>我是子组件:A</h1>
                            <p>B被选中的出书:{{ num }}</p>
                        </div>
                    `,
            data(){
                return {
                    num:0
                }
            },
            mounted(){                                          // 3.组件2中:mounted(){bus.$on(事件,(值)=>{...})}
                //在文档准备就绪之后就要开始监听bus是否触发了xuanwo的事件
                bus.$on('xuanwo',function(val){
                    //this.num+=val;
                    console.log(this) // this 并不是组件A
    
                });
    
                bus.$on('xuanwo',(val)=>{
                    this.num+=val;
                    console.log(this) // this 是组件A
    
                })
            }
        }
    
        let B={
            template:`
                        <div>
                            <h1>我是子组件:B</h1>
                            <button v-on:click='add'>选我</button>
                        </div>
                    `,
            data(){
                return {
                    num:10
                }
            },
            methods:{
                add(){
                    bus.$emit('xuanwo',this.num);                  // 2.组件1中: 通过bus.emit(事件,值)向外传递数据
                }
            }
        }
    
        var App = {
            template: `<div>
                    <A></A>
                    <B></B>
                </div>`,
            components: {
                A,
                B
            }
        }
    
        new Vue({
            el: '#app',
            data() {
            },
            template: `<App />`,
            components: {
                App
            }
        });
        </script>
    </body>
    组件1-->组件2传值
    <body>
        <div id="app">
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
            // 打油诗: 先声子 挂子 用子
            // 1.先声明组件
            // 局部组件
            var Vheader = {
                template:`
                    <header class='head'>
                        <span>{{title}}</span>
                        <span>{{count}}</span>
                        <button @click = 'count+=1'>点击</button>
                    </header>
                `,
                data(){
                    return {
                        count: 0
                    }
                },
                //父组件向子组件传递数据:通过Prop   props:['自定义的属性1','自定义属性2']
                //当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性,那么我们就可以像访问data中的值一样  
                //在父组件中的子组件标签中,绑定自定义的属性 <Vheader :title = '父组件中data声明的数据属性'/>  
                //一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
                props:['title'],
                methods:{
    
                }
            };
    
            var Vaside = {
                template:`
                    <div class='aside'>
                        我是侧边栏
                    </div>
                `
            };
            var Vcontent = {
                template:`
                    <div class='content'>
                        <ul>
                            <li v-for = 'post  in posts' :key = 'post.id'>
                                <h3>我的博客标题:{{post.title}}</h3>
                                <p>我的博客内容:{{post.content}}</p>
                            </li>
                        </ul>
                        <button @click='changeSize'>改变字体大小</button>
                    </div>
                `,
                props:['posts'],
                methods:{
                    changeSize(){
                        // 如何从子组件传递数据到父组件
                        // 给子组件中的某个按钮绑定原声事件,可以调用内建的 this.$emit('自定义的事件名','传递的数据'),来向父级组件触发一个自定义的事件.
                        // 在父组件中的子组件标签中,绑定自定义的事件
                        // this指的vue实例化对象的子类
                        this.$emit('postChangeSize',3)
                    }
                }
            };
    
            // 局部组件 我是入口组件
            var Vmain = {
                data(){
                        return{
                            fontsize:18
                        }
                    },
            // 3.使用子组件
                template:`
                    <div class='main' :style  = '{fontSize:fontsize+"px"}'>
    
                        <Vheader v-bind:title = 'title'></Vheader>  //#######在父组件中的子组件标签中,绑定自定义的属性
                        <div class='wrap'>
                            <Vaside />
                            <Vcontent v-bind:posts = "appPosts"  @postChangeSize = 'clickHandler'/> //#######在父组件中的子组件标签中,绑定自定义的事件
                        </div>
                    </div>
                `,
                methods:{
                    clickHandler(value){
                        this.fontsize  = this.fontsize+value;
                    }
                },
                components:{
                    // 2.挂载子组件   Vheader等价于Vheader:Vheader 
                    Vheader,
                    Vaside,
                    Vcontent
                },
                props:['title','appPosts']
            }
    
            new Vue({
                el:"#app",
                // 3.使用子组件
                template:`<Vmain  :title = "text" :appPosts = "posts"/>`, //入口组件
                data:{
                    text:"alex",
                    posts:[
                        {id:1,title:"组件中的传值",content:"通过Prop传递数据"},
                        {id:2,title:"组件中的传值2",content:"通过Prop传递数据2"},
                        {id:3,title:"组件中的传值3",content:"通过Prop传递数据3"},
                    ]
                },
                components:{
                    // 2.挂载子组件  key表示组件名 value:组件对象
                    Vmain:Vmain
                }
            });
        </script>
    </body>
    局部组件的使用
    <body>
        <div id="app">
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
        // 创建全局组件  第一个参数是公共组件的名字,第二个参数options
        /*
        Vue.component('全局组件的名字',{
         跟new Vue() 实例化对象中的options是一样,但是要注意:
         不管是公共组件还是局部组件 data必须是个函数 函数一定要返回 {}
        })
        */
        Vue.component('Vbtn', {
            template: `<button class='defalut' :class='type'>
                    <slot></slot>  //元素作为承载分发内容的出口
                </button>`,
            props: ['type']
        });
    
        var Vheader = {
            data() {
                return {
    
                }
            },
            template: `<div id='head'>
                    <Vbtn>登录</Vbtn>
                    <Vbtn>注册</Vbtn>
                    <Vbtn>提交</Vbtn>
                    <Vbtn>默认的按钮</Vbtn>
                    <Vbtn type='primary'>主要的按钮</Vbtn>
                    <Vbtn type='success' >成功的按钮</Vbtn>
                </div>`
        };
    
        var App = {
            template: `<div>
                    <Vheader></Vheader>
                </div>`,
            components: {
                Vheader
            }
        }
    
        new Vue({
            el: '#app',
            data() {
            },
            template: `<App />`,
            components: {
                App
            }
        });
        </script>
    </body>
    全局组件的使用
    <body>
    <div id="app">
        <PopUp></PopUp>
        <ToolTip></ToolTip>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript">
    //混合Mixins  重复功能和数据的储存器,可以覆盖Mixins的内容。
    var base = {
         data: function () {
            return {
                visible: false,
            }
        },
        methods: {
            show: function () {
                this.visible = true
            },
            hide: function () {
                this.visible = false
            }
        }
    }
    
    Vue.component('popup', {
        template:`
            <div>
            <button @click="show">PopUp show</button>
            <button @click="hide">PopUp hide</button>
            <div v-if="visible"><p>hello everybody</p></div>
            </div>
        `,
        mixins: [base],
        data: function () {
            return {
                visible: true,
            }
        }
    
    });
    Vue.component('tooltip', {
        template: `
            <div>
            <div @mouseenter="show" @mouseleave="hide">ToolTip</div>
            <div v-if="visible"><p>ToolTip</p></div>
            </div>
        `,
        mixins: [base]
    });
    
    new Vue({
        el: "#app",
    })
    </script>
    </body>
    混合Mixins

    四、Vue生命周期(钩子函数)

    • create 和 mounted 相关

      beforecreated :el 和 data 并未初始化
      created:完成了data数据的初始化 el 没有
      beforeMount:完成了el 和 data的初始化
      mounted:完成了挂载
      也就是说挂载前的状态是虚拟DOM技术,先把坑站住了,挂载之后才真正的把值渲染进去.

    <body>
        <div id="app">
            <App></App>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script type="text/javascript">
        var Test = {
            data(){
                return{
                    message:"哈哈哈"
                }
            },
            template:`
                <div>
                    <div>{{message}}</div>
                    <button @click = 'changeHandler'>修改</button>
                </div>
            `,
            methods:{
                changeHandler(){
                    this.message = this.message + 'alex'
                }
            },
            /*
            beforeCreate: function () {
                console.group("beforeCreate  创建实例之前===========");
                console.log("el: " + this.$el); // undefined
                console.log("data: " + this.$data); // undefined
                console.log("message: " + this.message);  // undefined
            },
            */
            beforeCreate(){
                // 组件创建之前
                console.group("beforeCreate  创建实例之前===========");
                console.log("el: " + this.$el); // undefined
                console.log("data: " + this.$data); // undefined
                console.log("message: " + this.message);  // undefined
            },
             created(){
                 // 组件创建之后
                 // 使用该组件,就会触发以上的钩子函数,created中可以操作数据,发送ajax,并且可以实现vue==》页面的影响  应用:发送ajax请求
                 console.group("Created:  创建实例完成===========");
                console.log("el: " + this.$el); // undefined
                console.log("data: " + this.$data); // 已被初始化
                console.log("message: " + this.message); // 已被初始化
                 this.message = '嘿嘿黑';
             },
             beforeMount(){
                 // 装载数据到DOM之前会调用
                console.group("beforeMount  挂载前状态==========");
                console.log("el: " + this.$el); // undefined
                console.log("data: " + this.$data); // 已被初始化
                console.log("message: " + this.message); // 已被初始化
                console.log(document.getElementById('app'));
             },
              mounted(){
                  // 这个地方可以操作DOM
                 // 装载数据到DOM之后会调用 可以获取到真实存在的DOM元素,vue操作以后的DOM
                console.group("Mounted  挂载结束状态=============");
                console.log("el: " + this.$el); // 已被初始化
                console.log("data: " + this.$data); // 已被初始化
                console.log("message: " + this.message); // 已被初始化
                 console.log(document.getElementById('app'));
             },
             beforeUpdate(){
                 // 在更新之前,调用此钩子,应用:获取原始的DOM
                console.group("beforeUpdate  更新前状态=========");
                console.log("el: " + this.$el);
                console.log("data: " + this.$data);
                console.log("message: " + this.message);
                 console.log(document.getElementById('app').innerHTML);
             },
             updated(){
                 // 在更新之前,调用此钩子,应用:获取最新的DOM
                console.group("Updated  更新完成状态");
                console.log("el: " + this.$el);
                console.log("data: " + this.$data);
                console.log("message: " + this.message);
                 console.log(document.getElementById('app').innerHTML);
            },
            beforeDestroy(){
                console.group("beforeDestroy  实例销毁之前");
                console.log("el: " + this.$el);
                console.log("data: " + this.$data);
                console.log("message: " + this.message);
                console.log('beforeDestroy');
            },
            destroyed(){
                console.group("Destoryed  实例销毁之后");
                console.log("el: " + this.$el);
                console.log("data: " + this.$data);
                console.log("message: " + this.message);
                console.log('destroyed');
            },
            activated(){
                console.log('组件被激活了');
            },
            deactivated(){
                console.log('组件被停用了');
    
            }
        }
    
        var App = {
            data(){
                return {
                    isShow : true
                }
            },
            template:`
                <div>
                    <keep-alive>
                        <Test v-if = 'isShow'></Test>
                    </keep-alive>
                    <button @click = 'changeHandler'>改变组件的生死</button>
                </div>
            `,
            methods:{
                changeHandler(){
                    this.isShow = !this.isShow;
                }
            },
            components:{
                Test
            }
        };
        new Vue({
            el:'#app',
            template:``,
            components:{
                App
            }
        });
        </script>
    
    </body>
    Vue生命周期(钩子函数)

    五、Vue-Router

    • vue-router是Vue的路由系统,定位资源的,我们可以不进行整页刷新去切换页面内容。
    • $route为当前router调转对象,里面可以获取name, path, query, params等
    • $router为VueRouter实例,有$router.push方法等
    • 路由的生命周期就是从一个路由跳转到另一路由整个过程,两个钩子router.beforeEach() router.afterEach()
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="vue.js"></script>
        <!-- 1.引入 vue-router的对象 -->
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
        <!-- 全局的VueRouter对象   vue-router 还给咱们提供了两个全局的组件 router-link  router-view-->
        <script type="text/javascript">
        // 嵌套路由:
        // 需求:进入首页之后 点击 音乐 /home/music     电影 /home/movie
        Vue.use(VueRouter);
    
    
        var Home = {
            template: `
                    <div>
                        <br />
    
                        <router-link to = '/home/music'>音乐</router-link>   // 嵌套路由不要用name,不然会有警告,用to
                        <router-link to = '/home/movie'>电影</router-link>
    
                        <!--子路由组件的出口-->
                        <router-view></router-view>
                        
                    </div>
                `
        };
    
        var Music = {
            template: `
                    <div>我是音乐</div>
    
                `
        };
        var Movie = {
            template: `
                    <div>我是电影</div>
    
                `
        };
    
        // 3.创建一个路由对象
        var router = new VueRouter({
            // 配置路由对象
    
            routes: [{
    
                    path: '/',
                    // redirect:{name:'home'}
                    redirect: '/home'
                },
                {
                    // 动态的路由参数 以冒号开头
                    path: '/home',
                    // name:'home',  //嵌套路由不要用name,不然会有警告
                    component: Home,
                    children: [
                        // 动态路由匹配 表示你的子组件中的结构是不同的
    
                        // 当访问/home时,Home组件的出口是不会渲染任何内容,这是因为没有匹配到合适的子路由
                        {
                            path: '',
                            component: Music
                        },
                        {
                            path: 'music',
                            component: Music,
    
                        },
                        {
                            path: 'movie',
                            component: Movie
    
                        }
    
                    ]
                }
            ]
    
        });
        var App = {
            template: `
                    <div>
                        <router-link to = "/home">首页</router-link>
                        <!--路由组件的出口-->
    
                        <router-view></router-view>
    
                    </div>
                `
        };
    
        new Vue({
            el: '#app',
            components: {
                App
            },
            router,
            template: `<App />`
        });
        </script>
    </body>
    嵌套路由
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="vue.js"></script>
        <!-- 1.引入 vue-router的对象 -->
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
        <!-- 全局的VueRouter对象   vue-router 还给咱们提供了两个全局的组件 router-link  router-view-->
        <script type="text/javascript">
        // 嵌套路由:
        // 需求:进入首页之后 点击 音乐 /home/music   电影 /home/movie
        Vue.use(VueRouter);
    
    
        var Timeline = {
            template: `
                    <div>
                        <router-link :to = "{name:'comDesc',params:{id:'android'}}">Android</router-link>
                        <router-link :to = "{name:'comDesc',params:{id:'frontend'}}">前端</router-link>
    
                        <router-view></router-view>
                        
                    </div>
                `
        };
        var Pins = {
            template: `
                    <div>
                        我是沸点
                    </div>
                `
        };
    
        // 共同的子组件
        var ComDesc = {
            data() {
                return {
                    msg: ''
                }
            },
            template: `
                <div>
                        我是{{msg}}
                </div>
            `,
            created() {
                // alert(1);
                this.msg = 'andorid';
            },
            watch: {
    
    // 提醒一下,当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
                '$route' (to, from) {
                    // 对路由变化作出响应...
                    console.log(to);
                    console.log(from);
    
                    this.msg = to.params.id;
    
                }
            }
        }
    
    
        // 3.创建一个路由对象
        var router = new VueRouter({
            // 配置路由对象
            routes: [{
                    // 动态的路由参数 以冒号开头
                    path: '/timeline',
                    component: Timeline,
                    children: [{
                            path: "",
                            component: ComDesc
                        },
                        {
                            path: '/timelin/:id',
                            name: 'comDesc',
                            component: ComDesc
                        }
                    ]
    
                },
                {
                    // 动态的路由参数 以冒号开头
                    path: '/pins',
                    name: 'pins',
                    component: Pins,
    
                }
    
            ]
    
        });
        var App = {
            template: `
                    <div>
                        <router-link to = "/timeline">首页</router-link>
                        <router-link to = "/pins">沸点</router-link>
                        <!--路由组件的出口-->
    
                        <router-view></router-view>
    
                    </div>
                `
        };
    
        new Vue({
            el: '#app',
            components: {
                App
            },
            router,
            template: `<App />`
        });
        </script>
    </body>
    动态路由匹配
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="vue.js"></script>
        <!-- 1.引入 vue-router的对象 -->
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
        <!-- 全局的VueRouter对象   vue-router 还给咱们提供了两个全局的组件 router-link  router-view-->
        <script type="text/javascript">
        // 嵌套路由:
        // 需求:进入首页之后 点击 音乐 /home/music   电影 /home/movie
        Vue.use(VueRouter);
    
    
        var Timeline = {
            template: `
                    <div>
                        我是首页
                    </div>
                `,
            created() {
                console.log('首页组件创建了');
            },
            mounted() {
                console.log('首页组件DOM加载了')
            },
            destroyed() {
                console.log('首页销毁了');
            }
        };
        var Pins = {
            template: `
                    <div>
                       
                    <h3 @click = 'clickHandler'> 我是沸点</h3>
                        
                    </div>
                `,
            methods: {
                clickHandler(e) {
                    e.target.style.color = 'red';
                }
            },
            created() {
                console.log('沸点组件创建了');
            },
            mounted() {
                console.log('沸点组件DOM加载了')
            },
            destroyed() {
                console.log('沸点销毁了');
            }
        };
    
    
    
    
        // 3.创建一个路由对象
        var router = new VueRouter({
            // 配置路由对象
           
            routes: [{
                    // 动态的路由参数 以冒号开头
                    path: '/timeline',
                    component: Timeline
                },
                {
                    // 动态的路由参数 以冒号开头
                    path: '/pins',
                    name: 'pins',
                    component: Pins,
    
                }
    
            ]
    
        });
        var App = {
            template: `
                    <div>
                        <router-link to = "/timeline">首页</router-link>
                         <router-link to = "/pins">沸点</router-link>
                        <!--路由组件的出口-->
            <keep-alive>
                        <router-view></router-view>
            </keep-alive>
                    </div>
                `
        };
    
        new Vue({
            el: '#app',
            components: {
                App
            },
            router,
            template: `<App />`
        });
        </script>
    </body>
    keep-alive 缓存
    <body>
        <!--
            SPA : Single Page Application
    
            前端路由
                1.锚点值 监视
                2.ajax获取动态的数据
                3.核心点是锚点值的改变
    
            前端中 vue|react|angular 都很适合做单页面应用
         -->
    
         <a href="#/login">登录页面</a>
         <a href="#/register">注册页面</a>
         <div id="app">
    
         </div>
         <script type="text/javascript">
             // onhashchange 事件  url上的锚点数据(#/xxx改变)
             var oDiv = document.getElementById('app');
    
             window.onhashchange = function(){
                 console.log(location.hash);
                 // 根据不同的锚点值,对页面不同的切换。
                 switch (location.hash) {
                     case '#/login':
                         oDiv.innerHTML = '<h2>登录页面</h2>'
                         break;
                     case '#/register':
                         oDiv.innerHTML = '<h2>注册页面</h2>'
                         break;
                     default:
                         // statements_def
                         break;
                 }
             }
         </script>
    </body>
    前端路由的实现原理
    <body>
        <div id="app"></div>
    
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <!-- 1.引入vue.js-->
        <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
        <!-- 2.引入 vue-router的对象 -->
        <!-- 全局的VueRouter对象   vue-router 还给咱们提供了两个全局的组件 router-link  router-view-->
        <script type="text/javascript">
            // 3.让Vue使用该VueRouter创建
            Vue.use(VueRouter);
    
            var Login = {template:`<div>登录页面</div>`};
            var Register = {template:`<div>注册页面</div>`};
    
            var nameLogin = {template:`<div>命名登录页面</div>`};
            var nameRegister = {template:`<div>命名注册页面</div>`};
    
            var UserParams = {template:`<div>我是用户{{$route.params.userId}}</div>`,
                created(){
                    console.log(this.$route.params.userId);  // 1 获取参数
                    // 发送ajax请求
                    console.log(this.$router);              // VueRouter
                }
            };
            var UserQuery = {template:`<div>我是用户{{$route.query.userId}}</div>`,
                created(){
                    console.log(this.$route);               // Object
                    console.log(this.$route.query.userId);  // 2 获取参数
                    // 发送ajax请求
                    console.log(this.$router);             // VueRouter
                }
            };
    
            // 4.创建一个路由对象
            var router = new VueRouter({
                // 配置路由对象
                routes:[
                    {
                        path:'/login',
                        component:Login
                    },
                    {
                        path:'/register',
                        component:Register
                    },
                    // 命名路由
                    {
                        path:'/nlogin',
                        name:'nlogin',
                        component:nameLogin
                    },
                    {
                        path:'/nregister',
                        name:'nregister',
                        component:nameRegister
                    },
                    // 路由参数
                    {
                        // 动态的路由参数 以冒号开头
                        path:'/user/:userId',
                        name:'userp',
                        component:UserParams
                    },
                    {
                        path:'/user',
                        name:'userq',
                        component:UserQuery
                    }
                ],
                //mode: 'history',    //路由去掉#
    
            });
            var App = {
                template:`
                    <div>
                        <!--router-link默认会被渲染成a标签 to属性默认会被渲染成href属性-->
                        <router-link to="/login">登录页面</router-link>
                        <router-link to="/register">注册页面</router-link>        
    
                        <!--命名路由  注意router-link里to一定要v-bind-->
                        <router-link :to="{name:'nlogin'}">命名登录页面</router-link>
                        <router-link :to="{name:'nregister'}">命名注册页面</router-link>
    
                        <!--路由参数  路由范式
                              (1)xxxx.html#/user/1             params
                              (2)xxxx.html#/user?userId = 2    query
                        -->
                        <router-link :to="{name:'userp',params:{userId:1}}">用户1</router-link>
                        <router-link :to="{name:'userq',query:{userId:2}}">用户2</router-link>
    
                        <router-link to="/user?userId=99">用户99</router-link>
                        <router-link to="/user/88">用户88</router-link>
    
                        <!--编程式导航-->
                        <button @click = 'paramsHandler'>用户123</button>
                        <button @click = 'queryHandler'>用户321</button>
    
                        <!--路由组件的出口-->
                        <router-view></router-view>
                    </div>
                `,
                methods:{
                    paramsHandler(){
                        // 编程式导航
                          this.$router.push({ name: 'userp', params: { userId: 123 }})
                    },
                    queryHandler(){
                          this.$router.push({ name: 'userq', query: { userId: 321 }})
                    }
                }
            };
    
            new Vue({
                el:'#app',
                components:{
                    App
                },
                router,        // 5.##挂载
                template:`<App />`
            });
    
        </script>
    </body>
    vue-router基本配置
    <body>
        <div id="app">
        <div>
            <router-link to="/">首页</router-link>
            <router-link :to="{name: 'about'}">关于我们</router-link>
            <router-link to="/user/alex?age=19">alex</router-link>
        </div>
        <div>
            <router-view></router-view>
            <!--命名路由视图,显示不同区域,就需要对视图进行命名-->
            <router-view name="content" class="content-view"></router-view>
            <router-view name="footer" class="footer-view"></router-view>
        </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script type="text/javascript">
    
    Vue.use(VueRouter);
    let routes = [
            {
                path: '/',
                /*
                component: {
                    template: `<h1>这是主页</h1>`
                }*/
                //命名路由视图
                components: {
                    content: {
                        template: `<div><h1>首页1111</h1></div>`,
                    },
                    footer: {
                        template: `<div><h1>首页2222</h1></div>`,
                    }
                }
            },
            {
                path: "/about",
                name: "about",
                component: {
                    template: `<h1>关于我们</h1>`
                }
            },
            {
            path: "/user/:name",
            component: {
                template: `<div>
                          <h1>我是:{{$route.params.name}}</h1>
                          <h1>我年龄是:{{$route.query.age}}</h1>
                          <router-link to="more" append>更多信息</router-link>
                          <router-view></router-view>
                        </div>`,
            },
            children: [
                {
                path: "more",
                component: {
                    template: `<div>
                          {{$route.params.name}}的详细信息
                    </div>`,
                }
            }
            ]
        },
        //错误路由的重定向
        {
            path: "**",
            redirect: "/about"
        },
        ];
    
        let router = new VueRouter({
            routes: routes,
            //mode: "history"
        });
    
        const app = new Vue({
            el: "#app",
            router: router,
            mounted(){
                console.log(this.$route)
                console.log(this.$router)
            }
        })
        </script>
    </body>
    命名路由视图
    <body>
        <div id="app"></div>
    
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
        <script type="text/javascript">
    
        Vue.use(VueRouter);
    
         // 1.点击题库时,检测用户是否登录过,如果没有,则跳转登录页面。
        // 2.当用户点击退出,该用户直接删除
        var Home = {template: `<div>我是首页</div>`};
        var Questionbank = {template: `<div>我是题库</div>`};
    
        // 登录组件
        var Login = {
            data(){
                return {
                    name:'',
                    pwd:''
                }
            },
            template:`
                    <div>
                        <input type="text" v-model = 'name' />
                        <input type="text" v-model = 'pwd' />
                        <input type="button"  value = '登录' @click = 'loginHandler'/>
                    </div>
            `,
            methods:{
                loginHandler(){
                        //用户名和密码保存到 localStorage 然后跳转相应的路由(智能题库)
                        localStorage.setItem('user', {name:this.name,pwd:this.pwd});
                        // 编程式导航
                        this.$router.push({name:'questionbank'});
                }
            }
        };
    
        var router = new VueRouter({
            routes: [{
                    path: '/home',
                    component: Home
                },
                {
                    path: '/questionbank',
                    name: 'questionbank',
                    component: Questionbank,
                    // 给未来的路由 做权限控制
                    meta:{
                        // 表名访问该组件时需要登录
                        required_login: true
                    }
                },
                {
                    path:'/login',
                    component:Login
                }
            ]
        });
    
        // 全局的导航守卫  钩子1
        router.beforeEach(function(to,from,next){
            console.log(to.meta.required_login);
            console.log(from);
            // 如果不调用next 那么页面会卡主
            if(to.meta.required_login){
                // 用户点击了智能题库的导航,需要对用户做登录判断
                if (localStorage.getItem('user')) {
                    // 不为空 放行
                    next()
                }else{
                    // 为空  进入登录页面
                    next({path:'/login'});
                }
            }else{
                // 直接放行
                next();
            }
        });
    
        /*
        next:function  一定要调用这个方法来resolve这个钩子函数。
            执行效果依赖next方法的调用参数
            next() 什么都不做继续执行到调转的路由
            next(false) 中断当前导航 没有跳转 也没有反应
            next("/")  参数是路径 调转到该路径
            next(error)  如果next参数是一个Error实例 导航终止该错误
                        会传递给router.onError()注册过的回调中
    
        钩子2
        router.afterEach(function (to, from) {
        console.log(to)
        console.log(from)
        });
        */
    
        var App = {
            template: `
                    <div>
                        <router-link to = "/home">首页</router-link>
                         <router-link to = "/questionbank">智能题库</router-link>
                         <router-link to = '/login'>登录</router-link>
                         <a href="javascript:void(0)" @click = 'clear'>退出</a>
                        <!--路由组件的出口-->
                        <keep-alive>
                        <router-view></router-view>
                        </keep-alive>
                    </div>
                `,
                methods:{
                    clear(){
                        // 退出
                        localStorage.removeItem('user');
                        this.$router.push('/login');
                    }
                }
        };
    
        new Vue({
            el: '#app',
            components: {
                App
            },
            router,
            template: `<App />`
        });
        </script>
    </body>
    meta路由元信息实现权限控制

    六、axios

    • 官方文档:点击 

    • 基于Promise的HTTP请求客户端,可以同时在浏览器和node.js使用。
      - 从浏览器中创建 XMLHttpRequests
      - 从 node.js 创建 http 请求
      - 支持 Promise API
      - 拦截请求和响应
      - 转换请求数据和响应数据
      - 取消请求
      - 自动转换 JSON 数据
      - 客户端支持防御 XSRF

    • 使用npm安装axios: -- npm install axios -D

    • 基本的配置:
      Vue.prototype.$axios = axios; 挂载,就可以在任意组件中通过this.$axios获取到当前的axios实例
      axios.defaults.baseURL = 'http://127.0.0.1:8800' 默认配置URL

    <body>
        <div id="app"></div>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/axios/dist/axios.js"></script>
        <!-- vue和axios都是全局的对象  未来 axios会成为局部作用域-->
        <script type="text/javascript">
            // 1.挂载 
            Vue.prototype.$axios = axios;
            // 2.配置公共的url
            axios.defaults.baseURL = 'http://127.0.0.1:8800';
            var App = {
                data(){
                    return {
                        msg:'',
                        datas:[]
                    }
                },
                template:`
                    <div>
                        <button @click = 'sendAjax'>发Get请求</button>
                        <div v-html = 'msg'></div>
                        <button @click = 'sendAjaxByPost'>发post请求</button>
                        {{datas}}
                    </div>
                `,
                methods:{
                    sendAjax(){
                        // 发送get请求
                        /* 带参数
                        this.$axios.get('/',{
                            params: {
                              id: 123,
                            }
                          })
                        this.$axios.post(/create,{
                              course_title: "Python",
                              course_price: "19.88"
                          })
                        */
                        this.$axios.get('/')
                        .then(res=>{
                            console.log(res.data);
                            console.log(typeof res.data);
                            this.msg = res.data;
                        })
                        .catch(err=>{
                            console.log(err);
                        })
                    },
                    sendAjaxByPost(){
                        // var _this = this;
                        var params = new URLSearchParams();
                        params.append('name','alex');
                        this.$axios.post('/create',params).then((res)=>{
                            // 解决this的指向问题,在vue中用函数 建议使用箭头函数
                            console.log(this);
                            console.log(res);
                            // 初学者容易犯的错
                            // _this.datas = res;
                            this.datas = res;
                        }).catch(err=>{
                            console.log(err);
                        })
                    }
                }
            }
    
            new Vue({
                el:"#app",
                data(){
                    return {
                    }
                },
                components:{
                    App
                },
                template:`<App />`
            })
        </script>
    </body>
    axios的默认配置和基础使用
        <script type="text/javascript">
            // 1.挂载 
            Vue.prototype.$axios = axios;
            // 2.配置公共的url
            axios.defaults.baseURL = 'http://127.0.0.1:8800';
            //发送多个并发请求
            function getCourse(){
              return this.$axios.get('/course/12')
                    }
            function getCourse_all() {
                      return this.$axios.get('/course')
                    }
            this.$axios.all([getCourse_all(),getCourse()])
                      .then().catch()
    
    
            methods: {
              init(){
                var that = this
                this.$axios.request({
                  url: that.$store.state.apiList.course,
                  method: 'get'
                }).then(function (data) {
                  if (data.status === 200){
                      that.courseList = data.data
                  }
                }).catch(function (reason) {
                  console.log(reason)
                })
              }
            },
        </script>    
    axios补充

    七、Vuex

    官方文档:点击 

    • vuex是一个专门为Vue.js设计的集中式状态管理架构。状态? 理解为在data中需要共享给其他组件使用的部分。

    • Vuex和单纯的全局对象有以下不同:
      - Vuex 的状态存储是响应式的。当vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会相应的得到高效更新。
      - 不能直接改变store中的状态。改变store中的状态的唯一途径就是显示的提交(commit)mutation。

    • 安装: -- npm install vuex

    // 为了方便维护,我们通常把在src下面新建一个store文件夹,然后在里面新建一个index.js
    // index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex);
    const store =  new Vuex.Store({
        // 五大将  state  getter  mutation  action  module
        /*
        1、state是保存我们data中需要共享的数据。
    
        由于Vuex的存储是响应式的,从store实例中读取状态的最简单的方式就是在计算属性中返回某个状态。
        通过:this.$store.state.count
    
        2、Getter会接收state作为其第一个参数,Getter也可以接收getters为第二个参数,
    
        有时候我们需要从store中的state中派生出一些状态,例如对数据进行简单的计算。
        并且很多组件都需要用到此方法,我们要么复制这个函数,要么抽取到一个公共函数,多处导入。
        我们vuex提供了更加方便的方法,getter ,它就像计算属性一样,getter的返回值会根据它的依赖被
        缓存起来,只有它的依赖发生改变时,才会重新计算。
    
        3、更改Vuex中的store中的状态的唯一方法是提交(commit) mutation。
    
        每个mutation都有一个字符串的事件类型(type),和一个回调函数handler。
        也就是说我们要触发mutation中定义的方法(type),然后才会执行这个方法(handler)。
        这个方法就是我们更改状态的地方,它会接收state为第一个参数,后面接收其他参数:
    
        Mutation需要遵守Vue的响应规则,
        既然vuex中的store中的状态是响应式的,那么当我们状态变更时,监视状态的vue组件也会更新。
        这就意味着vuex中的mutation也需要与使用vue一样遵守一些注意事项:
      -- 1,最好提前在你的store中初始化好所有的所需要的属性
      -- 2,当对象需要添加属性时,你应该使用
          --  Vue.set(obj, 'newProp', 123)
          --  以新对象代替老对象  state.obj = { ...state.obj, newProp: 123}
    
        4、Action 类似于 mutation,不同在于:
           Action 提交 mutation,而不是直接变更状态。
           Action 可以包含任意异步操作。
    
         使用dispatch 和 commit的区别在于,前者是异步操作,后者是同步操作,所以 一般情况下,推荐直接使用commit,
         即 this.$store.commit(commitType, payload),以防异步操作会带来的延迟问题。
    
        Mutation 必须是同步函数,在vue中,只有mutation才能正真改变VUEX stroe中的state。
        Action 提交的是 mutation,而不是直接变更状态。
        Action 可以包含任意异步操作。 个人觉得这个action的产生就是因为mutation 不能进行异步操作,如果有异步操作那么就用action 来提交mutation
        */
        state:{
            // 通过:this.$store.state.count  
            count:1
        },
        getters: {
            // 通过:this.$store.getters.my_func
            my_func: function (state) {
              return state.count * 2
            },
            // 通过 this.$store.getters.my_func_count
            my_func_count: function (state, getters) {
              return getters.my_func.length
            }
        },
        mutations:{
            // 同步
            // 需要通过 this.$store.commit('addCount', 10)
            addCount(state,val){
                //变更状态
                state.count+=val;
            },
            asyncHandler(state,val){
                state.count+=val;
            }
        },
        actions:{
            // 异步
            // 通过: this.$store.dispatch('addCount',3)
            addCount({commit},val){
                setTimeout(()=>{
                    commit('addCount',val)
                },2000)
            },
            asyncHandler({commit},val){
                commit('asyncHandler',val)
            }
        }
    });
    export default store;
    
    
    //src下面的main.js
    import Vue from 'vue'
    import App from './App'
    import store from './store'    //就是导入上面的index.js
    
    Vue.config.productionTip = false
    
    new Vue({
      el: '#app',
      store, //挂载
      components: { App },
      template: '<App/>'
    })
    Vuex的使用

    八、webpack

    官方文档:点击 

    webpack: 对前端中的资源编译打包、支持模块化es6的module

    webpack它里面很多loader

    webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。

    当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),

    其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。

    webpack (打包工具)把在后端开发的前端代码(JS/CSS/TypeScript...)打包成前端浏览器可以执行的JS代码,

    为什么要用webpack,因为按照后端模式开发写的JS,浏览器不认识。 用webpack打包代码成浏览器能认识的代码

    为什么要按照后端开发的方式写JS,因为前端不支持模块化,加载代码是同步的(CDN挂了,后面的代码都运行不了了,node.js支持模块化的开发。)

    1、webpack3

    • webpack是跑在Node.js环境下的,所以确定有node环境。

    • 安装方式:

      1. npm install webpack@3.12.0 -g 全局安装

      2. webpack  <要打包文件>  <打包后文件>  全局这种方式进行打包
      3. cd 目录

      4. npm install webpack@3.12.0 -D  在项目下 npm init 后再下载webpack就是局部安装

      5. 如果在项目中配置了webpack.config.js 那么在终端中直接输入webpack,默认识别webpack.config.js项目配置文件

      6. 自定义命令在package.json 文件的 scripts下面自定义 npm run dev ,npm run build

    {
      "name": "02-module_deep",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "dev": "webpack-dev-server  --open --hot --inline   --config   ./webpack.dev.config.js",
        "build": "webpack --config  ./webpack.prod.config.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "css-loader": "^1.0.0",
        "html-webpack-plugin": "^3.2.0",
        "style-loader": "^0.23.1",
        "vue-loader": "^14.1.1",
        "vue-template-compiler": "^2.5.17",
        "webpack": "^3.12.0",
        "webpack-dev-server": "^2.9.0"
      },
      "dependencies": {
        "vue": "^2.5.17"
      }
    }
    package.json
    //自带nodejs环境  cmd规范
    // module.exports = {}
    // var a = require('./webpack.config.js')
    
    // 如果在项目中配置了webpack.config.js 那么在终端中直接输入webpack,默认识别webpack.config.js项目配置文件
    module.exports = {
        // 入口
        entry:{
            "main":'./main.js'
        },
        // 出口
        output:{
            filename:'./bundle.js'
        },
        watch:true
    }
    webpack.config.js
    //自带nodejs环境  cmd规范
    // module.exports = {}
    // var a = require('./webpack.config.js')
    
    // nodejs中内容模块
    var path = require('path');
    var HtmlWebpackPlugin = require('html-webpack-plugin');
    // html-webpack-plugin
    // 如果在项目中配置了webpack.config.js 那么在终端中直接输入webpack,默认识别webpack.config.js项目配置文件
    module.exports = {
        // 入口
        entry:{
            "main":'./src/main.js'
        },
        // 出口
        output:{
            path:path.resolve('./dist'),//相对转绝对
            filename:'./bundle.js'
        },
        // 模块中的loader  loader加载器 它能对css、json png jpg mp3 mp4 es6的js代码
        module:{
            loaders:[
                {
                    test:/\.css$/,
                    loader:'style-loader!css-loader'
                },
                {
                    test:/\.vue$/,
                    loader:'vue-loader'
                }
            ]
        },
        watch:true,
        // 插件
        plugins:[
            new HtmlWebpackPlugin({
                template:'./index.html',//参照物
            })
        ]
    }
    webpack.dev.config.js
    //自带nodejs环境  cmd规范
    // module.exports = {}
    // var a = require('./webpack.config.js')
    
    // nodejs中内容模块
    var path = require('path');
    var HtmlWebpackPlugin = require('html-webpack-plugin');
    // html-webpack-plugin
    // 如果在项目中配置了webpack.config.js 那么在终端中直接输入webpack,默认识别webpack.config.js项目配置文件
    module.exports = {
        // 入口
        entry:{
            "main":'./src/main.js'
        },
        // 出口
        output:{
            path:path.resolve('./dist'),//相对转绝对
            filename:'./bundle.js'
        },
        // 模块中的loader  loader加载器 它能对css、json png jpg mp3 mp4 es6的js代码
        module:{
            loaders:[
                {
                    test:/\.css$/,
                    loader:'style-loader!css-loader'
                }
            ]
        },
        // 插件
        plugins:[
            new HtmlWebpackPlugin({
                template:'./index.html',//参照物
            })
        ]
    }
    webpack.prod.config.js

    2、webpack4

    • webpack不在单独使用,需要webpack-cli

    • 安装方式:

      1. npm install webpack webpack-cli -g -D 全局安装

      2. npm install webpack webpack-cli -D 局部安装

    • 增加了模式区分 (development, production):

      1. webpack --mode development/production 进行模式切换

      2. development 开发者模式 打包默认不压缩代码

      3. production 生产者模式 上线时使用,压缩代码。 默认是这个模式

    • 固定入口目录为src,与入口默认文件index.js,打包后文件在新增的dist目录下:

      1. 当只有一个入口文件也就是src/index.js时,无需增加webpack.config.js

    vue之vue-cookies

    安装:

    npm install vue-cookies --save

    使用:

    import Vue from 'Vue'
    import VueCookies from 'vue-cookies'
    Vue.use(VueCookies)

    Api:

      设置 cookie:

    this.$cookies.set(keyName, time)   //return this

      获取cookie

    this.$cookies.get(keyName)       // return value   

      删除 cookie

    this.$cookies.remove(keyName)   // return  false or true , warning: next version return this; use isKey(keyname) return true/false,please

      查看一个cookie是否存在(通过keyName

    this.$cookies.isKey(keyName)        // return false or true

      获取所有cookie名称

    this.$cookies.keys()  // return a array
  • 相关阅读:
    第零次作业
    第一本书的学习笔记
    第一次作业
    第零次作业
    第一周作业
    第零次作业回复
    第零次作业
    第一周作业
    第0次作业
    第一次作业
  • 原文地址:https://www.cnblogs.com/bubu99/p/10454351.html
Copyright © 2011-2022 走看看