vue学习

vue入门

  • vue引入
    下载源码
    cdn引入(Content Delivery Network,即内容分发网络)

  • hello vue


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>

    <!--
        MVVM: M(model),V(view),VM(ViewModel)
    -->
    <!--vue实例控制的这个元素区域就是 MVVM 中的V视图-->
    <div class="app">
        <p>{{msg}}</p>
    </div>

    <script>
        /**
         * 创建view实例
         * 导入vue包后,在浏览器内存中就会多一个Vue的构造函数
         * 下面new出来的vm对象就是MVVM中的VM调度者
         */
        var vm=new Vue({
            el: '.app',//vue实例控制页面的哪个区域
            data: { //存放el要用到的数据
                msg:'hello,vue!'//通过vue提供的指令,很方便的把数据渲染到页面上,程序员不用动手操作DOM元素
            }
        })
    </script>

</body>
</html>

指令

  • v-model
    在html页面中修改msg内容,会直接修改vue中的msg
<body>
    <div id="app">
        <p>{{msg}}</p>
        <!--v-model 数据双向绑定-->
        <input type="text" v-model="msg">
    </div>

    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'学习vue'
            }
        })
    </script>
</body>
  • v-text

解决{{对象}}闪现的问题

    <div id="app">
        <p>{{msg}}</p>
        <p v-text="msg"></p>
    </div>

    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'学习vue'
            }
        })
    </script>
  • v-html
    可以执行html命令字符串
    <div id="app">
        <p>{{msg}}</p>
        <p v-html="msg"></p>
    </div>

    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'<h1>学习vue</h1>'
            }
        })
    </script>
  • v-cloak

和css规则[v-cloak]{display:none}一起使用,可以隐藏未编译的Mustache直到实例准备完毕

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <style>
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>
    <div id="app">
        <p v-cloak>{{msg}}</p>
    </div>

    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'学习vue'
            }
        })
    </script>
</body>
</html>
  • v-for
<body>

<div id="app">
    <!--迭代简单数组-->
    <!--<p v-for="(item,i) in list">索引:{{i}}  值:{{item}}</p>-->


    <!--迭代复杂数组-->
    <!--<p v-for="(item,i) in listC">索引:{{i}}  id:{{item.id}}  名字:{{item.name}}</p>-->

    <!--迭代对象中的属性-->
    <!--<p v-for="(val,key,i) in userInfo">索引:{{i}} 属性值{{val}} 属性名{{key}}</p>-->

    <!--迭代数字-->
    <p v-for="item in 10">第{{item}}轮循环</p>
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            list: [1, 2, 3, 4, 5, 6, 7],
            listC:[
                {id:1,name:'张三'},
                {id:2,name:'李四'},
                {id:3,name:'王五'},
                {id:4,name:'陈六'}
            ],
           userInfo:{
                id:1,
               name:'张三',
               gender:'男'
           }
        }
    })
</script>
</body>

注意 在2.2.0+版本中,当使用v-for时,key必须使用
Vue.js中v-for在更新已经渲染过的元素列表时,默认使用“就地复用”策略。为了方便vue能跟踪每个结点的身份,从而重用和重新排序现有元素,我们需要给一个唯一的key属性(key的值必须为string或number类型

<body>

<div id="app">
    <div>
        <lable>Id:
            <input type="text" v-model="id">
        </lable>
        <lable>Name:
            <input type="text" v-model="name">
        </lable>

        <input type="button" value="添加" @click="add">
    </div>

    <div>
        <!--key指定可以唯一标识的值-->
        <p v-for="item in list" :key="item.id">
            <input type="checkbox"> {{item.id}} {{item.name}}
        </p>
    </div>

</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            id:'',
            name:'',
            list: [
                {id: 1, name: '张三'},
                {id: 2, name: '李四'},
                {id: 3, name: '王五'},
                {id: 4, name: '陈六'}
            ]
        },
        methods:{
            add(){
                /*unshift向数组中队头添加对象*/
                this.list.unshift({id:this.id,name:this.name});
            }
        }
    })
</script>
</body>
  • v-if和v-show
div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <!--v-if:每次都会重新删除或创建元素-->
    <h3 v-if="flag">这是v-if控制的元素</h3>
    <!--v-show:每次都不会重新进行DOM的删除和操作,只是切换了元素的display:none样式-->
    <h3 v-show="flag">这是v-show控制的元素</h3>
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            flag:true
        }
    })
</script>

绑定样式

元素绑定class样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <style>

        .red{
            color: red;
        }

        .italic{
            font-style: italic;
        }

        .active{
            letter-spacing: 0.5em;
        }
    </style>
</head>
<body>
    <!--&lt;!&ndash;html原生的添加class方式&ndash;&gt;
    <h1 id="h1" class="red italic active">{{msg}}</h1>-->


    <!--使用v-bind绑定-->
    <!--<h1 id="h1" :class="['red','italic','active']">{{msg}}</h1>-->

    <!--将class对应的数组对象提取出来写在vue实例的data中-->
    <!--<h1 id="h1" :class="classObj">{{msg}}</h1>-->

    <!--使用使用三元表达式-->
    <!--<h1 id="h1" :class="['red','italic',flag?'active':'']">{{msg}}</h1>-->

    <!--使用对象代替三元表达式-->
    <!--<h1 id="h1" :class="['red','italic',{'active':flag}]">{{msg}}</h1>-->

    <!--注意
        在class中使用v-bind绑定对象时,对象的属性名是类名,由于对象的属性可带引号,也可以不带
    -->

    <script type="text/javascript">
        var vm=new Vue({
            el: '#h1',
            data:{
                msg:'我是一级标题',
                flag:false,
                classObj:['red','italic','active']
            }
        })
    </script>
</body>
</html>

元素绑定style样式

<body>
    <!--直接通过:style方式-->
    <!--<h1 id="h1" :style="{color:'red','font-size':'40px'}">{{msg}}</h1>-->

    <!--把样式对象定义到data中,再引用到:style-->
    <!--<h1 id="h1" :style="styleObj">{{msg}}</h1>-->

    <!--在:style中通过数组应用多个data上的样式-->
    <h1 id="h1" :style="[styleObj,styleObj2]">{{msg}}</h1>

    <script type="text/javascript">
        var vm=new Vue({
            el: '#h1',
            data:{
                msg:'我是一级标题',
                styleObj:{color:'red','font-size':'40px'},
                styleObj2:{fontStyle:'italic'}
            }
        })
    </script>
</body>

过滤器

  • 过滤器使用管道符:’|’
<div id="app">

    <!--过滤器使用格式{{数据 | 过滤器名称}}-->
    <p>{{msg | filter1}}</p>

</div>

<script type="text/javascript">

    /*
    创建过滤器
    filter1:为过滤器名称
    msg:传递过来的数据,通过管道符左边的传递的数据
    */
    Vue.filter('filter1',function (msg) {
        return msg.replace(/你/g,'他们');
    })
    var vm = new Vue({
        el: '#app',
        data: {
            msg:'你好,你吃过了吗,你要去哪?'
        }
    })
</script>
  • 过滤器还可以传入参数
<div id="app">

    <!--过滤器使用格式{{数据 | 过滤器名称}}-->

    <p>{{msg | filter1('他们','111')}}</p>

</div>

<script type="text/javascript">

    //创建过滤器
    Vue.filter('filter1',function (msg,arg,arg2) {
        return msg.replace(/你/g,arg+arg2);
    })
    var vm = new Vue({
        el: '#app',
        data: {
            msg:'你好,你吃过了吗,你要去哪?'
        }
    })
</script>
  • 可以同时使用多个过滤器
<p>{{msg | filter1 |filter2 }}</p>
  • 全局和私有过滤器

上面定义的是全局过滤器,下面定义私有过滤器

在new Vue({})中添加filters

filters: {//私有过滤器
            dateFormat:function (dateStr,pattern='') {
                //根据给定的时间字符串,得到特定的时间
                var dt=new Date(dateStr);

                //提取年月日
                var y=dt.getFullYear();
                var m=dt.getMonth()+1;//月份从0开始
                var d=dt.getDate();

                if(pattern.toLocaleLowerCase()=='yyyy-mm-dd'){
                    return `${y}-${m}-${d}`;
                }else{

                    //最全时间格式
                    var hh=dt.getHours();
                    var mm=dt.getMinutes();
                    var ss=dt.getSeconds();
                    return `${y}-${m}-${d} ${hh}:${mm}:${ss}~~~~`;
                }
            }
        }

当全局和私有过滤器同名且同时存在,就近原则,优先调用私有过滤器

字符串补充

  • String.prototype.padStart(maxLength,fillString=‘xx’)或String.prototype.padEnd(maxLength,fillString=‘xx’)
    字符串长度不足时padStart在左边补齐’xx’,padEnd在右边补齐’xx’

数组补充

  • some
    用于检测数组中的元素是否满足指定的条件。
数组名.some((str)=>{
     return str==='xxx'
   //如果有就是true否则为false
})
  • splice(index,len,[item])
    它也可以用来替换/删除/添加数组内某一个或者几个值(该方法会改变原始数组)
    index:数组开始下标
    len: 替换/删除的长度
    item:替换的值,删除操作的话 item为空
this.list.some((item,i)=>{
    if(item.id==id){
    //删除下标从i开始,删除1个
    this.list.splice(i,1);
    return true;
    }
})

按键修饰符

vue中提供的按键修饰符
https://cn.vuejs.org/v2/guide/events.html

在js中每个按键都对应具体的数字,可以直接使用,也可以自定义修饰符

<!--在js中f2对应113-->
<input type="text" class="form-control" v-model="name" @keyup.113="add">
<input type="text" class="form-control" v-model="name" @keyup.f2="add">
<script>
  Vue.config.keyCodes.f2=113;
</script>

自定义指令

https://cn.vuejs.org/v2/guide/custom-directive.html


<input type="text" class="form-control" v-model="keywords" v-focus v-color>
//自定义指令名称为focus 使用时v-focus
    Vue.directive('focus',{
        //el参数,是一个原生的JS对象
        inserted:function (el) {//在插入DOM时会执行一次
            el.focus()

            //Js行为相关的都在inserted中设置
        }
    })

    Vue.directive('color',{
        //指令绑定元素时操作,只会触发一次
        bind:function(el){
            //和样式相关的操作都在bind中操作
            el.style.color='red';
        }
    })

传递颜色值


<input type="text" class="form-control" v-model="keywords" v-color="'blue'">

Vue.directive('color',{
        //指令绑定元素时操作,只会触发一次
        bind:function(el,binding){
            //和样式相关的操作都在bind中操作
            el.style.color=binding.value;
        }
    })

vue生命周期

在这里插入图片描述

vue-resource基本使用

https://github.com/pagekit/vue-resource/blob/develop/docs/http.md

methods:{
          getInfo(){
              this.$http.get('http://10.3.242.250:3000/').then(response => {
                  console.log(response.body);
              });

          },
            postInfo(){
              this.$http.post('http://10.3.242.250:3000/list',{},{emulateJSON:true})
                  .then(result=>{
                      console.log(result.body)
                  })
            },
            jsonpInfo(){
              this.$http.jsonp('ip地址').then(result=>{
                  console.log(result.body)
              })
            }

        }

组件

  • 什么是组件:

    组件的出现 ,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;

  • 组件化和模块化的不同:

    • 模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
    • 组件化:是从∪I界面的角度进行划分的;前端的组件化,方便∪I组件的重用;

创建组件方式

  1. Vue.extend()方式
<div id="app">

    <!--使用驼峰-->
    <!--<my-com1></my-com1>-->
    <!--不适用驼峰,直接拿名字使用-->
    <mycom1></mycom1>
</div>

<script type="text/javascript">

    //使用Vue.extend来创建全局Vue组件
    var com1=Vue.extend({
        //通过template属性指定组件要展示的HTML结构
        template:'<h2>只是使用Vue.extend创建的组件</h2>'
    })

    //使用Vue.component('组件名称',创建出来的组件模板对象)

    /**
     *Vue.component定义全局变量时,组件使用驼峰命名,则在引用组件的时候需要把大写的驼峰改成小写的字母,
     * 同时,两个单词之间使用'-'链接
     *
     *如果不适用驼峰,则直接拿名称来使用
     */

     
    /*Vue.component('myCom1',com1);*/
    /*Vue.component('mycom1',com1);*/

    /*两步合成一步*/
    Vue.component('mycom1',Vue.extend({
        //通过template属性指定组件要展示的HTML结构
        template:'<h2>只是使用Vue.extend创建的组件</h2>'
    }));
    var vm = new Vue({
        el: '#app',
        data: {
            msg:'ok'
        },
        methods:{
          show(){
              console.log('执行了show方法')
          }
        }
    })
</script>
</body>
  1. Vue.component直接创建

/*两步合成一步*/
    Vue.component('mycom2',{
        //通过template属性指定组件要展示的HTML结构
        template:'<h2>只是使用Vue.extend创建的组件</h2>'
    });

无论时那种方式创建组件,template属性指向的模板内容,必须有且只能有唯一的一个根元素

3、template单独写


<div id="app">
    <mycom3></mycom3>
</div>

<!--在被控制的#app外面,使用template元素,定义组件的html模板结构-->
<template id="tmpl">
    <div>
        <h2>只是使用Vue.extend创建的组件</h2>
    </div>
</template>

<script type="text/javascript">

    /*两步合成一步*/
    Vue.component('mycom3',{
        //通过template属性指定组件要展示的HTML结构
        template:'#tmpl'
    });
    var vm = new Vue({
        el: '#app',
        data: {}
    })
</script>

私有组件

  • components
<div id="app">
    <mycom4></mycom4>
</div>

<!--在被控制的#app外面,使用template元素,定义组件的html模板结构-->
<template id="tmpl">
    <div>
        <h2>只是使用Vue.extend创建的组件</h2>
    </div>
</template>

<script type="text/javascript">

    var vm = new Vue({
        el: '#app',
        data: {},
        components:{
            mycom4:{
                template:'#tmpl'
            }
        }
    })
</script>

组件切换

  • v-if和v-else
<div id="app">
    <input type="button" value="登录" @click="flag=true">
    <input type="button" value="祖册" @click="flag=false">
    
    <!--通过flag的值来确定显示哪个组件-->
    <login v-if="flag"></login>
    <register v-else="flag"></register>
</div>

<script type="text/javascript">

    /*两步合成一步*/
    Vue.component('login',{
        template:'<h2>登录组件</h2>'
    });

    Vue.component('register',{
        template:'<h2>注册组件</h2>'
    })
    var vm = new Vue({
        el: '#app',
        data: {
            flag:true
        }
    })
</script>
  • component占位符
<div id="app">
    <input type="button" value="登录" @click="compName='login'">
    <input type="button" value="注册" @click="compName='register'">

    <!--component在这里就是一个占位符,通过:is来绑定一个组件并显示-->
    <component :is="compName"></component>
</div>

<script type="text/javascript">

    /*两步合成一步*/
    Vue.component('login',{
        template:'<h2>登录组件</h2>'
    });

    Vue.component('register',{
        template:'<h2>注册组件</h2>'
    })
    var vm = new Vue({
        el: '#app',
        data: {
            compName:'login'
        }
    })
</script>

父组件向子组件传递

  • 父组件向子组件传递值

<div id="app">
    <!--通过v-bind绑定一个parentmsg对象和父组件中的msg对象-->
    <com1 v-bind:parentmsg="msg"></com1>
</div>

<script type="text/javascript">

    var vm = new Vue({
        el: '#app',
        data: {
            msg:'这是父组件中的值'
        },
        /*定义子组件*/
        components:{
            //子组件无法默认访问到父组件中的data上的数据和methods中的方法
            com1:{
                //子组件中data数据是自身私有的,可以修改
                data(){
                    return{
                        title:'123',
                        content:'qqq'
                    }
                },
                template:'<h2>这是子组件------{{parentmsg}}</h2>',
                //props是一个数组类型,中的数据,都是父组件传递给子组件的,不可以修改
                props:['parentmsg']
            }


        }
    })
</script>
  • 父组件向子组件传递事件

<div id="app">
    <!--事件绑定需要使用v-on或简写@,自定义一个func事件变量,绑定show-->
    <com1 @func="show"></com1>
</div>

<template id="tmp1">
    <div>
        <h1>这是子组件</h1>
        <input type="button" value="这是子组件的按钮,点击它,触发父组件传递过来func方法" @click="myclick">
    </div>
</template>

<script type="text/javascript">

    //定义一个自变量类型的组件模板对象
    var com1={
        template: '#tmp1',//通过指定id,加载对应的template元素中的内容,当做组件的HTML结构
        methods:{
            myclick(){
                //通过调用子组件自身的$emit方法,传递自定义的事件名,如果方法有参数,对应传递参数
                this.$emit('func','123')
            }
        }
    }
    var vm = new Vue({
        el: '#app',
        data: {
            msg:'这是父组件中的值'
        },
        /*定义子组件*/
        components:{
            com1
        },
        methods:{
            show:function (data) {
                console.log('这是父组件show方法'+data)
            }
        }
    })
</script>

通过子组件调用父组件的事件,也可以把子组件的数据传递给父组件

非父子组件间数据传值

  1. 单独事件中心管理组件间的通信
    var eventHub=new Vue()

  2. 监听事件与销毁事件
    eventHub. o n ( 函 数 名 , 函 数 体 ) e v e n t H u b . on(函数名,函数体) eventHub. on(,)eventHub.off(函数名)

  3. 触发事件
    eventHub.$emit(函数名,参数)

在这里插入图片描述

  • 案例代码
    在这里插入图片描述
<div id="app">
        <div>
            <span>父组件</span>
            <button @click='handle'>销毁事件</button>

        </div>
        <test-tom></test-tom>
        <test-jerry></test-jerry>
    </div>


    <script>

        //事件中心
        var eventHub=new Vue();
        //组件test-tom
        Vue.component("test-tom", {
            data() {
                return {
                    num: 0
                }
            },

            template: `
                <div>
                    <h6>TOM:{{num}}</h6>
                    <div>
                        <button @click='handle'>点击</button>
                    </div>
                </div> 
            `,
            methods: {
                handle:function(val){
                    eventHub.$emit('jerry-event',2);
                }
            },
            mounted:function(){
                //监听事件
                eventHub.$on('tom-event',(val)=>{
                    this.num+=val;
                })
            }
        });

        //组件test-jerry
        Vue.component("test-jerry", {
            data() {
                return {
                    num: 0
                }
            },

            template: `
                <div>
                    <h6>Jerry:{{num}}</h6>
                    <div>
                        <button @click='handle'>点击</button>
                    </div>
                </div> 
            `,
            methods: {
                handle:function(val){
                    eventHub.$emit('tom-event',1);
                }
            },
            mounted:function(){
                //监听事件
                eventHub.$on('jerry-event',(val)=>{
                    this.num+=val;
                })
            }
        });

        var vm=new Vue({
            el:'#app',
            data:{

            },
            methods: {
                //注销事件
                handle:function(){
                    eventHub.$off('tom-event');
                    eventHub.$off('jerry-event');
                }
            },
        });

    </script>

ref获取DOM元素和组件引用


<div id="app">
    <input type="button" value="show" @click="show">
    <!--通过在元素中添加ref属性,讲指定名称的组件添加到vue中的refs-->
    <h3 id="myh3" ref="myh3">今天天气真好!</h3>
    <com1 ref="com1"></com1>
</div>

<template id="tmp1">
    <div>
        <h1>这是子组件</h1>
    </div>
</template>

<script type="text/javascript">

    //定义一个自变量类型的组件模板对象
    var com1={
        template: '#tmp1',//通过指定id,加载对应的template元素中的内容,当做组件的HTML结构
        methods:{
            myclick(){
                console.log('子组件事件')
            }
        }
    }
    var vm = new Vue({
        el: '#app',
        data: {
            msg:'这是父组件中的值'
        },
        methods:{
            show:function () {
                /*通过this.$refs.元素名称进行访问*/
                console.log(this.$refs.myh3.innerText)
                this.$refs.com1.myclick()
            }
        },
        /*定义子组件*/
        components:{
            com1
        }

    })
</script>

前端路由和后端路由

什么是路由

  1. 后端路由: 所有超链接都是URL地址,所有URL地址都对应服务器上对应的资源;
  2. 前端路由: 对于单页面应用程序,主要通过URL中的hash(#号)来实现单页面不同位置之间的切换;hash有一个特点:HTTP请求不会包含hash相关内容。
  3. 在单页面通过hash改变来切换页面内容的方式,称作前端路由(区别于后端路由)
  • 参考链接:https://www.cnblogs.com/joyho/articles/4430148.html

vue-router基本使用

  1. 引入对应js资源,需要依赖vue
  2. 创建VueRouter实例
  3. 在实例中添加对应的路由匹配规则
  4. 在Vue实例中添加 2中的VueRouter实例
  5. 在对应Vue控制区域添加占位符
<div id="app">
   	<!--<a href="#/login">登录</a>
    <a href="#/register">注册</a>-->

    <!--vue-router提供的元素,router-link默认渲染为一个 a标签,通过tag可以指定渲染成对应标签-->
    <router-link to="/login" tag="span">登录</router-link>
    <router-link to="/register">注册</router-link>

    <!--vue-Router提供的元素,专门用来当作占位符,将来路由匹配规则匹配到的组件会展示到router-view中-->
    <router-view></router-view>
</div>

<script type="text/javascript">
    //登录组件模板对象
    var login={
        template: '<h2>登录组件</h2>'
    }

    //登录组件模板对象
    var register={
        template: '<h2>注册组件</h2>'
    }
    /*第二步创建VueRouter实例*/
    //创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
    var routerObj=new VueRouter({
        /*路由匹配规则数组,注意是routes*/
        routes:[
            /**
             * 每个路由匹配规则都是一个对象,每个对象必须有2个属性
             * 属性1 path,表示监听那个路由链接地址
             * 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
            */
            {path:'/login',component:login},
            {path:'/register',component:register}
        ]
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件

    })

</script>

上面代码中需要注意,使用点击超链接流程是:超链接改变请求地址的hash,然后在根据请求地址请求匹配对应的组件

  • 路由redirect重定向

在上面的案例中第一次进入页面应该展示登录组件比较合理,这个时候可以采用

 {path:'/',component:login}

但是地址栏上#/显示的却是登录组件,会给用户带来困惑

所以我们可以使用vue-router提供的redirect

{path:'/',redirect:'/login'},
  • router-link 控件点击激活样式

通过上面案例,点击 router-link会自动在该控件上添加类:router-link-active
该类是由VueRouter实例中的linkActiveClass指定的所以修改控件点击样式有2种方式

<style>
        .myactive{
            color:red;
        }

        /*方式二重写默认样式的router-link-active*/
        .router-link-active{
            color:blue;
        }
    </style>
<div id="app">
    
    <!--vue-router提供的元素,router-link默认渲染为一个 a标签,通过tag可以指定渲染成对应标签-->
    <router-link to="/login" tag="span">登录</router-link>
    <router-link to="/register">注册</router-link>

    <!--vue-Router提供的元素,专门用来当作占位符,将来路由匹配规则匹配到的组件会展示到router-view中-->
    <router-view></router-view>
</div>

<script type="text/javascript">
    //登录组件模板对象
    var login={
        template: '<h2>登录组件</h2>'
    }

    //登录组件模板对象
    var register={
        template: '<h2>注册组件</h2>'
    }
    /*第二步创建VueRouter实例*/
    //创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
    var routerObj=new VueRouter({
        /*路由匹配规则数组,注意是routes*/
        routes:[
            /**
             * 每个路由匹配规则都是一个对象,每个对象必须有2个属性
             * 属性1 path,表示监听那个路由链接地址
             * 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
            */
            {path:'/',component:login},
            //{path:'/',redirect:'/login'},
            {path:'/login',component:login},
            {path:'/register',component:register}
        ],
        /*方式一自定义指定样式*/
        //linkActiveClass:'myactive'
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件

    })

</script>
  • 路由传参
    1.参数保存在query中
    在上面案例代码中修改如下代码
<router-link to="/login?id=10" tag="span">登录</router-link>

在这里插入图片描述
通过浏览器命令终端可以看到query中保存了传递的参数

在代码中输出路由传递的参数

//登录组件模板对象
    var login={
        template: '<h2>登录组件--{{$route.query.id}}</h2>',
        created(){//组件生命周期钩子函数
            console.log(this.$route.query.id)
        }
    }
  1. 参数保存在params中

vue-router提供了一套参数正则匹配

/:id/:name
在传参时,通过/12/zhagnsan
在vue中的Router中的params中会生成
id:12
name:zhagnsan

修改代码如下

<router-link to="/login/12/ls">登录</router-link>

<script>
//登录组件模板对象
    var login={
        template: '<h2>登录组件--{{$route.params.id}}--{{$route.params.name}}</h2>',
        created(){//组件生命周期钩子函数
            console.log(this.$route.params.id)
            console.log(this.$route.params.name)
        }
    }
<!--在路由匹配规则中使用:名称-->
{path:'/login/:id/:name',component:login}
</script>

在这里插入图片描述

  • 路由的嵌套
<div id="app">
    <router-link to="/account">account</router-link>
    <!--vue-Router提供的元素,专门用来当作占位符,将来路由匹配规则匹配到的组件会展示到router-view中-->
    <router-view></router-view>
</div>

<template id="tmp1">
    <div>
        <h1>这是Account组件</h1>
        <router-link to="/account/login">登录</router-link>
        <router-link to="/account/register">注册</router-link>
        <router-view></router-view>
    </div>
</template>
<script type="text/javascript">


    var account={
        template:'#tmp1'
    }
    //登录组件模板对象
    var login={
        template: '<h2>登录组件</h2>',
    }

    //登录组件模板对象
    var register={
        template: '<h2>注册组件</h2>',
    }
    /*第二步创建VueRouter实例*/
    //创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
    var routerObj=new VueRouter({
        /*路由匹配规则数组,注意是routes*/
        routes:[
            /**
             * 每个路由匹配规则都是一个对象,每个对象必须有2个属性
             * 属性1 path,表示监听那个路由链接地址
             * 属性2 component,表示对应前面path路由匹配的对应组件,且必须是组件模板对象,不能是组件引用名称
            */
            {
                path:'/account',
                component:account,
                /*children子路由*/
                children:[
                    /*子路由的path前面不要带 / ,否则永远从根路径开始请求*/
                    {path:'login',component:login},
                    {path:'register',component:register}
                ]
            }

        ],
        /*方式一自定义指定样式*/
        //linkActiveClass:'myactive'
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
    })

</script>
  • 路由使用命名视图
    在router-view控件中使用name属性来指定显示组件
<div id="app">
    <!--没有标记name的使用默认-->
    <router-view></router-view>
    <router-view name="left"></router-view>
    <router-view name="main"></router-view>
</div>

<script type="text/javascript">
    var header={
        template:'<h2>头组件</h2>'
    }
    //登录组件模板对象
    var left={
        template: '<h2>左侧组件</h2>',
    }

    //登录组件模板对象
    var main={
        template: '<h2>右侧组件</h2>',
    }
    /*第二步创建VueRouter实例*/
    //创建一个路由对象,当导入一个vue-router包后,在window全局对象中,就有一个路由的构造函数,叫做VueRouter
    var routerObj=new VueRouter({
        /*路由匹配规则数组,注意是routes*/
        routes:[
            {
                path:'/',
                /*注意这里是components*/
                components:{
                    /*左边名称会自动添加引号*/
                    default:header,
                    left:left,
                    left:main
                }
            }

        ],
        /*方式一自定义指定样式*/
        //linkActiveClass:'myactive'
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        router: routerObj//将路由匹配对象,注册到vue实例上,用来监听URL地址的变化,然后展示对应的组件
    })

</script>

watch、computed

  • watch文本监听
    输入名和字来拼接出全名
<div id="app">
    <input type="text" v-model="firstname">+
    <input type="text" v-model="lastname">
    <input type="text" v-model="fullname">
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            firstname:'',
            lastname:'',
            fullname:''
        },
        watch:{
            /*watch可以监视data中指定数据的变化,然后触发这个watch中对应的function处理函数*/
            firstname: function (newVal,oldVal) {
                this.fullname=newVal+'-'+this.lastname
            },
            lastname: function (newVal,oldVal) {
                this.fullname=newVal+'-'+this.lastname
            },
        }
    })

</script>
  • computed
<div id="app">
    <input type="text" v-model="firstname">+
    <input type="text" v-model="lastname">
    <input type="text" v-model="fullname">
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            firstname: '',
            lastname: ''
        },
        /*
        * 在computed中可以定义一些属性,叫做【计算属性】,计算属性的本质就是一个方法
        * 计算属性可以直接当做属性来使用,并不会把计算属性当做方法来调用
        * 计算属性function内部如果用到了data数据,只要其中发生了变化,就会立即重新计算。
        * 计算属性的求值结果会被缓存起来,方便下次使用。
        * */
        computed: {
            'fullname': function f() {
                return this.firstname+'-'+this.lastname
            }
        }
    })

</script>
  • watch、computed和methods之间的对比
  1. computed 属性的结果会被缓存,除非依赖的响应式属性変化オ会重新计算.主要当作属性来使用
  2. methods 方法表示一个具体的操作,主要书写业务逻辑;
  3. watch 个対象,键是需要观察的表达式,值是对应回调函数.主要用来监听某些特定数据的变化,从而迸行某些具体的逻辑操作;可以看作是computed和methods 结合体;

webpack

什么是webpack

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

使用webpack

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

局部安装
npm install --save-dev webpack
  1. 使用前的准备
  • 创建文件目录如下
    在这里插入图片描述

  • 在项目文件的根目录下,创建package.json 文件,这是一个npm说明文件。

  npm init

输入这个命令后,终端会提出一系列问题,一般默认即可,也可以使用npm init -y。在项目目录下,自动创建package.json 文件。

  • package.json文件已经就绪,在项目中安装webpack依赖包

      npm install --save-dev webpack
    
  1. 基础使用

现在需要实现一个功能:页面显示多个列表行,奇数行和偶数行背景颜色不同

index.html

<!-- 网页入口 -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- <script src="./main.js"> </script> -->
    <title>首页</title>
    <!-- <script src="/buddle.js"></script> -->
</head>
<body>
  <ul>
    <li>这是第1个li</li>
    <li>这是第2个li</li>
    <li>这是第3个li</li>
    <li>这是第4个li</li>
    <li>这是第5个li</li>
    <li>这是第6个li</li>
    <li>这是第7个li</li>
    <li>这是第8个li</li>
    <li>这是第9个li</li>
    <li>这是第10个li</li>
  </ul>
</body>
</html>

项目安装jquery

 npm install jquery --save 缩写
npm i jquery -S

补充npm i 安装命令中的 -g -D -S的区别
https://blog.csdn.net/qq_32202099/article/details/100005445

main.js

//项目的js入口文件

//导入jquery
import $ from 'jquery'
// const $ = require('jquery')

$(function(){
  $('li:odd').css('backgroundColor','black')
  $('li:even').css('backgroundColor',function(){
    return '#'+'D97634'
  })
})

因为在main.js中使用了import命令,这是ES6代码,浏览器解析不了。所以需要使用webpack继续解析成对应js文件

webpack .\src\main.js .\dist\bundle.js

在index.js文件中引入这个bundle.js文件即可。

当修改main.js文件内容时,需要重新手运行webpack .\src\main.js .\dist\bundle.js比较麻烦。现在引入webpack配置文件

在项目根目录下创建 webpack.config.js

const path=require('path')

//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
  entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
  output:{
    path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录中去
    filename: 'bundle.js'//指定输出文件的名称
  }
}

现在再次修改main.js文件后,可以直接运行webpack命令即可

修改main.js自动编译
本地安装 webpack-dev-server插件,实现自动打包编译功能

npm i webpack-dev-server -D

因为是本地安装,不能在终端直接使用 webpack-dev-server命令,所以需要在package.json中配置

"scripts": {
    ....,
    "dev": "webpack-dev-server"
  },

在命令行中可以直接运行

npm run dev

注意: 运行webpack-dev-server生成的bundle.js是在内存中的,路径是/bundle.js,所以需要修改一下index.js中的引用。

webpack-dev-server常用参数配置方式一
在package.json中配置,方便

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"
  },

–open:启动webpack-dev-server自动打开浏览器
–port 3000 :端口号
–contentBase src:默认打开网页目录
– hot:热更新,不用每次都生成全新的bundle.js文件

webpack-dev-server常用参数配置方式一
在webpack.config.js中配置,比较麻烦
直接查看js文件

const path=require('path')

//启动热更新的第二步
const webpack=require('webpack')

//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
  entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
  output:{
    path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录总去
    filename: 'buddle.js'//指定输出文件的名称
  },
  devServer:{//这是配置dev-server 命令参数的第二种形式,相对来说,这种方式麻烦一些
    // --open --port 3000 --contentBase src --hot
    open:true,//自动打开浏览器
    port:3000,//设置启动时运行端口
    contentBase:'src',//指定托管的跟目录
    hot:true//启动热更新的第一步
  },

  plugins:[//配置插件的结点
    //启动热更新第三步
    new webpack.HotModuleReplacementPlugin(),
  ]
}

安装配置 html-webpack-plugin
自动在内存中根据指定页面生成一个内存页面
安装 npm i html-webpack-plugin -D

配置

const path=require('path')

//启动热更新的第二步
const webpack=require('webpack')

//导入内存中生成HTML页面的插件
//只要是插件都需要放到 plugins结点中
//这个插件的两个作用:
// 1. 自动在内存中根据指定页面生成一个内存页面
// 2. 自动,把打包好的bundle.js追加到页面中去
const htmlWebpackPlugin=require("html-webpack-plugin")
//这个配置文件,起始就是一个JS文件,通过Node中的模块,向外暴露一个配制对象
module.exports={
  entry: path.join( __dirname ,'./src/main.js'),//入口,要使用webpack打包那个文件
  output:{
    path: path.join(__dirname,'./dist'),//指定打包好的文件,输出到哪个目录总去
    filename: 'buddle.js'//指定输出文件的名称
  },
  devServer:{//这是配置dev-server 命令参数的第二种形式,相对来说,这种方式麻烦一些
    // --open --port 3000 --contentBase src --hot
    open:true,//自动打开浏览器
    port:3000,//设置启动时运行端口
    contentBase:'src',//指定托管的跟目录
    hot:true//启动热更新的第一步
  },

  plugins:[//配置插件的结点
    //启动热更新第三步
    new webpack.HotModuleReplacementPlugin(),

    new htmlWebpackPlugin({
      template: path.join(__dirname,'./src/index.html'),//指定模板页面,将来会根据指定的页面,去内存生成内存中的页面
      filename: 'index.html'//指定生成页面的名称
    })
  ]
}

运行 npm run dev,会访问内存中生成的index.html页面,页面会自动在body末尾添加内存中bundle.js文件的应用。

处理css文件的第三方loader
webpack默认只能打包处理JS类型的文件,处理非JS类型的文件,需要手动安装一些合适的第三方loader加载器。处理css文件,需要安装style-loadercss-loader

npm i style-loader css-loader -D

在webpack.config.js配置文件中,新增配置结点 module对象,在这个module对象身上,有一个rules属性,这个属性是一个数组,存放所有第三方文件的匹配和处理规则。

module:{
    rules:[
      {test:/\.css$/,use:['style-loader','css-loader']},//配置处理css文件的第三方loader规则
    ]
  }

处理less文件的第三方loader

npm i less-loader -D

出现没有安装的依赖,需要继续安装

{test:/\.less$/,use:['style-loader','css-loader','less-loader']},//处理less文件的第三方loader规则

处理scss文件的第三方loader

npm i sass-loader -D

出现没有安装的依赖,需要继续安装

{test:/\.less$/,use:['style-loader','css-loader','sass-loader']},//处理scss文件的第三方loader规则

处理图片文件的第三方loader

npm i url-loader file-loader -D

其中file-loader是url-loader的依赖包,出现没有安装的依赖,需要继续安装

{test:/\.(jpg|png|bmp|jpeg|gif)$/,use:'url-loader'},//处理图片文件的第三方loader规则

loader设置参数:

{test:/\.(jpg|png|bmp|jpeg|gif)$/,use:'url-loader?limit=7631&name=[name].[ext]'}

其中limit给定值是图片的大小,单位是byte,引用的图片如果大于等于给定值,则不会转成base64格式字符串,否则转成base64格式字符串

name=[name].[ext]:[name] 代表之前什么名,转换后还是什么名;.[ext]之前什么后缀名,转换后还是什么后缀名。

如果希望前面加上hash:name=[hash:8]-[name].[ext]:[name]:天面添加8位hash值。

处理字体图标的第三方loader

使用的loader还是url-loader。这里引用bootstrap中的字体图标。

 npm i bootstrap@3.3.7 -S

注意这个案例中需要引入bootstrap@3.3.7

到bootstrap官网上找一个组件:

<span class="glyphicon glyphicon-search" aria-hidden="true"></span>

在main.js中引入bootstrap.css依赖

//如果通过路径形式引入node_modules中的相关文件,可以省略路径前面的node_modules这一层目录。默认会取node_modules中查找
import 'bootstrap/dist/css/bootstrap.css'

在webpack.config.js中添加匹配处理规则

  {test:/\.(|eot|svg|ttf|woff|woff2)$/,use:'url-loader'},//处理文字文件的第三方loader规则

注意:json文件中不能有注释

webpack中babel配置
在webpack中,默认只能处理一部分ES6的新语法,一些更高级的ES6语法或ES7语法需要借助第三方loader将其处理为低级语法后,再把结果交给webpack去打包到bundle.js中。

  1. 安装两套包,安装Babel的loader功能

    • npm i babel-core babel-loader@7 babel-plugin-transform-runtime -D
    • npm i babel-preset-env babel-preset-stage-0 -D
  2. 在webpack.config.js文件中配置匹配规则

{test:/.js&/,use:'babel-loader',exlude:/node_modules/}

exlude用来排除对应的文件包,只需要解析我们自己写的js文件。

  1. 在项目的根目录中新建一个叫 .babelrc的babel配置文件,这个配置文件属于JSON格式,所以在写.babelrc配置的时候,必须符合JSON语法规范:不能写注释,字符串必须用双引号。
  {
    "presets":["env","stage-0"],
    "plugins":["transform-runtime"]
  }

vue中render函数渲染组件

<div id="app">
  </div>

  <script>
    var login={
      template:'<h1>这是登陆组件</h1>'
    }

    var vm=new Vue({
      el:'#app',
      data:{},
      methods:{},
      //createElements是一个方法,调用它,能够把指定的组件模板渲染为HTML结构
      render:function(createElements){
        //注意,这里的return结果会替换页面中el指定的那个容器
        return createElements(login)
      }
    });
  </script>

在webpack使用vue

安装vue

npm i vue -D

在main.js中引入vue

//注意:在webpack中,使用import vue from 'vue'导入的Vue构造函数,功能不完整,
//只提供了runtime-only的方式,并没有提供像网页中那样使用方式
//方式一
import Vue from '../node_modules/vue/dist/vue.js'
//回顾包的查找规则:
//1. 查找项目根目录有没有node_modules文件夹
//2. 在node_modules中根据包名,找对应的vue文件夹
//3. 在vue文件夹中找一个叫 package.json的包配置文件
//4. 在package.json 文件中,查找一个main属性【main属性指定了这个包在被加载的时候,入口文件】


var login={
  template:'<h1>这是登陆组件</h1>'
}

var vm=new Vue({
  el:'#app',
  data:{},
  methods:{},
  //createElements是一个方法,调用它,能够把指定的组件模板渲染为HTML结构
  render:function(createElements){
    //注意,这里的return结果会替换页面中el指定的那个容器
    return createElements(login)
  }
});

引入vue的第二种方式
main.js

//方式二
import Vue from 'vue'

在webpack.config.js

resolve:{
    alias:{
      "vue$":"vue/dist/vue.js"
    }
  }

使用vue的runtime-only模式

在runtime-only模式,需要把vue模板template放到对应的.vue文件中

在src目录下建立login.vue文件

/* 模板 */
<template>
  <div>
    <h1>这是登陆组件</h1>
  </div>
</template>
/* 业务逻辑 */
<script></script>
/* 样式 */
<style></style>

安装配置处理vue文件的loader

npm i vue-loader -D

在webpack.config.js文件中配置插件

const VueLoaderPlugin = require('vue-loader/lib/plugin');

plugins:[//配置插件的结点
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
  ],

main.js

import Vue from 'vue'
import login from './login.vue'
var vm=new Vue({
  el:'#app',
  data:{},
  methods:{},
  render:function(createElements){
    return createElements(login)
  }
});

export default和export使用方法

在login.vue组件文件中,添加数据变量

<template>
  <div>
    <h1>这是登陆组件-----{{msg}}----{{title}}</h1>
  </div>
</template>

<script>
  export default{
    data(){
      //注意组件中的data必须是function
      return {
        msg:'123',
        title:'小星星'
      }
    },
    methods:{
      show(){
        console.log("调用了login.vue 中的show方法");
      }
    }
  }
</script>

<style></style>

在src目录下新建test.js

//再Node中向外暴露成员的形式:
//module.exports和exports暴露成员
//var 名称=require('模块标识符') 接收成员

//在ES6中,使用export default 和export 向外暴露成员;使用import 模块名称 from '模块路径'

//一个模块 只能使用export default向外暴露一次
export default{
  name:'ly',
  sex:'男'
}

//export可以多次使用,并且可以和export default 一起使用
export var title='大猩猩'

在main.js中引入test.js文件

//接收,其中export需要使用{}来接收,称为【按需导出】,使用as可以换名
import person,{title as title11} from './test.js'

console.log(person)
console.log(title11)

webpack 使用vue-router

  1. 安装vue-router
npm i vue-router -S
  1. 项目准备

在src目录下建立main文件夹,文件夹中建立Account.vue和GoodsList.vue

/* Account.vue */
<template>
  <div>
    <h1>这是account组件</h1>
  </div>
</template>

<script>
</script>

<style></style>

/* GoodsList.vue */
<template>
  <div>
    <h1>这是goodslist组件</h1>
  </div>
</template>

<script>
</script>

<style></style>

在src下建立新文件login.vue

<template>
  <div>
    <h1>这是登陆组件</h1>

    <router-link to="/account">Account</router-link>
    <router-link to="/goodslist">GoodsList</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
</script>

<style></style>
  1. 在main.js中引入vue-router

    //项目的js入口文件
    import Vue from 'vue'
    //1. 导入vue-router包
    import VueRouter from 'vue-router'
    import login from './login.vue'
    
    import account from './main/Account.vue'
    import goodslist from './main/GoodsList.vue'
    
    //2. 手动安装VueRouter
    Vue.use(VueRouter)
    
    //3. 创建路由对象
    var router = new VueRouter({
     routes:[
     {path:'/',redirect:'/account'},
     {path:'/account',component:account},
     {path:'/goodslist',component:goodslist}
     ]
    })
    
    var vm=new Vue({
     el:'#app',
     data:{},
     methods:{},
     render:function(createElements){
     return createElements(login)
     },
     router
    });
    

组件中style标签

  • scoped标签

在Vue组件中的style中设置样式,默认是全局效果

<style>
 div{
 font-style: italic;
 }
</style>

通过添加scoped属性来限制为当前组件的样式

<style scoped>
 div{
 font-style: italic;
 }
</style>

scoped属性是通过属性选择器的方式起作用的

  • lang标签

在style中可以使用less和scss文件格式通过lang属性来指定

<style lang="scss" scoped>
    body{
       div{
       font-style: italic;
        } 
    }   
</style>

抽离路由模块

基本原则,把路由配置部分的代码从main.js中抽离出来,放到一个和mian.js同级的文件 router.js文件中。

补充知识

  • 变异方法:修改原始数据

    • push()

    • pop()

    • shift()

    • unshift()

    • splice()

    • sort()

    • reverse()

  • 替换数组:生成新的数组

    • filter()

    • concat()

    • slice()

  • Vue数组响应式变化

    • Vue.set(vm.items,indexOfItem,newValue)

    • vm.$set(vm.item,indexOfItem,newValue)

    参数1:数组名称

    参数2:数组索引

    参数3:要处理的值

<div id="app">
        <li :key="index" v-for="(item,index) in list">{{item}}</li>
    </div>

    <script>
        var vm=new Vue({
            el:'#app',
            data: {
                list:["apple","orange","lemon"]
            },
        });

        //修改在页面无响应
        //vm.list[1]="pear";

        //响应方式1
        //Vue.set(vm.list,1,'pear');

        vm.$set(vm.list,1,'pear');

    </script>

通过上面两个方式也可以向对象中添加值

Vue.set(vm.object,‘key’,value)

插槽slot

slot基础用法

在子组件内使用元素可以为该子组件开启一个插槽,在父组件模板中,插入子组件标签内的所有内容将替代子组件的标签及它的内容。

<div id="app">
        <alert-box>有一个警告</alert-box>
        <alert-box></alert-box>
    </div>
    <script>

        //组件test-jerry
        Vue.component("alert-box", {
            template: `
                <div>
                    <span>Error:</span>
                    <slot>默认值</slot>
                </div> 
            `
        });

        var vm = new Vue({
            el: '#app',
            data: {

            }
        });

    </script>

在这里插入图片描述

具名插槽

给组件中的元素指定一个name可以在父组件中指定内容填充到子组件中,父组件中没有对应的name会填充到匿名slot中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <style>
        .header{
            color: red;
        }

        .footer{
            color: blue;
        }
    </style>
</head>
<body>
    <div id="app">
        <base-layout>
            <!-- <p slot="header">标题信息</p>
            <p >主要内容1</p>
            <p >主要内容2</p>
            <p slot="footer">底部信息</p> -->

            <!-- template标签起到打包多个内容插入指定name的插槽中 -->
            <template slot="header">
                <div>
                    <p slot="header">标题信息1</p>
                    <p slot="header">标题信息2</p>
                </div>
            </template>
            <p >主要内容1</p>
            <p >主要内容2</p>
            <template slot="footer">
                <div>
                    <p slot="footer">底部信息1</p>
                    <p slot="footer">底部信息2</p>
                </div>
            </template>
            <!-- 填充到子组件中的匿名slot中 -->
            <p >主要内容3</p>
        </base-layout>
    </div>

    
    <script>

        Vue.component("base-layout",{
            template:`
            <div>
                <header class='header'>
                    <slot name='header'></slot>
                </header>
                <main>
                    <slot></slot>
                </main>
                <footer  class='footer'>
                    <slot name='footer'></slot>
                </footer>
            </div>
            `
        })
        var vm=new Vue({
            el:'#app'
        })
    </script>
</body>
</html>

上面案例运行结果图:

在这里插入图片描述

作用域插槽

应用场景:父组件对子组件的内容进行加工处理

<div id="app">
        <fruit-list :list='list'>
            <!-- 插槽内容:template包裹,通过slot-scope属性获取子组件中插槽中的数据(slotProps随便命名) -->
            <template slot-scope='slotProps'>
                <strong v-if="slotProps.item.id==1">{{slotProps.item.name}}</strong>
                <span v-else>{{slotProps.item.name}}</span>
            </template>
        </fruit-list>
    </div>
    <script>

        Vue.component("fruit-list",{
            props:['list'],
            template:`
            <div>
                <li :key='item.id' v-for='(item,index) in list'>
                    <!-- 插槽定义:使用v-bind来绑定一个变量来传递给父组件,item随便命名 -->
                    <slot v-bind:item='item'>
                        {{item.name}}
                    </slot>
                </li>
            </div>
            `
        })
        var vm=new Vue({
            el:'#app',
            data:{
                list:[
                    {
                        id:1,
                        name:'apple'
                    },
                    {
                        id:2,
                        name:'orange'
                    },
                    {
                        id:3,
                        name:'banana'
                    }
                ]
            }
        })
    </script>

vue前后端交互

Promise用法

  1. 实例化Promise对象,构造函数中传递函数,该函数用于处理异步任务。

  2. resolve和reject两个参数用于处理成功和失败两种情况,并通过p.then获取处理结果。

<script>
        var p=new Promise(function(resolve,reject){
            var flag=true;
            if(flag){
                resolve('hello world!');
            }else{
                reject('错误结果');
            }
        });

        p.then(function(ret){
            //从resolve处理逻辑
            console.log(ret);
        },function(ret){
            //reject处理逻辑
            console.log(ret);
        });
    </script>
  • 基于Promise处理Ajax请求

这里需要了解一下原生ajax请求步骤

<script>
        //基于Promise处理Ajax请求

        function queryData(url){
            var p=new Promise(function(resolve,reject){

                var xhr=new XMLHttpRequest();
                xhr.onreadystatechange=function(){
                    if(xhr.readyState!=4) return;
                    if(xhr.readyState==4&& xhr.status==200){
                        //处理正常的情况
                        resolve(xhr.responseText);
                    }else{
                        reject('服务器错误');
                    }
                }

                xhr.open('get',url);
                xhr.send(null);
            });

            return p;

        }

        queryData(url1)

            .then(function(data){
                console.log(data);
                //小技巧:返回下一个需要请求的对象,可以直接在后面使用.then()方法
                return queryData(url2);

            })
            .then(function(data){
                console.log(data);
            })  

    </script>
  • then参数中的函数返回值

    1. 返回Promise实例对象

    返回的实例对象会调用接下来的then,就是上面案例所示。

    1. 返回普通值

    返回的普通值会直接传递给下一个then(),通过then()参数中的函数来接收该值,因为没有返回Promise对象,默认会创建一个Promise对象,所以依旧可以调用then()方法。

    queryData(url)
    
               .then(function(data){
    
                    console.log(data);
                    //小技巧:返回下一个需要请求的对象,可以直接在后面使用.then()方法
                    return "hello";
                })
                .then(function(data){
                    console.log(data);
                })
    
  • Promise的实例方法

    • p.then():得到异步任务的结果

    • p.catch():获取异常信息

    • p.finally():成功与否都会执行

    <script>
                    var p=new Promise(function(resolve,reject){
                        var flag=false;
                        if(flag){
                            resolve('hello world!');
                        }else{
                            reject('错误结果');
                        }
                    });
    
                    p.then(function(ret){
                        //从resolve处理逻辑
                        console.log('then:'+ret);
                    })
                    //当执行reject时,会执行,相当于then方法中第二个函数
                    .catch(function(data){
                        console.log("catch:"+data);
                    })
                    //无论成功失败,都会执行
                    .finally(function(){
                        console.log('finally');
                    })
                </script>
    
  • Promise中对象方法

    • Promise.all()并发处理多个异步任务,所有任务都执行完成才得到结果

    • Promise.race()并发处理多个异步任务,只要一个任务完成就得到结果,其他的异步任务也会执行,但是不获取结果。

    //获取p1,p2,p3对应的返回结果
    Promise.all([p1,p2,p3]).then((result)=>{
        console.log(result)
    })
    //只获取p1对应的返回结果
    Promise.race([p1,p2,p3]).then((result)=>{
     console.log(result)
    })
    

fetch 用法

  • fetch基础用法
fetch(url).then(function(data){
            //返回Promise对象,用于获取后台返回的数据
            return data.text();
        })
        //Promise通过then方法,来处理其中的数据
        .then(function(data){
            console.log(data);
        })
  • fetch请求参数

常用配置选项

method(String):HTTP请求方法,默认为Get(POST、PUT、DELETE)

body(String):http请求的参数

header(Object):http请求头,默认为{}
fetch(url,{
            method:'get'
        }).then(function(data){
            //返回Promise对象,用于获取后台返回的数据
            return data.text();
        })
        //Promise通过then方法,来处理其中的数据
        .then(function(data){
            console.log(data);
        })

Get和Delete方式传参数一般有两种:?xxx=‘xxx’&yyy=‘yyy’,vue通过 query获取

/:id/name ,vue中通过params获取

post和put传参

//字符串格式
        fetch(url,{
            method:'post',
            body:'name=lisi&pwd=123',
            headers:{
                'Content-Type':'application/x-www-form-urlencoded'
            }
        }).then(function(data){
            //返回Promise对象,用于获取后台返回的数据
            return data.text();
        })
        //Promise通过then方法,来处理其中的数据
        .then(function(data){
            console.log(data);
        })

        //json格式
        fetch(url,{
            method:'post',
            body:JSON.stringify({
                name:'lisi',
                pwd:'123'
            }),
            headers:{
                'Content-Type':'application/json'
            }
        }).then(function(data){
            //返回Promise对象,用于获取后台返回的数据
            return data.text();
        })
        //Promise通过then方法,来处理其中的数据
        .then(function(data){
            console.log(data);
        })

vue脚手架

创建vue项目

查看版本

vue -V

  • 基于3.x版本的脚手架创建Vue项目:

安装

npm install -g @vue/cli 1).使用命令创建Vue项目
命令:vue create my-project
选择Manually select features(选择特性以创建项目)
勾选特性可以用空格进行勾选。
是否选用历史模式的路由:n
ESLint选择:ESLint + Standard config
何时进行ESLint语法校验:Lint on save
babel,postcss等配置文件如何放置:In dedicated config files(单独使用文件进行配置)
是否保存为模板:n
使用哪个工具安装包:npm

  • 基于ui界面创建Vue项目
    命令:vue ui
    在自动打开的创建项目网页中配置项目信息。

  • 基于2.x的旧模板,创建Vue项目
    npm install -g @vue/cli-init
    vue init webpack my-project

  • 分析Vue脚手架生成的项目结构
    在这里插入图片描述

    node_modules:依赖包目录
    public:静态资源目录
    src:源码目录
    src/assets:资源目录
    src/components:组件目录
    src/views:视图组件目录
    src/App.vue:根组件
    src/main.js:入口js
    src/router.js:路由js
    babel.config.js:babel配置文件
    .eslintrc.js: eslint语法配置文件

配置vue项目

配置项目启动自动打开浏览器及端口:

  1. 在package.json中
"vue":{
    "devServer":{
      "port":8888,
      "open":true
    }
  }
  1. 在项目根目录下创建 vue.config.js文件
module.exports={
    devServer:{
        //自动打开浏览器
        open:true,
        port:8878
    }
}

注意: 两种配置方式只能同时使用一种

Element-UI

Element-UI:一套为开发者、设计师和产品经理准备的基于Vue 2.0的桌面组件库

基于命令行方式手动安装

  1. 安装依赖包

npm i element-ui -S

  1. 导入Element-UI相关资源
//导入element-ui库
import ElementUI from 'element-ui'
//导入element-ui相关样式
import 'element-ui/lib/theme-chalk/index.css'
//配置Vue插件
Vue.use(ElementUI)

基于图形化界面自动安装

  1. 运行vue ui命令,打开图形化界面

  2. 通过vue项目管理器,进入具体的项目配置面板

  3. 点击插件->添加插件,进入插件查询面板

  4. 搜索vue-cli-plugin-element并安装

  5. 配置插件,实现按需导入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值