Vue知识点总结-DX的笔记

简介

什么是Vue

  • Vue是一个构建用户界面的前端框架
  • 是一个轻量级的MVVM
  • 数据驱动和组件化的前端开发

mvvm

  • MVVM(Model-View-ViewModel),其实就是所谓的数据的双向绑定mvc

  • Model:对应数据层的域模型,它主要做域模型的同步。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在模型层间关系里,它主要用于抽象出 ViewModel 中视图的 Model。个人理解:后端提供API,后端服务架构是 控制器+数据模型 或者 纯控制器。

  • View:View是作为视图模板,用于定义结构、布局。它自己不处理数据,只是将ViewModel中的数据展现出来。此外为了和ViewModel产生关联,那么还需要做的就是数据绑定的声明,指令的声明,事件绑定的声明。ViewModel和View之间是双向绑定,意思就是说ViewModel的变化能够反映到View中,View的变化也能够改变ViewModel的数据值。

  • ViewModel:ViewModel起着连接View和Model的作用,同时用于处理View中的逻辑。在MVC框架中,视图模型通过调用模型中的方法与模型进行交互,然而在MVVM中View和Model并没有直接的关系,在MVVM中,ViewModel从Model获取数据,然后应用到View中。个人理解:Web前端的webserver对View进行双向绑定渲染。

    整个MVVM实际上实现了前后端分离,通过api来实现前后端交互,前端通过纯js或者双向绑定框架来渲染页面。

开发准备

  • 安装vue.js插件
  • 新建web项目
  • 添加vue.js
  • 创建html

基础知识

初识Vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--插值表达式:由Vue对象解析数据,从model中取出数据,并渲染到指定页面位置-->
    {{message}}
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    //创建vue js的核心对象,核心Vue对象就是vm
    var vm = new Vue({
        //配置vm对象管理的html
        el: '#app',
        //data配置就是数据模型M,它本身是一个字面量对象
        //其中字面量对象属性名即数据名,字面量对象的属性值即数据值
        data: {
            message: 'hello vue',
            num:20,
            flage:true,
            list:['aa','bb','dd'],
            obj:{
                name: 'xxx',
                age:24
            }
        }
    });
</script>
</body>
</html>

数据绑定

  • vue中的数据显示到界面
  • v-text v-html
<div id="app">
    <!--
    指令:html中的动态属性,所有的指令都是以v-开头的
    v-text 将数据从model取出,并渲染到指定标签中。替换特殊符号
    v-html 将数据从model取出,并渲染到指定标签中。原样展示
    -->
    <h1 v-text="message"</h1>
    <p v-text="msg"></p>
    <h1 v-html="message"></h1>
    <p v-html="msg"></p>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vue',
            msg:'<a href="#">超链接</a>'
        }
    });
</script>

属性绑定

  • v-bind:将vue变量绑定到属性上
  • v-bind可以省略为‘ :’
<div id="app">
    <!--
    属性绑定指令
    v-bind:HTML原生属性名称="data中的数据名称"
    简化
    v-bind:  ===>  :
    -->
    <h1 title="你好">{{message}}</h1>
    <h1 v-bind:title="msg">{{message}}</h1>
    <p :title="msg">{{message}}</p>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vue',
            msg:"你好啊"
        }
    })
</script>

事件绑定

  • v-on:事件名=“函数名”
  • 函数简化写法 v-on --> @
<div id="app">
    <!--
    事件绑定指令
    v-on:事件名称="函数名称"
    事件名称 click,focus,blur,change,dbclick,load...
    简化
    v-on:  ===>  @
    -->
    <p><button type="button" v-on:click="myFun1">按键1</button></p>
    <p><button type="button" @click="myFun2">按键2</button></p>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vue'
        },
        //事件函数
        method: {
            myFun1: function () {
                console.log("函数1执行了。。。")
            },
            //简化
            myFun2() {
                //在函数中可以使用data中的数据,但是必须以this(vue对象)调用
                console.log("函数2执行了。。。" + this.message);
            }
        }
    });
</script>

双向绑定

  • 用法

    • v-model:仅用于表单元素上
    • 数据双向绑定指令:v-model=“data中的数据”
    • 仅能用在表单元素上,文本框、单选按钮、复选框、下拉列表、多行文本框…
  • vue对象

    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello vue',
                genderVal: 'female',
                login: false,
                hobbys: ['篮球v', '排球v'],
                edu: '',
                array: []
            }
        });
    </script>
    
  • 文本框 (单行 多行)

    <h1>文本框</h1>
    <p><input type="text" v-model="message"></p>
    <p><textarea cols="30" rows="10" v-model="message"></textarea></p>
    <h1>date中的数据:{{message}}</h1>
    
  • 单选按钮

    <h1>单选按钮</h1>
    <p>
        <label><input type="radio" name="gender" value="male" v-model="genderVal">男性</label>
        <label><input type="radio" name="gender" value="female" v-model="genderVal">女性</label>
    </p>
    <p>date中的数据:{{genderVal}}</p>
    
  • 复选框

    <h1>复选框</h1>
    <!--
    两种用法:
    1.单用:绑定数据类型为boolean
    2.多用:绑定数据类型为数组
    -->
    <p>
        <label><input type="checkbox" v-model="login">十天免登录</label>
    </p>
    <p>
        <label><input type="checkbox" name="hobby" value="足球v" v-model="hobbys">足球</label>
        <label><input type="checkbox" name="hobby" value="篮球v" v-model="hobbys">篮球</label>
        <label><input type="checkbox" name="hobby" value="乒乓球v" v-model="hobbys">乒乓球</label>
        <label><input type="checkbox" name="hobby" value="羽毛球v" v-model="hobbys">羽毛球</label>
        <label><input type="checkbox" name="hobby" value="排球v" v-model="hobbys">排球</label>
    </p>
    <p>data中的数据:{{hobbys}}</p>
    
  • 下拉列表

    • 单选式
    • 多选式
    <h1>下拉列表</h1>
    <p>
        <select v-model="edu">
            <option value="1">幼儿园</option>
            <option value="2">小学</option>
            <option value="3">中学</option>
            <option value="4">高中</option>
            <option value="5">大学</option>
        </select>
    </p>
    <p>data中的数据:{{edu}}</p>
    <p>
        <select multiple v-model="array">
            <option value="aa">选项1</option>
            <option value="bb">选项2</option>
            <option value="cc">选项3</option>
            <option value="dd">选项4</option>
            <option value="ee">选项5</option>
        </select>
    </p>
    <p>data中的数据:{{array}}</p>
    

条件渲染

  • v-if
  • v-else
  • v-else-if
  • v-show
<div id="app">
    <p><button type="button" @click="islLogin=!islLogin">登录与退出</button></p>
    <div v-if="isLogin">当前登陆用户:{{username}}</div>
    <div v-else>请登陆</div>
    <p>data中的数据:{{isLogin}}</p>
    <hr>
    <div>
        <div v-if="gender == '1'">男性</div>
        <div v-else-if="gender == '2'">女性</div>
        <div v-else-if="gender == '3'">保密</div>
        <div v-else>有误</div>
    </div>
    <hr>
    <!--
    v-if 条件成立时渲染元素,条件不成立时不渲染元素
    v-show 无论条件成立与否都渲染元素,通过css(display:none)来隐藏此标签
    -->
    <div v-show="isLogin">v-show指令</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vue',
            username: '张三',
            isLogin: true,
            gender: '5'
        }
    })
</script>
  • 列表渲染

    • v-for of/in
    • of / in
    • index 索引
    • :key 排序条件,一般用id
    • 遍历对象
    <div id="app">
        <ul>
            <li v-for="name in nameList">{{name}}</li>
        </ul>
        <hr>
        <ul>
            <li v-for="name of nameList">{{name}}</li>
        </ul>
        <hr>
        <ul>
            <li v-for="(name, index) of nameList">{{name}}--{{index}}</li>
        </ul>
        <hr>
        <ul>
            <li v-for="(name, index) of nameList" :key="index">{{name}}--{{index}}</li>
        </ul>
        <hr>
        <table border="1" width="500" align="center">
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>成绩</th>
            </tr>
            <tr v-for="student in studentList" :key="student.id">
                <td>{{student.id}}</td>
                <td v-text="student.name"></td>
                <td v-text="student.age"></td>
                <td v-text="student.score"></td>
            </tr>
        </table>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello vuejs',
                nameList: ['张三', '李四', '王五', '赵柳', '小七', '大巴'],
                studentList: [
                    {id: 101, name: '小明', age: 20, score: 90},
                    {id: 102, name: '小红', age: 21, score: 87},
                    {id: 103, name: '小张', age: 23, score: 76},
                    {id: 104, name: '小王', age: 20, score: 69},
                    {id: 105, name: '小李', age: 22, score: 100}
                ]
            }
        });
    </script>
    

计算属性

  • 作用:处理data中的数据
  • 计算属性的函数使用与data中的属性一致
<div id="app">
    <p>{{message}}</p>
    <!--复杂运行尽量不在插值表达式中进行-->
    <p>{{message.split(' ').reverse().join(' ')}}</p>
    <!--计算属性的使用方式:计算属性的函数使用与data中的属性一致-->
    <p>{{msg}}</p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        //计算属性: 处理data中的数据
        computed: {
            msg: function (){
                var array = this.message.split(' ');
                array.reverse();
                //计算属性的函数必须有返回值
                return array.join('$$');
            }
        }
    });
</script>

监听器

  • 作用:监听data数据的变化
  • 函数名称与数据名保持一致
<div id="app">
    <p>姓名:<input type="text" v-model="name"></p>
    <p>{{name}}</p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs',
            name: ''
        },
        //侦听器:监听data数据的变化
        watch: {
            /**
             * 侦听函数
             * 名称:与侦听的数据名一致
             * 参数:1数据变化之后的值 2数据变化之前的值
             */
            name: function (newVal, oldVal){
                console.log('新数据', newVal);
                console.log('老数据', oldVal);
            }
        }
    });
</script>

生命周期

  • 钩子函数:生命周期的某个阶段会执行的函数

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TqWeHOY9-1661774468138)(E:\JAVA\DLJD\我的笔记\myImages\Vue知识点总结\lifecycle.16e4c08e.png)]

  • <div id="app">
        <p>{{ message }}</p>
        <p><button type="button" @click="message += '2022'">按钮</button></p>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello vuejs'
            },
            methods: {
                myFun(){
                    console.log('myFun....')
                }
            },
            //生命周期钩子函数
            beforeCreate(){
                //vue对象已经创建,但是data数据与method函数没有初始化
                console.log('beforeCreate', this.message);
                // this.myFun();
            },
            created(){
                //data数据与method函数已经初始化完成
                console.log('created', this.message);
                this.myFun();
            },
            beforeMount(){
                //mount挂载:解析模板(动态的内容被替换成静态数据)
                //模板没有被解析
                var dom = document.querySelector('#app > p');
                console.log('beforeMount', dom.innerHTML);
            },
            mounted(){
                //模板已经解析完成
                var dom = document.querySelector('#app > p');
                console.log('mounted', dom.innerHTML);
            },
            beforeUpdate(){
                //vue对象运行期间,当data数据变化时
                //data数据已经变化,但没有渲染到页面
                console.log('beforeUpdate-data', this.message);
                var dom = document.querySelector('#app > p');
                console.log('beforeUpdate-html', dom.innerHTML);
            },
            updated(){
                //data数据已经变化,也渲染到页面
                console.log('updated-data', this.message);
                var dom = document.querySelector('#app > p');
                console.log('updated-html', dom.innerHTML);
            },
            beforeDestroy(){
            },
            destroyed(){
            }
        });
    </script>
    

样式绑定

  • Class与
  • 样式类
  • 动态样式类
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        .red {
            color: red;
        }
        .size {
            font-size: 25px;
        }
        .back {
            background-color: green;
        }
    </style>
</head>
<body>
    <div id="app">
        <h2>内联样式</h2>
        <div style="color: red; font-size: 20px; background-color: green;">{{message}}</div>
        <h2>样式类</h2>
        <div class="red size back">{{message}}</div>
        <h2>对象</h2>
        <div :class="{red: true, size: true, back: false}">{{message}}</div>
        <div :class="obj">{{message}}</div>
        <h2>数组</h2>
        <div :class="['red', 'size', flag?'back':'']">{{message}}</div>
        <p><button type="button" @click="flag = !flag">按钮</button></p>
    </div>
    <script type="text/javascript" src="./js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello vuejs',
                obj: {
                    red: true,
                    size: true,
                    back: true
                },
                flag: true
            }
        });
    </script>
</body>
</html>

过滤器

  • 作用:处理数据

  • 全局定义

    Vue.filter(过滤器名,过滤函数(源数据,参数1,参数2...{})
    
  • 局部定义

    var vm = new Vue({
        ...
        filters: {
            过滤函数名: (source){
                return source+'局部过滤器'
            }
        }
    });
    
<div id="app">
    <p>{{ message }}</p>
    <p>{{ message | msgFormat1 }}</p>
    <p>{{ message | msgFormat2('夏向向') }}</p>
    <p>{{ message | msgFormat3('小王','小盼') }}</p>
    <p>{{ message | msgFormat4 }}</p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    /**
     * 过滤器:处理数据,数据格式化
     * 1.全局定义
     * Vue.filter(过滤器名,过滤函数(源数据,参数1,参数2...){})
     */
    Vue.filter('msgFormat1', function (source) {
        //过滤器返回值,处理数据后的结果
        //只改一个
        // return source.replace('vue', 'java');
        //改所有匹配的(区分大小写)
        // return source.replace(/vue/g, 'java');
        //改所有匹配的(不区分大小写)
        return source.replace(/vue/ig, 'java');
    });
    //传入一个或多个参数
    Vue.filter('msgFormat2',function (source,param) {
        return source.replace(/vue/ig, param);
    });
    Vue.filter('msgFormat3',function (source,param1,param2) {
        return source.replace(/vue/ig, param1+" and "+param2);
    });

    var vm = new Vue({
        el: '#app',
        data: {
            message: '我爱vue,vue爱我,Vue真牛!'
        },
        //2.局部过滤器
        filters: {
            //过滤函数
            msgFormat4(source){
                return source+'局部过滤器'
            }
        }
    });
</script>

组件

初识组件

  • 可复用

全局组件

  • Vue.component(组件名称, 组件配置);
    
  • 三种使用方式

<div id="app">
    <!--组件使用:以html标签的形式,组件名为html标签名-->
    <login></login>
    <login></login>
    <register></register>
    <tabs></tabs>
</div>
<!--方式三:使用组件模板-->
<template id="tabs">
    <div>
        <table border="1" width="300">
            <tr>
                <th>表头1</th>
                <th>表头2</th>
                <th>表头3</th>
            </tr>
            <tr>
                <td>数据11</td>
                <td>数据12</td>
                <td>数据13</td>
            </tr>
            <tr>
                <td>数据21</td>
                <td>数据22</td>
                <td>数据23</td>
            </tr>
        </table>
    </div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    /**
     * 全局组件
     * Vue.component(组件名称, 组件配置);
     */
    //方式一
    Vue.component('login', {
        //html模板
        template: '<div><h1>用户登录组件</h1></div>'
    });
    //方式二 (不推荐,麻烦)
    var register = Vue.extend({
        template: '<div><h1>用户注册组件</h1></div>'
    });
    Vue.component('register', register);
    //方式三:使用组件模板
    Vue.component('tabs', {
        template: '#tabs'
    });
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        }
    });
</script>

局部组件

  • 写好函数,再把函数注册到组件中
<div id="app">
    <pageheader></pageheader>
    <pagefooter></pagefooter>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    var pageheader = {
        template: '<div><h1>页面顶部组件</h1></div>'
    };
    var pagefooter = {
        template: '<div><h1>页面底部组件</h1></div>'
    };
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        //注册局部组件
        components: {
            //字面量对象
            //属性名为组件的名称,属性值为组件的配置
            pageheader: pageheader,
            //字面量对象的简化写法(属性名与属性值一致时可简化)
            pagefooter
        }
    });
</script>

组件命名注意事项

  • 1.不能与Html标签名冲突
  • 2.名称为多个单词组成
    • 中划线间隔:my-main,list-nav,user-add
    • 驼峰:myMain, listNav, userAdd, StudentList
    • 注意:组件在使用时,必须使用中划线
  • 3.组件的html部分,仅能有一个根标签,仅会渲染第一个标签中的内容
<div id="app">
    <my-main></my-main>
<!--    无效写法: <MyMain1></MyMain1> -->
    <my-main1></my-main1>
    <mymain2></mymain2>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    Vue.component('my-main',{
        template: '<div><h1>使用-命名:my-main</h1></div>'
    }),
    Vue.component('MyMain1',{
        template: '<div><h1>使用驼峰命名:MyMain1</h1></div>'
    }),
    Vue.component('mymain2',{
        template: '<div>第一个div</div><div>第二个div</div>'
    })
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        }
    });
</script>

组件中的data

  • data数据可以被模板组件调用
  • 模板组件还可以调用事件函数
<div id="app">
    <list-nav></list-nav>
    <list-nav></list-nav>
    <list-nav></list-nav>
</div>
<template id="listNav">
    <div>
        <p><button type="button" @click="changeAge">按钮</button></p>
        <ul>
            <li><a href="#">首页--{{msg}}</a></li>
            <li><a href="#">新闻--{{username}}</a></li>
            <li><a href="#">用户--{{age}}</a></li>
            <li><a href="#">关于--{{address}}</a></li>
        </ul>
    </div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    /**
     * 组件的数据与函数
     * data: 数据
     * 组件中的数据data是一个函数,并且函数有返回值,返回值为字面量对象(此字面量对象为数据)
     * 好处:
     * 1.数据可以拥有自己的过程代码(对数据进行初步处理)
     * 2.组件中的数据在组件复用时,每个组件实例中的数据是隔离(相互不影响)
     */
    var listNav={
        template: '#listNav',
        data() {
            //数据函数体:初步数据处理
            return {
                msg: '组件',
                username: 'zhangsan',
                age: 24,
                address: '北京'
            }
        },
        //组件中的事件函数
        methods: {
            changeAge(){
                this.age++;
            }
        }
    }

    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        components: {
            listNav
        }
    });
</script>

组件传值

父传子
  • 父组件可以将属性和方法传给子组件

  • 在父组件中绑定子组件属性,和传递方法

    <sub-component v-bind:msg="message" v-on:demo="test"></sub-component>
    
<div id="app">
    <h2>父组件中的数据:{{message}}</h2>
    <p><button type="button" @click="message+='666'">修改父组件中的数据</button></p>
    <!--传
    在父组件中使用子组件时通过子组件标签的属性进行传递
    v-bind:子组件内部接收数据的变量名称="父组件中的数据"

    传递函数:
    v-on:在子组件内调用函数名称="父组件中的函数名"
    -->
<!--        <sub-component v-bind:msg="message" v-on:demo="test"></sub-component>-->
    <sub-component :msg="message" @demo="test"></sub-component>
</div>
<template id="sub">
    <div>
        <h2>子组件中的数据:{{username}}</h2>
        <h2>子组件接收父组件传递的数据: {{msg}}</h2>
        <p><button type="button" @click="myFun">调用父组件中的函数</button></p>
    </div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
    //子组件
    var subComponent={
        template: '#sub',
        data() {
            return{
                username:'tom'
            }
        },
        /**
         * 接收
         * 通过props配置来接收父组件传递过来的数据
         *
         * props的值
         * 1.数组: 数组中存放就是接收数据的变量名称
         * 2.对象:属性名称即变量名称,其值为数据类型
         */
        // props: ['msg']
        props: {
            msg: String
        },
        methods: {
            myFun(){
                /**
                 * 在子组件中通过触发调用,来调用父组件中传递过来的函数
                 * $emit('调用的函数名', 函数参数)
                 */
                // this.demo()
                this.$emit('demo', 'hello');
            }
        }
    };
    //父组件
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        methods: {
            test(param){
                console.log('test函数执行了...'+param)
            }
        },
        components: {
            subComponent
        }
    });
</script>
子传父
  • 子组件将属性和方法传递给父组件

  • 1.向子组件传数据,添加一个关键字(修饰符)

    <sub-component :msg.sync="message" @damo="test"></sub-component>
    
  • 2.通过触发调用函数,向父组件传递数据

    //$emit('update:props中的变量名称', 传递的数据值);
    this.$emit('update:msg','你好vuejs');
    
<div id="app">
    <h2>父组件中的数据:{{message}}</h2>
    <p><button type="button" @click="message += '666'">修改父组件中的数据</button></p>
    上面是父组件<hr color="red">下面是子组件
    <!--1.向子组件传数据,添加一个关键字(修饰符)-->
    <sub-component :msg.sync="message" @damo="test"></sub-component>
</div>
<template id="sub">
    <div>
        <h2>子组件中的数据: {{username}}</h2>
        <h2>子组件接收父组件传递的数据: {{msg}}</h2>
        <p><button type="button" @click="myFun">调用父组件中的函数</button></p>
        <p><button type="button" @click="msg += '123'">修改子组件中的props</button></p>
        <p><button type="button" @click="changeMsg">子传父的方法</button></p>
    </div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">

    //子组件
    var subComponent={
        template: '#sub',
        data() {
            return {
                username: 'xxx'
            }
        },
        /**
         * 父组件中的数据变化,子组件中的数据也会变化
         * 但是,如果子组件中的props数据变化,父组件中的数据是不会变化。数据传递为单向, 父 --> 子
         * 注意: porps的数据是不允许修改的,仅允许读取
         */
        props: {
            msg: String
        },
        methods:{
            myFun() {
                this.$emit('demo', 'hello')
            },
            changeMsg(){
                /**
                 * 2.通过触发调用函数,向父组件传递数据
                 * $emit('update:props中的变量名称', 传递的数据值);
                 */
                this.$emit('update:msg','你好vuejs');
            }
        }
    };
    //父组件
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        methods: {
            test(param){
                console.log('test函数执行了....' + param)
            }
        },
        components:{
            subComponent
        }
    });
</script>

单文件组件

<template>
  <!--组件中的html部分-->
  <div></div>
</template>

<script>
//组件的js代码区域
export default {
  data(){
    return {}
  },
  methods: {},
  props: {},
  watch: {},
  computed: {},
  components: {},
  mounted(){}
}
</script>

<style scoped>
/**
css代码区域
注意:样式是整个项目中所有的.vue文件共享
    scoped属性表示当前组件中的样式为私有样式
 */
.demo{
  font-size: 30px;
}
</style>

路由

初识路由

  • 作用:用于切换组件、组件之间数据传递
  • 创建项目后,导入vue-router.js文件
<div id="app">
    <h1>欢迎使用路由</h1>
    <!--
    4.路由的使用
    <router-link>标签,路由导航标签,它会被解析为一个超链接
    <router-view>标签,路由出口,通过点击导航标签,组件渲染的位置
    -->
    <router-link to="/login">登录</router-link>
    <router-link to="/reg">注册</router-link>
    <!--组件渲染,既展示路由指定的组件-->
    <router-view></router-view>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
    //1.定义组件
    var login = {template: '<div><h1>登录组件</h1></div>'};
    var register = {template: '<div><h1>注册组件</h1></div>'};
    //2.定义路由
    //路由作用:切换组件,组件之间的数据传递
    var router = new VueRouter({
        //路由模式,默认hash,历史模式history
        // mode: 'history',
        //路由列表: 路径与组件的对应
        routes: [
            /**
             * 单个路由对象
             * path: 路由路径字符串,值必须以斜杠开头
             */
            {path: '/login', component: login},
            {path: '/reg', component: register}
        ]
    });
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        //3.在vue对象中设置路由
        router
    });
</script>

路由传参

  • 路径拼接传参
  • 路径传参
<div id="app">
    <h1>欢迎使用路由</h1>
    <!--路径拼接传参-->
    <router-link to="/login?username=tom&password=123">登录</router-link>
    <!--路径传参-->
    <router-link to="/reg/101/zhangsan">注册</router-link>
    <router-view></router-view>
</div>
<template id="login">
    <div>
        <h1>登录组件</h1>
        <!--
        在路由中两种对象
        $router对象   表示全局路由对象,就是VueRouter对象本身
        $route对象    表示当前路由,通过路径导航到组件对应的路由对象

        $route对象,在当前路由对象中有一个属性query,记录所有路径拼接传参的数据
        -->
        <p>{{$route.query}}</p>
        <p>{{$route.query.username}}</p>
        <p>{{$route.query.password}}</p>
    </div>
</template>
<template id="reg">
    <div>
        <!--
        $route对象,在当前路由对象中有一个属性params,记录所有路径传参的数据
        -->
        <h1>注册组件</h1>
        <p>{{$route.params}}</p>
        <p>{{$route.params.id}}</p>
        <p>{{$route.params.username}}</p>
    </div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
    //1.定义组件
    var login = {template: '#login'};
    var register = {template: '#reg'};
    //2.定义路由
    var router = new VueRouter({
        routes: [
            {path: '/login', component: login},
            {path: '/reg/:id/:username', component: register}
        ]
    });
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        //3.在vue对象中设置路由
        router
    });
</script>

编程式导航

  • 在路由导航的同时,导航到指定的历史记录
  • 两种传参方式
<div id="app">
    <h1>欢迎使用路由</h1>
    <h2>声明式导航</h2>
    <p>
        <router-link to="/login">登录</router-link>
        <router-link to="/reg">注册</router-link>
        <router-link to="/user">用户</router-link>
        <router-link to="/emp">员工</router-link>
    </p>
    <h2>编程式导航</h2>
    <p>
        <button type="button" @click="doRedirect('login')">登录按钮</button>
        <button type="button" @click="doRedirect('reg')">注册按钮</button>
        <button type="button" @click="doRedirect('user')">用户按钮</button>
        <button type="button" @click="doRedirect('emp')">员工按钮</button>
    </p>
    <p>
        <button type="button" @click="doBackward">后退</button>
        <button type="button" @click="doForward">前进</button>
    </p>
    <router-view></router-view>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
    //1.定义组件
    var login = {template: '<div><h1>登录组件{{$route.query}}</h1></div>'};
    var register = {template: '<div><h1>注册组件{{$route.query}}</h1></div>'};
    var user = {template: '<div><h1>用户组件{{$route.params}}</h1></div>'};
    var emp = {template: '<div><h1>员工组件{{$route.params}}</h1></div>'};
    //2.定义路由
    //路由作用:切换组件,组件之间的数据传递
    var router = new VueRouter({
        routes: [
            //name: 路径的名称
            {path: '/login', name: 'login', component: login},
            {path: '/reg', name: 'reg', component: register},
            {path: '/user', name: 'user', component: user},
            {path: '/emp', name: 'emp', component: emp}
        ]
    });
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        //3.在vue对象中设置路由
        router,
        methods: {
            /**
             * 编程式导航
             * $router 全局路由对象
             *
             * push() 在路由导航的同时,在历史列表中添加一个新的历史记录
             * replace() 在路由导航的同时,在历史列表中替换最后一个历史
             * go() 导航到指定的历史记录
             */
            doRedirect(name){
                // this.$router.replace('/'+name);
                /*两种传参方式*/
                //1.query
                // this.$router.push({
                //     path: '/' + name,
                //     query: {
                //         id: 10,
                //         name: '张三'
                //     }
                // });
                //2.params
                //编程式导航通过params传递参数时,不能使用路径进行导航,应该使用路径名称
                this.$router.push({
                    // path: '/'+name,
                    name: name,
                    params: {
                        id: 20,
                        name: '李四'
                    }
                });
            },
            doForward(){
                this.$router.go(1);
            },
            doBackward(){
                this.$router.go(-1);
            }
        }
    });
</script>

嵌套路由

  • 定义路由时,使用children属性,可以定义子路由
  • 子路由的路径写在父路径的后面
<div id="app">
    <h1>欢迎使用路由</h1>
    <p>
        <router-link to="/login">登录</router-link>
        <router-link to="/main">主页</router-link>
    </p>
    <!--路由出口:提供给一级路由-->
    <router-view></router-view>
</div>
<template id="main">
    <div>
        <h2>导航</h2>
        <p>
            <router-link to="/main/user">用户</router-link>
            <router-link to="/main/emp">员工</router-link>
            <router-link to="/main/dept">部门</router-link>
        </p>
        <!--路由出口:提供给嵌套路由-->
        <router-view></router-view>
    </div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
    //1.定义组件
    var login = {template: '<div><h1>登录组件</h1></div>'};
    var main = {template: '#main'};
    var user = {template: '<div><h1>用户组件</h1></div>'};
    var emp = {template: '<div><h1>员工组件</h1></div>'};
    var dept = {template: '<div><h1>部门组件</h1></div>'};
    //2.定义路由
    var router = new VueRouter({
        routes: [
            {path: '/login', name: 'login', component: login},
            {
                path: '/main',
                name: 'main',
                component: main,
                //嵌套路由,子路由列表
                children: [
                    //嵌套路由:1.相对路径:不以斜杠开头(父路径+子路由路径) 2绝对路径:以斜杠开头
                    // 如果子路由路径为user,真实路径为/main/user
                    // 如果子路由路径为/user,真实路径为/user
                    {path: 'user', name: 'user', component: user},
                    {path: 'emp', name: 'emp', component: emp},
                    {path: 'dept', name: 'dept', component: dept}
                ]
            }
        ]
    });
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'hello vuejs'
        },
        router
    });
</script>

Node.js

简介

  • Node.js 是一个开源和跨平台的 JavaScript 运行时环境

  • 作用:以前需要把 js 代码写到html文件中执行,现在可以直接执行了

    #例如执行 hello.js
    node hello.js
    

npm

  • Nodejs package managerment

  • npm是node提供的一个包管理系统,类似于maven

  • 通过npm去安装依赖包,就不需要在页面上使用script标签引入了

  • 建立 node.js 项目

    npm init
    
  • 建立完项目会生成package.json文件

    • 这个文件是项目的描述文件
    • 里面不能写注释
  • 脚本:json文件中的 scripts

    ...
    "scripts": {
        "test": "echo 'hello nodeJs'"
    },
    ...
    
    #运行脚本
    npm run test
    
  • 管理当前项目依赖:dependencies

    • 如使用命令

      npm install md5
      
    • 生成node_modiles文件夹,此文件夹存放第三方的依赖

  • 命令

    #配置淘宝下载源
    #设置
    npm config set registry https://registry.npm.taobao.org
    #查看
    npm config get registry
    
    #根据package.json文件中依赖下载当前项目中所有的依赖
    npm install
    #简化写法
    npm i
    
    #安装指定包
    npm install 包名
    #下载指定版本
    npm install 包名@版本号
    #搜包的网站:https://www.npmjs.com/
    
    #安装指定包到dev环境
    npm install --save-dev 包名
    #也可简写为
    npm i -D 包名
    npm i -D axios@0.26.1
    
    #安装到全局(非当前项目目录,在所有的项目中都可使用)
    npm install -g 包名
    #npm镜像加速配置
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    #查看版本
    nnpm -v
    
    #卸载
    npm uninstall 包名
    npm uninstall -g 包名
    
    #设置全局安装目录,注意:需要修改环境变量
    #查看
    npm config get prefix
    #设置
    npm config set prefix 位置
    npm config set prefix D:\RuanJian\nodejs_cache\npm
    
    #设置npm缓存目录
    #查看
    npm config get cache
    #设置
    npm config set cache 位置
    

    dependencies:开发与发布环境都可使用的依赖

    devDependencies:开发环境使用的依赖

搭建vuejs项目

vue-cli

  • vue-cli(vue脚手架),它是一个专门为单页面应用快速搭建繁杂的脚手架

  • 它可以轻松的创建新的应用程序而且可用于自动生成vue和webpack的项目模板。

  • vue-cli是有Vue提供的一个官方cli,专门为单页面应用快速搭建繁杂的脚手架。

  • 它是用于自动生成vue.js+webpack的项目模板

  • 安装vue-cli脚手架

    npm install -g @vue/cli@4.5.19
    
  • 执行命令配置项目

    vue create 项目名称
    #使用图形化界面创建项目
    vue ui
    
  • 打开npm工具窗口:package.json右键—>show npm Spripts

包与模块

  • 包:前端项目

  • 模块:一个独立的js文件(类似于Java中类)

模块的导出
  • demo / user.js

    //模块:定义的变量和函数都是私有的
    var id=20;
    var username='xxx';
    var password='13413';
    var login=function (){
        console.log('登录函数');
    }
    
    //导出:普通导出,可以导出多个变量和函数,也可以多次导出
    export {id,username,password,login}
    
  • student / index.js

    var stu = {
        id: 10,
        name: '张三',
        age: 21,
        address: '上海'
    }
    
    //导出默认:仅能导出一次,一次仅能有一个对象
    export default stu;
    
模块的导入
  • main.js

    //启动项目即被执行
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    //导入user.js导出的文件
    import {id,username,password,login} from "@/demo/user";
    // import {id,username,password,login} from "./demo/user";
    //导入student
    import student from './student'
    
    //打印导入的值
    console.log("用户ID", id);
    console.log("用户名", username);
    console.log("密码", password);
    login();
    console.log("学生", student);
    
    Vue.config.productionTip = false
    new Vue({
      router,
      render: h => h(App)
    }).$mount('#app')//这里定义了入口组件
    

组件与路由

组件
  • 复用组件:可复用

  • 页面式组件:不复用的,独此一份

  • Dept.vue

    <template>
      <div>
        <h1>部门页面</h1>
        <table border="1" width="450" align="center">
          <tr>
            <th>部门编号</th>
            <th>部门名称</th>
            <th>部门位置</th>
          </tr>
          <tr v-for="dept in deptList" :key="dept.id">
            <td>{{dept.id}}</td>
            <td>{{dept.name}}</td>
            <td>{{dept.loc}}</td>
          </tr>
        </table>
      </div>
    </template>
    
    <script>
    export default {
      name: "Dept",
      data() {
        return {
          deptList: []
        }
      },
      methods: {
        listHandle(){
          this.deptList = [
            {id: 11, name: '研发部', loc: '北京'},
            {id: 12, name: '生产部', loc: '上海'},
            {id: 13, name: '采购部', loc: '深圳'},
            {id: 14, name: '销售部', loc: '杭州'},
            {id: 15, name: '人力部', loc: '苏州'}
          ];
        }
      },
      mounted() {
        this.listHandle();
      }
    }
    </script>
    <style scoped>
    </style>
    
路由
  • 用于加载组件

  • 两种加载方式:立即加载 延迟加载

  • index.js

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    //立即导入(立即加载)组件
    import Home from '../views/Home.vue'
    //使用路由
    Vue.use(VueRouter)
    //路由列表
    const routes = [
      {path: '/', name: 'Home', component: Home},
      //组件延迟加载
      {path: '/about', name: 'About', component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')},
      {path: '/dept', name: 'dept', component: () => import(/* webpackChunkName: "dept" */ '@/views/Dept.vue')},
      {path: '/emp', name: 'emp', component: () => import(/* webpackChunkName: "emp" */ '@/views/Emp.vue')}
    ]
    const router = new VueRouter({
      routes
    })
    export default router
    
入口组件中添加路由
  • 在App.vue入口组件中添加路由

  • App.vue

    <template>
      <div id="app">
        <div id="nav">
          <router-link to="/">Home</router-link> |
          <router-link to="/about">About</router-link> |
          <router-link to="/dept">部门</router-link> |
          <router-link to="/emp">员工</router-link>
        </div>
        <router-view/>
      </div>
    </template>
    ...
    

Axios

简介

  • 专业的异步请求工具
  • Axios 中文文档 :https://www.axios-http.cn/
  • 官网简介
    • Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。
    • 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。
    • 在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

安装和导入axios

  • 安装

    $ npm install axios
    
  • 在XXX.Vue文件

Axios的使用

四种请求
axios.get(url, config)
axios.post(url, data, config)
axios.put(url, data, config)
axios.delete(url, config)
传递参数
/* 传递参数:
 * get与delete在配置中定义一个属性params(路径拼接传递参数)
 *post与put提价数据时在data参数填写数据即可,data参数本身是一个字面量对象,提交时会被转换为json字符串提交
 * axios发送请求时,ContentType内容类型默认为application/json
 */
axios({
  method: 'post',
  url: '/test',
  data: {
    id: 10,
    name: 'zhangsan'
  }
});
axios.get('/getTest',{
  params: {
    id: 20,
    name: 'list'
  }
});
axios.post('/postTest', {
  id: 30,
  name: 'wangwu'
});
接收响应:连调函数
/** 
 * 注意:如果需要进行跨域异步请求,路径必须写成完整
 * 连调函数then()成功回调,catch()失败回调
 * 此两个函数的参数也是一个函数,回调处理程序
 * 回调函数的参数为axios封装的一个对象,在此对象中有一个属性data为服务端真正响应的数据
 */
var that = this;
axios.get('http://localhost:8080/dept/list').then(function(res){
  console.log('响应内容', res.data.data);
  //在function函数中this关键字指向发生了改变
  that.deptList = res.data.data;
  console.log('deptList:',that.deptList)
}).catch(function (){
});
箭头函数
/**
 * 箭头函数:类似于Java lamda表达式
 * 替代匿名函数
 * function(){}
 * () => {}
 *
 * function(id){}
 * id => {}
 *
 * function(id,name){}
 * (id,name) => {}
 *
 * function(){console.log();}
 * () => console.log();
 * 好处:函数体内不改变this关键字的指向
 */
axios.get('http://localhost:8080/dept/list').then(res => {
  if(res.data.code == 0){
    this.deptList = res.data.data;
  }
}).catch(res => console.log(res));
封装为工具
  • 上面的写法还是太麻烦

  • 创建xxx.js文件,配置axios

    //导入axios
    import axios from 'axios';
    
    //创建axios对象,进行公共配置
    var instance = axios.create({
        //基础路径
        baseURL: 'http://localhost:8080',
        //请求超时时间
        timeout: 10000
    });
    
    //发送请求允许携带凭证(cookie)
    instance.defaults.withCredentials=true;
    
    //请求拦截器:在axios发送请求之前作出处理
    instance.interceptors.request.use(config => {
        console.log('请求的配置对象', config);
        //设置请求头部信息
        config.headers['myToken'] = 'hello axios';
        return config;
    }, error => Promise.reject(error));
    
    //响应拦截器:在axios收到响应之后作出处理
    instance.interceptors.response.use(response => {
        //将服务器响应的数据从axios的封装中取出,直接返回
        return response.data;
    }, error => Promise.reject(error));
    
    //导出axios对象
    export default instance;
    
  • 使用工具类

    • 在main.js中导入,并挂载到全局

      //导入axios工具类
      import request from '@/utils/request'
      ...
      //将axios工具类对象挂载到全局(Vue对象),$ajax是自定义的属性名,用的时候保持一致就可以
      Vue.prototype.$ajax = request;
      
    • 在xxx.vue中使用

      //this 是vue对象
      this.$ajax.get('/dept/list').then(res => {
          console.log('服务端响应的数据:', res)
          if(res.code == 0){
              this.deptList = res.data;
          }
      }).catch(res => console.log(res));
      

(){
});


#### 箭头函数

```js
/**
 * 箭头函数:类似于Java lamda表达式
 * 替代匿名函数
 * function(){}
 * () => {}
 *
 * function(id){}
 * id => {}
 *
 * function(id,name){}
 * (id,name) => {}
 *
 * function(){console.log();}
 * () => console.log();
 * 好处:函数体内不改变this关键字的指向
 */
axios.get('http://localhost:8080/dept/list').then(res => {
  if(res.data.code == 0){
    this.deptList = res.data.data;
  }
}).catch(res => console.log(res));
封装为工具
  • 上面的写法还是太麻烦

  • 创建xxx.js文件,配置axios

    //导入axios
    import axios from 'axios';
    
    //创建axios对象,进行公共配置
    var instance = axios.create({
        //基础路径
        baseURL: 'http://localhost:8080',
        //请求超时时间
        timeout: 10000
    });
    
    //发送请求允许携带凭证(cookie)
    instance.defaults.withCredentials=true;
    
    //请求拦截器:在axios发送请求之前作出处理
    instance.interceptors.request.use(config => {
        console.log('请求的配置对象', config);
        //设置请求头部信息
        config.headers['myToken'] = 'hello axios';
        return config;
    }, error => Promise.reject(error));
    
    //响应拦截器:在axios收到响应之后作出处理
    instance.interceptors.response.use(response => {
        //将服务器响应的数据从axios的封装中取出,直接返回
        return response.data;
    }, error => Promise.reject(error));
    
    //导出axios对象
    export default instance;
    
  • 使用工具类

    • 在main.js中导入,并挂载到全局

      //导入axios工具类
      import request from '@/utils/request'
      ...
      //将axios工具类对象挂载到全局(Vue对象),$ajax是自定义的属性名,用的时候保持一致就可以
      Vue.prototype.$ajax = request;
      
    • 在xxx.vue中使用

      //this 是vue对象
      this.$ajax.get('/dept/list').then(res => {
          console.log('服务端响应的数据:', res)
          if(res.code == 0){
              this.deptList = res.data;
          }
      }).catch(res => console.log(res));
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值