Vue.js简单基础入门(MVVM模式+vue生命周期+指令+组件化)

1.MVVM模式

  • M:模型,包括数据和一些基本操作。
  • V:视图、页面渲染结果。
  • VM:View-Nodel,模型与视图间的双向操作(无需开发人员干涉)。
    在这里插入图片描述
    官网:https://cn.vuejs.org/v2/guide/
    github:https://github.com/vuejs

2.Node和NPM

下载之后,在控制台中查看node-v和npm -v查看是否自动配置好环境变量。
npm默认的仓库地址是在国外网站,速度较慢,建议设置淘宝镜像。但是切换镜像是比较麻烦的,推荐一款切换镜像工具:nrm。

首先安装nrm,-g代表全局安装
npm install nrm -g
在这里插入图片描述

3.快速入门

3.1新建项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2项目初始化

npm init -y
在这里插入图片描述
初始化之后项目下面多了一个package.json
在这里插入图片描述

3.3安装vue

–save 只针对项目使用
-g 全局使用
在这里插入图片描述
安装之后,项目多了一个文件夹。
在这里插入图片描述

3.4编写html

3.4.1 新建html

在这里插入图片描述

3.4.2 在html中引入依赖

<script src="node_modules/vue/dist/vue.js"></script>

在这里插入图片描述

3.4.2 入门实例

vue实例

new vue({})

<body>
<div id="app">
    <h1>
        {{name}}非常帅!
    </h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"jack",
        }
    });
</script>
</body>

在这里插入图片描述
F12,去修改name属性,vue会监测属性值的变化。
在这里插入图片描述

v-model双向绑定

v-model:模型数据,即有v-model表示的标签与模型数据关联。

<body>
<div id="app">
    <input type="text" v-model="num">
    <h1>
        {{name}}非常帅!<br>
        {{num}}个人。
    </h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"jack",
            num:1,
        }
    });

</script>
</body>

因为input框中数据与模型数据关联,所以无论谁改变都会影响到另一个的改变。
在这里插入图片描述
在这里插入图片描述

事件绑定

@click=函数

@click="num++”

<div id="app">
    <input type="text" v-model="num">
    <button @click="num++">+</button>
    <h1>
        {{name}}非常帅!<br>
        {{num}}个人。
    </h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"jack",
            num:1,
        }
    });

</script>
</body>

点击“+”,num就加一。
在这里插入图片描述

@click=方法名
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <button @click="handleClick">hello</button><br>
    <input type="text" v-model="num">
    <h1>
        {{name}}非常帅!<br>
        {{num}}个人。
    </h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"jack",
            num:1,
        },
        methods:{
            handleClick(){
                console.log("hello");
            }
        }
    });

</script>
</body>
</html>

在这里插入图片描述

3.5vue的生命周期

在这里插入图片描述

  • 初始化
  • 页面渲染
  • 是否有el或template元素,若el或template存在就找到关联的html标签,对标签进行编译(对vue代码编译成浏览器可以识别的代码),然后创建真实的html代码,把它挂在el或template关联的元素上。
    挂载之前交beforeMount,挂载之后叫mounted。
  • dom元素的重新渲染和挂载。
    执行之前叫beforUpdate,之后叫updated。
  • 销毁
    销毁之前叫beforeDestory,销毁之后叫Destoryed。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <button @click="handleClick">hello</button><br>
    <input type="text" v-model="num">
    <h1>
        {{name}}非常帅!<br>
        {{num}}个人。
    </h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"jack",
            num:1,
        },
        methods:{
            handleClick(){
                console.log("hello");
            }
        },
        created(){
            //向后台发起ajax请求,完成对data数据初始化,延迟1s后再赋值
            setTimeout(() => this.name = "li",1000);

        }
    });

</script>
</body>
</html>

在这里插入图片描述
1s后
在这里插入图片描述

4.指令

指令是带有v-前缀的特殊属性。eg:v-model,代表双向绑定。
@click = v-on:click

4.1插值表达式

4.1.1花括号

{{}}

4.1.2插值闪烁

当用户网速延迟时使用{{}}会出现问题,在数据未加载完成时,页面会显示出原始的{{}},加载完毕后才显示正确数据,称为插值闪烁。
测试:
将网速调慢
在这里插入图片描述
在这里插入图片描述

4.1.3解决插值闪烁v-text,v-html

这两个都是单向绑定。
使用v-text和v-html来替代{{}}。

  • v-text:将数据输出到元素内部,如果输出的数据中有html代码,html代码会原样输出。
  • v-html:将数据输出到元素内部,若输出的数据中有html代码,会被渲染。

v-text和v-html的区别:

 <span v-text="name"></span><br>
    <span v-html="name"></span>
 el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
        },
        methods:{
            handleClick(){
                console.log("hello");
            }
        },
        created(){
            //向后台发起ajax请求,完成对data数据初始化,延迟1s后再赋值
            //setTimeout(() => this.name = "li",1000);

        }
    });

在这里插入图片描述
但是v-html不安全,若黑客利用v-html传输,就会在页面上挂木马。

4.2 v-model

双向绑定。
用户可以输入可以操作的都可以使用v-model。

 <input type="checkbox" value="java" v-model="lessons"/>java<br>
    <input type="checkbox" value="ios" v-model="lessons"/>ios<br>
    <input type="checkbox" value="php" v-model="lessons"/>php<br>
    <h1>您已购买下列课程:{{lessons.join(",")}}</h1>
 const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[]
        } 
    });

在这里插入图片描述

4.3 v-on

4.3.1基本用户

v-on用于给页面元素绑定事件。
语法:@事件名=“js片段或者函数名”

4.3.1.1事件冒泡

<div style="width:100px;height: 100px;background-color: cadetblue" @click="print('div')">
        <button @click="print('button')">点我试试</button>
    </div>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[]
        },
        methods:{
            handleClick(){
                console.log("hello");
            },
            print(msg) {
                console.log(msg);
            }
        }
    });

点击div时:
在这里插入图片描述
点击button时:
在这里插入图片描述
当子元素父元素都有点击事件,当点击子元素的点击事件时,父元素的也被触发了,这就叫事件冒泡。

4.3.1.1解决事件冒泡

在子元素的时间上加上.stop

 <button @click.stop="print('button')">点我试试</button>

事件委托

4.4事件修饰符

在事件处理程序中调用event.preventDefault或event.stopPropagation()是非常常见的需求。
vue.js为v-on提供了事件修饰符:

  • .stop:阻止事件冒泡。
  • .prevent:阻止默认事件发生。
  • .eapture:使用事件捕获模式。
  • .self:只有元素自身出发事件才执行。(冒泡或捕获的都不执行)。
  • .once:只执行一次。

阻止默认事件发生

<div style="width:100px;height: 100px;background-color: cadetblue" @click="print('div')">
        <button @click.stop="print('button')">点我试试</button>
        <a href="http://www.baidu.com" @click.prevent="print('百度')">百度一下!</a>
    </div>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[]
        },
        methods:{
            handleClick(){
                console.log("hello");
            },
            print(msg) {
                console.log(msg);
            }
        }
    });

</script>

点击百度一下,并没有跳转到href指定的url。
在这里插入图片描述

4.5 v-for

4.5.1遍历数组

4.5.1.1只取数组中对象(一个参数)

<ul>
        <li v-for="user in users">{{user.name+","+user.age}}</li>
    </ul>
    <hr>
    <ul>
        <li v-for="user in users"><p v-text="user.name+','+user.age"></p></li>
    </ul>
 const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[],
            users:[
                    {name:"li",age:21,gender:"女"},
                    {name:"wang",age:20,gender:"男"},
                    {name:"liu",age:21,gender:"女"},
                    {name:"zhang",age:21,gender:"男"}
            ]
        }
    })

在这里插入图片描述

4.5.1.2数组角标

在遍历过程中,如果我们需要知道数组角标,可以指定第二个参数。

 <ul>
        <li v-for="(user,index) in users">{{index}}-{{user.name+","+user.age}}</li>
    </ul>
    <hr>
    <ul>
        <li v-for="(user,index) in users"><p v-text="index+'-'+user.name+','+user.age"></p></li>
    </ul>

const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[],
            users:[
                    {name:"li",age:21,gender:"女"},
                    {name:"wang",age:20,gender:"男"},
                    {name:"liu",age:21,gender:"女"},
                    {name:"zhang",age:21,gender:"男"}
            ]
        }
    })

在这里插入图片描述

4.5.2遍历对象

4.5.2.1遍历对象属性

<ul>
        <li v-for="user in users[0]"><p v-text="user"></p></li>
    </ul>
    <ul>
        <li v-for="(v,k,i) in users[0]"><p v-text="i+':'+k+','+v"></p></li>
    </ul>
const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[],
            users:[
                    {name:"li",age:21,gender:"女"},
                    {name:"wang",age:20,gender:"男"},
                    {name:"liu",age:21,gender:"女"},
                    {name:"zhang",age:21,gender:"男"}
            ]
        }
    })

在这里插入图片描述

4.5.3遍历常量

<ul>
        <li v-for="i in 5"><p v-text="i"></p></li>
    </ul>

在这里插入图片描述

4.5.4 key

vue.js用v-for,当数据发生改变时,v-for需要重新从开始变迁来渲染元素列表,这样效率会低,vue有内部优化,就是使用:key=“这个标签关联的唯一标识”。

 <ul>
        <li v-for="(user,index) in users" :key="index"><p v-text="index+'-'+user.name+','+user.age"></p></li>
    </ul>

该例子中绑定的key是数组的索引,是唯一的。

4.6 v-if与v-show

判断,如果为true,则渲染,否则不渲染。

语法:
v-if=“表达式”

4.6.1 v-if

<button @click="show = !show">点击切换</button><br>
    <h1 v-if="show">你好!</h1>
const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            name:"<font color='#a52a2a'>jack</font>",
            num:1,
            lessons:[],
            users:[
                    {name:"li",age:21,gender:"女"},
                    {name:"wang",age:20,gender:"男"},
                    {name:"liu",age:21,gender:"女"},
                    {name:"zhang",age:21,gender:"男"}
            ],
            show: true,
        }
    })

在这里插入图片描述
点击后
在这里插入图片描述

4.6.2v-if和v-for结合使用

<ul>
        <li v-for="i in 5" v-if="i%2 === 0"><p v-text="i"></p></li>
    </ul>

在这里插入图片描述

4.6.3v-if与v-else

 <ul>
        <li v-for="i in 5">
            <p v-if="i%2 === 0" >{{i}}</p>
            <p v-else style="background-color: cadetblue">{{i}}</p>
        </li>
    </ul>

在这里插入图片描述

4.6.4v-if、v-else、v-else-if

<ul>
        <li v-for="i in 7">
            <p v-if="i <= 5 " >工作日</p>
            <p v-else-if="5 < i < 7" style="background-color: cadetblue">星期{{i}}</p>
            <p v-else style="background-color: cadetblue">星期{{i}}</p>
        </li>
    </ul>

在这里插入图片描述

4.6.4v-show

<button @click="show = !show">点击切换</button><br>
    <h1 v-if="show">你好!</h1>
    <h1 v-show="show">hello!</h1>

在这里插入图片描述
点击切换后
在这里插入图片描述
v-if标识的标签直接从html页面上消失了,而v-show标识的标签是通过css样式来控制。从性能方面看v-show更好,从安全角度v-if更好。
页面加载时的一次性的判断,针对不同用户角色显示不同内容,使用v-if合适,防止通过源码查看。
v-show适合需要多次加载经常切换的场景。

4.7v-bind

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            color: darkgray;
        }
        .red{
            background-color: red;
        }
        .blue{
            background-color: blue;
        }
    </style>
</head>
<body>
<div id="app">
    <button @click="color='red'">红色</button>
    <button @click="color='blue'">蓝色</button>
    <div id="box" v-bind:class="color">box</div>

</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            color: "red",

        },
        methods:{

        }
    });

</script>
</body>
</html>

在这里插入图片描述
点击蓝色按钮
在这里插入图片描述
注意:
class="{{color}}"这样写是不可以的,插值表达式不能用在标签的属性中。
可以使用v-bind:class="color"或者:class=“color”。

优化代码

把class作为一个对象。
通过对象去指定。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            color: darkgray;
        }
        .red{
            background-color: red;
        }
        .blue{
            background-color: blue;
        }
    </style>
</head>
<body>
<div id="app">
    <button @click="isred = !isred">点我</button>
    <div id="box" v-bind:class="{red:isred,blue:!isred}">box</div>

</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            color: "red",
            isred:true,

        },
        methods:{

        }
    });

</script>
</body>
</html>

在这里插入图片描述
点击按钮
在这里插入图片描述

4.8计算属性

<!-- 计算属性-->
    <h1>
        日期:{{birth}}
    </h1>
const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            isred:true,
            birthday: 1529032123201

        },
        computed:{
            birth(){
                const day = new Date(this.birthday);
                return day.getFullYear()+"-"+day.getMonth()+"-"+day.getDay();
            }
        },
    });

他只在最开始计算一次。后续再使用,就不会再计算,会直接渲染。

4.8watch

4.8.1浅监控

 const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            isred:true,
            birthday: 1529032123201,
            num:1,
            person:{name:"jack",age:21}

        },
        computed:{
            birth(){
                const day = new Date(this.birthday);
                return day.getFullYear()+"-"+day.getMonth()+"-"+day.getDay();
            }
        },
        watch:{
            <!--浅监控-->
            num(arg1,arg2){
                console.log(arg1,arg2);
            },
           
            }
        }
    });

能监控值的变化,上个值和现在的值为多少。
在这里插入图片描述

4.8.2 深监控

 const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            isred:true,
            birthday: 1529032123201,
            num:1,
            person:{name:"jack",age:21}

        },
        computed:{
            birth(){
                const day = new Date(this.birthday);
                return day.getFullYear()+"-"+day.getMonth()+"-"+day.getDay();
            }
        },
        watch:{
            //写成一个对象
            person:{
                <!--person地址发生改变可以监控到,但是引用发生改变就监控不到了-->
                <!--加上该属性就是深度监控-->
                deep:true,
                <!--定义一个方法,方法名必须为handler-->
                handler(val){
                    console.log(val.age);
    }


            }
        }
    });

在这里插入图片描述

5.组件化

在开发大型应用时,页面可以分成很多部分,往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

5.1定义全局组件

使用vue的静态方法component(“组件id-String”,“定义组件{}”)
vue组件也是一个vue实例。
vue组件的定义方式和vue实例的定义方式几乎一样。vue实例的定义是跟html绑定了。
案例:

<body>
<div id="app">
    <!-使用自定义组件--->
    <conter></conter>

</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    //定义全局组件,参数:组件id,
    Vue.component("conter",{
        template:"<button @click='count++'>点我{{count}}次!</button>",
        data(){
            return{
                count:0
            }
        }
    })
    //vue实例
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
        
        }
    });
</script>
</body>

重复使用自定义组件,不会共享属性。
在这里插入图片描述

  • 组件其实也是一个vue实例,因此他在定义时也会接受:data、method、生命周期函数等。
  • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
  • 但是组件渲染需要html模板,所以增加了template属性,值就是html模板。
  • 全局组件定义完毕,任何vue实例都可以直接在html中通过组件名称来使用组件了。
  • data的定义方式比较特殊,必须是一个函数。

5.2局部注册

局部组件就是个变量,需要把它声明到vue实例内部。

<body>
<div id="app">
    <!-使用自定义组件--->
    <conter></conter>
    <conter></conter>
    <conter></conter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    //定义全局组件,参数:组件id,
   /* Vue.component("conter",{
        template:"<button @click='count++'>点我{{count}}次!</button>",
        data(){
            return{
                count:0
            }
        }
    })*/
    //局部组件,只能在当前实例中使用。
    const conter = {
        template:"<button @click='count++'>点我{{count}}次!</button>",
        data(){
            return{
                count:0
            }
        }
    }
    //vue实例
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{

        },
        components:{
        //若key=value完全一致,可以简写成conter.
            conter:conter
        }
    });

</script>
</body>

components就是当前vue对象子组件集合。(key就是子组件名称,value就是组件对象属性)
想过与全局注册类似,不同的是,局部组件只能在当前vue实例中使用。

5.3组件通信

通常一个单页应用会以一棵嵌套的组件树的形式来组织:
在这里插入图片描述
每个组件之间以潜逃的关系组合在一起,那么这时就需要有组件间通信。

5.3.1父向子传递props

5.3.1.1传递常量

<body>
<div id="app">
    <introduce :title="msg"></introduce>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    //局部组件,只能在当前实例中使用。
    const introduce = {
        template:"<h1>{{title}}</h1>",
        props:['title']
    }
    //vue实例
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            msg: "hello!"
        },
        components:{
            introduce
        }
    });
</script>
</body>

在这里插入图片描述

5.3.1.2传递数组

<div id="app">
    <for-component :items="lessons"></for-component>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    //定义局部组件,他是一个对象。
    const forComponent = {
        template: "<ul><li v-for='item in items'>{{item}}</li></ul>",
        //传递的组件中的属性名,使用的时候:属性名=“父类中的变量名”
        props:['items']
    }
    //vue实例
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            msg: "hello!",
            lessons:['java','php','ios']
        },
        components:{
           forComponent
        }
    });
</script>
</body>

在这里插入图片描述

5.3.2子向父传递props

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
<!-- 需要自定义事件-->
    <counter :num="count" @incr="add" @decr="reduce"></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const counter = {
        //在子组件中修改值,当父亲改的时候,会覆盖掉子组件中的值。所以应该在父组件中修改值。
        //修改前:template: "<button @click='num++'>点了{{num}}次!</button>",
        //修改后,要调用父组件的方法,就是子向父通信。
        template: `
        <div>
            <button @click="handleAdd">+</button>
            <button @click="handleReduce">-</button>
            <h1>
            num:{{num}}
            </h1>
        </div>
        `,
        //传递的组件中的属性名,使用的时候:属性名=“父类中的变量名”
        props:['num'],
        methods: {
            //触发事件
            handleAdd(){
                this.$emit('incr');
            },
            handleReduce(){
                this.$emit('decr')
            }
        }
    }
    //vue实例
    const app =new Vue({
        el:"#app",//element元素,一个标签就是一个元素,即vue所作用的标签
        data:{
            count:0
        },
        components:{
            counter
        },
        methods:{
            add(){
                this.count++;
            },
            reduce(){
                this.count--;
            }
    }
    });

</script>
</body>
</html>

在这里插入图片描述

发布了28 篇原创文章 · 获赞 0 · 访问量 900

猜你喜欢

转载自blog.csdn.net/weixin_43876557/article/details/102699654
今日推荐