Vue基础篇:模板语法,数据绑定(MVVM),事件,计算属性,监听属性,渲染,表单数据手机,过滤器,指令,生命周期,组件

Vue

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

作者:尤雨溪

特点:

  • 遵循MVVM模式
  • 编码简洁,体积小,运行效率高
  • 本身只关注于UI,可以引入第三方库

Vue的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

  1. 导入Vue
  2. 准备Vue容器
  3. 创建Vue实例
  4. 声明式渲染:{{}} -->插值表达式
<body>
  <div id="app" >
    <h1>Hellp,{{name}}</h1>
  </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
  const vm =  new Vue({
    el : '#app',    // 绑定容器
    data:{
      name :'张三'
    }
  });
</script>

总结:

  1. 想让Vue工作,创建Vue实例,并且传入配置对象
  2. 准备一个容器,并命名 id=‘app’ ,容器中的代码要符合HTML规范,但是可以包含Vue 的语法。
  3. app容器中的代码称为Vue模板
  4. Vue实例与容器是一一对应的
  5. {{xxx}} xxx是 js表达式 并且 xxx可以读取到data中的所有的属性
  6. 一旦data中的数据发生改变,模板中的变量也会自动更新

模板语法

<body>
  <div id="app">
      <!--插值表达式-->
      <h1>你好,{{name}}</h1>
      <hr/>
      <!--指令语法  v-test 文本插入 -->
      <h1 v-text="'Hello,'+name"></h1>
      <!--  v-bind:xxx 属性定义 -->
      <a v-bind:href = "url">点击跳转百度</a>
      <!--简写v-bind:xxx  :xxx -->
      <input :value="name" ></input>
  </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
        el:'#app',
        data:{
            name:'张三',
            url:'https://www.baidu.com'
        }
    });
</script>
  1. 插值表达式

    用于解析标签的内容(文本)

    {{xxx}} xxx js的表达式,可以读取到data中的所有属性

  2. 指令语法

    用于解析标签(标签的属性,标签的文本内容,标签的事件…)

    Vue的指令多数以v-开头

数据绑定

<body>
    <div id="root">
        <!--单向数据绑定-->
        <input type="text" :value="name" ><br/>
        <!--<input type="text" v-bind:value="name">-->

        <!--双向数据绑定-->
        <input type="text" v-model="name">
        <!-- 双向数据绑定 -->
        <!--<input type="text" v-model:value="name">-->
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    let vm = new Vue({
        el: "#root",
        data:{
            name:'张三'
        }
    });
</script>

Vue中有两种数据绑定方式:

  1. 单向数据绑定

    v-bind:xxx 数据只能从data到页面

  2. 双向数据绑定

    v-model:value 双向数据绑定不仅能从data到页面,也能从页面到data

    v-model一般用于表单元素,比如input,select …

data与el的两种写法

<body>
    <div id="root">
        <h1>{{name}}</h1>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
      // 第一种写法
       el:"#root",
        data(){
           return {
               name:'张三'
           }
        }
    });

    // 第二种el的写法
    vm.$mount('#root');
</script>

el与data的两种写法

  1. 创建Vue实例在配置el属性
  2. 先创建Vue的实例在通过$mount 配置容器

data的写法:

  1. 对象式:data:{}
  2. 函数式:data(){return {} },不能适应箭头函数 否则this就不是Vue实例

模拟Vue双向数据绑定

<style>
    #myInput {
        width: 400px;
        height: 50px;
        font-size: 40px;
        color: red;
    }
    #contain {
        overflow: auto;
        margin-top: 20px;
        width: 400px;
        height: 200px;
        border: 1px solid salmon;
    }
</style>
<body>
    <input id="myInput" type="text"/>
    <div id="contain">

    </div>
</body>
<script type="text/javascript">
    let oIn = document.getElementById("myInput");
    let oDiv = document.getElementById("contain");
    let text;
    window.data = {};
    oIn.addEventListener('input', function (e) {
        //获取当前input的value属性
        text = e.target.value;
        window.data.value = text;
    });

    Object.defineProperty(window.data,'value',{
        get(){
            return this.value;
        },
        set(v){
            oDiv.innerHTML = v;
        }
    })
</script>

MVVM模式

在这里插入图片描述

  • M:模型Model data中的数据
  • V:视图View 模板中的代码
  • VM:视图模型 (ViewModel) Vue实例

数据代理

  1. data中的所有属性,最终出现在VM身上
  2. VM身上的所有属性以及Vue原型上的所有的属性都可以在模板中使用

在这里插入图片描述

  • Vue中的数据通过vm对象来代理data中的所有属性的读写

  • Vue中的数据代理的好处:更方便操作data中的数据

  • 原理:

    1. 通过Object.defineProperty() 把data对象中的所有的属性都添加到vm
    2. 为每一个vm上的属性 ,都指定一个setter、getter
    3. 在getter、setter的内部 进行读写操作,操作data中对应的属性

事件

事件修饰符

绑定事件写法1:v-on:xxx

绑定事件写法2:@xxx

  1. 阻止默认行为:@click.prevent
  2. 事件占位符: e v e n t (给函数传参时,需要用 event (给函数传参时,需要用 event(给函数传参时,需要用event占位)
  3. 阻止事件冒泡:@click.stop
  4. 不管点击多少次,只执行一次:@click.once
  5. @click.capture 用于捕获模式下的事件处理。当一个事件被触发时,它会从内部元素向外部元素传播,直到到达根元素
  6. @wheel.passive 事件的默认行为立即执行,无需等待事件的回调
<style>
    * {
        margin-top: 20px;
    }
    .demo{
        height: 50px;
        background-color: pink;
    }
    .box1 {
        padding: 5px;
        background-color: green;
    }

    .box2 {
        padding: 5px;
        background-color: orange;
    }

    .list {
        width: 200px;
        height: 200px;
        background-color: peachpuff;
        overflow: auto;
    }

    li {
        height: 100px;
    }
</style>
<body>
    <div id="root">
        <!--绑定事件写法1:v-on:xxx  -->
        <!--绑定事件写法2:@xxx -->
        <a v-on:click="showInfo" :href="url">点击跳转百度</a>

        <!--@click.prevent 阻止默认行为-->
        <!--绑定点击事件  @click-->
        <a @click.prevent="showInfo" :href="url">点击跳转百度</a>

        <!--$evnet   事件占位符-->
        <button @click="showName($event,'事件占位符测试')">事件占位符测试</button>

        <!--@click.stop  阻止冒泡-->
        <div class="demo1" @click="showInfo">
                <button @click.stop="showInfo">点击测试冒泡</button>
        </div>

        <!--@click.once 不管点击多少次,只执行一次-->
        <button @click.once="showInfo">点击执行一次</button>

        <!--@click.capture  用于捕获模式下的事件处理。当一个事件被触发时,它会从内部元素向外部元素传播,直到到达根元素。-->
        <!--下面案例先触发A,再触发B-->
        <div class="box1" @click.capture="showMsg('A')">
            div1
            <div class="box2" @click="showMsg('B')">
                div2
            </div>
        </div>

        <!--wheel.passive 事件的默认行为立即执行,无序等待事件的回调-->
        <ul class="list" @wheel.passive="demo">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
        data(){
            return {
                url:'https://www.baidu.com'
            }
        },
        methods:{
            showInfo(){
                console.log('这是一个函数')
            },
            showName(event,msg){
                console.log(msg);
            },
            showMsg(msg){
                console.log(msg)
            },
            demo(){
                for(let i = 0;i<1000;i++){
                    console.log("*.*")
                }
                console.log("执行结束")
            }
        }
    });
    vm.$mount("#root");
</script>

键盘事件

<body>
    <div id="root">
        <input type="text" v-model="name" @keydown.enter="demo" >
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
        data(){
            return {
                name :'张三'
            }
        },
        methods:{
            demo(event) {
                console.log(event.key)
                console.log(event.keyCode)
            }
        }
    });
    vm.$mount("#root")
</script>

@keydowm.xxx

  1. enter:按回车触发
  2. esc 退出
  3. space 空格
  4. delete 删除 退格(Backspace)
  5. table
  6. up…

计算属性

使用场景:通过已有属性生成一个新的属性

<body>
    <div id="root">
        姓:<input type="text" placeholder="请输入姓" v-model="fName" ><br/>
        名:<input type="text" placeholder="请输入名" v-model="lName">
        <hr/>
        <h3>姓名:{{fullName}}</h3>
        <!--存在缓存,可以二次复用-->
        <h3>姓名:{{fullName}}</h3>
        <h3>姓名:{{fullName}}</h3>
        <hr/>
        <input type="text" v-model="fullName">
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
       data(){
           return {
               fName:'',
               lName:''
           }
       },
        methods:{},
        computed:{
           // 简写计算属性  只读
           //  fullName(){
           //      return this.fName+this.lName;
           //  }
            fullName:{
                get(){
                    console.log("执行了Get")
                    return this.fName+'-'+this.lName;
                },
                set(value){
                    console.log(value);
                    let arr = value.split("-");
                    this.fName=arr[0];
                    this.lName=arr[1];
                }
            }
        }
    });
    vm.$mount("#root");
</script>

计算属性:

  1. 有缓存 可以复用
  2. 当参与计算属性的属性发生改变时 会再次执行
  3. 当需要一个属性但是不存在,需要使用已有属性计算新的属性
  4. get 在初次读取时会执行一次
  5. 计算属性最终会出现在vm上 可以直接调用

监听属性

<body>
    <div id="root">
        <h2>a的值:{{nums.a}}</h2>
        <button @click="nums.a++">点击a++</button>
        <h2>b的值:{{nums.b}}</h2>
        <button @click="nums.b++">点击b++</button>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
       data(){
           return {
               nums:{
                   a:1,
                   b:2
               }
           }
       },
        methods:{},
        watch:{
            nums:{
                immediate:true,
                deep:true,
                handler(newValue,oldValue){
                    console.log(newValue,oldValue)
                }
            }
        }
    });
    vm.$mount("#root")
</script>
  1. 当被监视的属性改变时,回调函数会自动调用。

  2. 监视的属性必须存在才能进行监视

  3. 监视属性两种写法:

    • 在创建实例时 传入watch配置,如上述案例
    • 通过vm.$watch
       vm.$watch('nums.a', {
            immediate: true,
            // deep:true, //深度监视
            handler(newValue, oldValue) {
                console.log(newValue, oldValue)
            }
        })
    
  4. 深度监视: deep:true

  5. Vue 的watch默认不监测对象内部的值的改变,在watch中配置deep:true 可以检测对象内部的属性的值改变

Class与Style绑定

<style>
    .basic {
        width: 400px;
        height: 100px;
        border: 1px solid black;
    }

    .demoA {
        border: 4px solid red;
        background-color: orange;
    }

    .demoB {
        border: 4px dashed pink;
        background-color: gray;
    }

    .demoC {
        background-color: skyblue;
    }

    .box1 {
        background-color: yellow;
    }

    .box2 {
        font-size: 30px;
        text-shadow: 2px 2px 10px red;
    }

    .box3 {
        border-radius: 20px;
    }
</style>
<body>
    <div id="root">
        <div class="basic" :class="mood" @click="changeMood">
            {{name}}
        </div>
        <div class="basic" :class="classArr">
            {{name}}
        </div>
        <div class="basic" :class="classObj">
            {{name}}
        </div>

        <div class="basic" :style="styleObj">
            {{name}}
        </div>

        <div class="basic" :style="styleArr">
            {{name}}
        </div>
    </div>
<script src="../js/vue2.7.15.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                name: '张三',
                mood: 'demoC',
                classArr:[
                    'box1','box2'
                ],
                classObj:{
                    box1:true,
                    box2:true,
                    box3:true
                },
                styleObj:{
                    fontSize:'40px',
                    color:'red'
                },
                styleArr:[
                    {
                        fontSize:'40px',
                        color:'blue'
                    },
                    {
                        backgroundColor: 'yellow'
                    }
                ]
            }
        },
        methods: {
            changeMood() {
                const arr = ['demoA','demoB','demoC'];
                const index = Math.floor(Math.random() * 3);
                this.mood = arr[index];
            }
        }
    });
    vm.$mount("#root")
</script>
</body>

Class绑定:

语法 —> :class=’xxx‘ xxx可以是字符串 数组 对象

  • 字符串:用于类名不确定
  • 对象:要绑定多个样式,个数不确定,名字不确定
  • 数组:绑定多个样式,个数确定,名字确定,但不确定是否要用

Style绑定:

语法:

  • :style=“{fontSize:xxx}” xxx是动态值
  • :style=“[a,b,c]” a,b,c为对象
  • a == { fontSize:xxx, …}

条件渲染

指令:v-if 、v-if-else、v-else 、v-show

<body>
    <div id="root">
        <h1>当前的count值:{{count}}</h1>
        <button @click="count++">Count++</button>
        <hr/>
        <div v-if="count==1">1</div>
        <div v-else-if="count==2">2</div>
        <div v-else>其他</div>
        <div v-show="count==3"><h1>v-show</h1></div>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm  = new Vue({
        data(){
            return{
                count:0
            }
        },
        methods:{

        }
    });
    vm.$mount("#root");
</script>

v-if和v-show的区别

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

    v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块

  2. 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换

  3. 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

列表渲染

<body>
    <div id="root">
        <!--遍历数组-->
        <ul>
          	<!-- (student,index) in students  index:下标 -->
            <li v-for="(student,index) in students" :key="student.stuNo">
                {{index}}-{{student.stuNo}}-{{student.name}}
            </li>
        </ul>
        <hr>

        <!--遍历对象  (属性值,属性名)-->
        <ul>
            <li v-for="(value,key) in person"  :key="key" >
                {{key}}  ---->>  {{value}}
            </li>
        </ul>
        <hr>

        <!--遍历字符串    (字符,下标)-->
        <ul>
            <li v-for="(char,index) in str" :key="index">
                {{index}}  --->>   {{char}}
            </li>
        </ul>
        <hr>

        <ul>
            <li v-for="(num,index) in 5">
                {{index}}  --->> {{num}}
            </li>
        </ul>

    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm  = new Vue({
        data(){
            return {
                students:[
                    {stuNo:"001",name:"张三"},
                    {stuNo:"002",name:"李四"},
                    {stuNo:"003",name:"王五"}
                ],
                person:{
                    id:"101",
                    name:"谢广坤",
                    sex:"男"
                },
                str:'Hello,world'
            }
        },
        methods:{}
    });
    vm.$mount("#root");
</script>

Key的作用

<body>
<div id="root">
    <ul>
        <!--     :key="stu.stuNo"   -->
        <li v-for="(stu,index) in students" :key="index" >
            {{index}}-{{stu.name}}
            <input type="text"/>
        </li>
    </ul>
    <button @click="addStudent">添加学生</button>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                students: [
                    {stuNo: 'S10101', name: '张三'},
                    {stuNo: 'S10102', name: '李四'},
                    {stuNo: 'S10103', name: '王五'}
                ]
            }
        },
        methods: {
            addStudent() {
                let obj = {stuNo: 'S10104', name: '赵六'};
                this.students.unshift(obj);
            }
        }
    });
    vm.$mount("#root")
</script>
</body>

:key='xxx':xxx最好是唯一属性值,上述案例使用index在特殊场景下会出现问题,例如:在students数组的头添加元素,页面上的input元素会产生类似错位的现象;若使用stu.stuNo当作key时,比对时会把元素当作一个整体,不会出现类似错位的现象

列表过滤排序

<body>
<div id="root">
    <input type="text" placeholder="请输入姓名" v-model="keyWord"/>
    <button @click="sortType=2">年龄升序</button>
    <button @click="sortType=1">年龄降序</button>
    <button @click="sortType=0">原顺序</button>
    <ul>
        <li v-for="(student,index) in filStudents" :key="student.stuNo">
            {{index}} -{{student.stuNo}}-{{student.name}}-{{student.age}}
        </li>
    </ul>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                sortType: 0,
                keyWord: '',
                students: [
                    {stuNo: 'S10101', name: '张三', age: 20},
                    {stuNo: 'S10102', name: '李四', age: 22},
                    {stuNo: 'S10103', name: '王五', age: 18},
                    {stuNo: 'S10102', name: '李五', age: 30}
                ],
            }
        },
        computed: {
            filStudents() {
                const arr = this.students.filter(item => {
                    return item.name.indexOf(this.keyWord) != -1;
                })
                if (this.sortType) {
                    arr.sort((s1, s2) => {
                        return this.sortType == 1 ? s2.age - s1.age : s1.age - s2.age;
                    });
                }
                return arr;
            }
        }
    });
    vm.$mount("#root")
</script>
</body>

收集表单数据

<body>
    <div id="root">
        <form action="#" method="post" @submit.prevent="demo">
            账号: <input type="text" v-model="userInfo.account"><br/><br/>
            密码: <input type="password" v-model="userInfo.password"><br/><br/>
            年龄: <input type="number" v-model="userInfo.age"><br/><br/>
            性别:
            <label><input type="radio" name="sex" v-model="userInfo.sex" value=""></label>
            <label><input type="radio" name="sex" v-model="userInfo.sex" value=""></label><br/><br/>
            爱好:
            <label><input type="checkbox" v-model="userInfo.hobby" value="1"></label>
            <label><input type="checkbox" v-model="userInfo.hobby" value="2"></label>
            <label><input type="checkbox" v-model="userInfo.hobby" value="3">Rap</label>
            <label><input type="checkbox" v-model="userInfo.hobby" value="4">篮球</label>
            <br><br>
            城市:
            <select v-model="userInfo.city">
                <option value="">请选择</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="dandong">丹东</option>
            </select>
            <br><br>
            其他:
            <textarea cols="30" rows="10" v-model.lazy="userInfo.other">

            </textarea><br><br>
            <input type="checkbox" v-model="userInfo.agree"><a href="#">已阅读XXX</a><br><br>
            <button type="submit">提交</button>
        </form>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm =new Vue({
        el:"#root",
        data(){
            return {
                userInfo:{
                    account:'',
                    password:'',
                    age:18,
                    sex:'男',
                    hobby:[],
                    city:'beijing',
                    other:'',
                    agree:''
                }
            }
        },
        methods:{
            demo(){
                console.log(this.userInfo);
                return false;
            }
        }
    });
</script>

过滤器

案例:时间转换

导入Day.js —> Day.js地址:https://unpkg.com/dayjs@1.8.21/dayjs.min.js也可以下载采用离线模式

<body>
    <div id="root">
        <h2>时间</h2>
        <h3>当前时间:{{time}}</h3>
        <input v-bind:value="time | timeFormater()"/>
        <h3>转换后的时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss')}}</h3>
        <h3>转换后的时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss') | strSlice}}</h3>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script src="../js/dayjs.min.js"></script>
<script type="text/javascript">
    Vue.filter('strSlice',function (value) {
        return value.slice(0,11)
    })
    const vm = new Vue({
        data(){
            return {
                time:1702366792000
            }
        },
        filters:{
            //局部过滤器
            timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
                return dayjs(value).format(str)
            }
        }
    });
    vm.$mount("#root")
</script>

指令

  • v-bind:单向数据绑定

  • v-model:双向数据绑定

  • v-for:循环

  • v-if、v-if-else、v-else、v-show:条件渲染

  • v-text:文本替换

  • v-html:一般不使用,存在安全问题

  • v-cloak:本质是一个特殊的属性 Vue的实例创建完毕并接管容器后 会删除v-cloak

    需要css的配置 解决网速慢时 页面展示{{}}(显示插值)的问题

  • v-once:所在的节点 初次被渲染后 就视为静态内容

  • v-pre:跳过所在的节点的编译过程

<style>
    [v-cloak]{
        display: none;
    }
</style>
<body>
    <div id="root">
        <div v-text="name">
            这是文本内容
        </div>

        <div v-html="str">

        </div>

        <div v-cloak>
            {{name}}
        </div>

        <div v-once>
            {{name}}
        </div>

        <div v-pre>
            {{name}}
        </div>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
        data(){
            return{
                name:'张三',
                str: '<b>张三</b>'
            }
        },
        methods:{
        }
    });
    vm.$mount("#root")
</script>

自定义指令

除了核心功能默认内置的指令 (v-modelv-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

<body>
    <div id="root">
        <h2>当前n的值是:<span v-text="n"></span></h2>
        <h3>方法n的值(2倍):<span v-big="n"></span></h3>
        <button @click="n++">n的自增</button>
        <input type="text" v-fbind="n" />
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
        data(){
            return {
                n:1
            }
        },
        directives:{
            // 自定义指令
            big(element,binding){
                console.log('big',this)
                console.log(element,binding)
                // 获取指令中的参数
                element.innerText = binding.value*2;
            },
            fbind:{
                //指令与元素成功绑定时执行(一进来)
                bind(element,binding){
                    console.log("bind");
                    element.value =  binding.value;
                },
                //指令所在的元素被载入页面时执行
                inserted(element,binding){
                    console.log("inserted");
                    element.focus();
                },
                //指令所在的模板被解析时
                update(element,binding){
                    console.log("update");
                    element.value =  binding.value;
                }
            }
        }
    });
    vm.$mount("#root");
</script>

上述fbind也可以通过Vue.directive

Vue.directive('fbind',{
    //指令与元素成功绑定时执行(一进来)
    bind(element,binding){
      console.log("bind");
      element.value =  binding.value;
    },
    //指令所在的元素被载入页面时执行
    inserted(element,binding){
      console.log("inserted");
      element.focus();
    },
    //指令所在的模板被解析时
    update(element,binding){
      console.log("update");
      element.value =  binding.value;
    }
})

Vue生命周期

Vue生命周期也叫生命周期钩子

在这里插入图片描述

<body>
    <div id="root">
        <h2>n的值为:{{n}}</h2>
        <button @click="n++">n++</button>
        <button @click="bye">结束Vue生命周期</button>
        <hr>
        <h2 :style="{opacity}" >欢迎光临,{{name}}</h2>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const vm = new Vue({
        data() {
            return {
                name:"张三",
                opacity:1,
                n: 1
            }
        },
        beforeCreate(){
            console.log("beforeCreate");
        },
        created(){
            console.log("created")
        },
        beforeMount(){
            console.log("beforeMount")
        },
        mounted(){
            console.log("mounted");
          	// 透明度由100%-0,循环
            this.timer = setInterval(()=>{
                this.opacity -= 0.01;
                if (this.opacity <=0){
                    this.opacity = 1;
                }
            },20)
        },
        beforeUpdate(){
            console.log("beforeUpdate")
        },
        updated(){
            console.log("updated")
        },
        beforeDestroy(){
            console.log("beforeDestroy")·
            // 清除定时器
            clearInterval(this.timer);
        },
        destroyed(){
            console.log("destroyed")
        },
        methods:{
            bye(){
                //结束vue声明周期
                this.$destroy();
            }
        }
    });
    vm.$mount("#root");
</script>

Vue组件

组件:是用来实现局部功能的代码和资源的集合

Vue中使用组件的三个步骤:

  1. 定义组件
  2. 注册组件
  3. 使用组件 (html 双标签)

Vue组件为什么没有el?

最终所有的组件都要经过vm的管理,由vm中的el来决定在那个容器中展示

组件名:

  1. 首字母大小写都可以
  2. 多个单词可以采用-连接,eg:my-school
  3. 多个单词还可以采用驼峰命名:MySchool

VueComponent

School组件本质是一个VueComponent 的构造函数并不是我们创建的 是Vue.extend生成的

<school></school>在使用时Vue解析时会帮我们创建,school组件的实例对象,new VueComponent({…}),每次调用Vue.extend 都会返回一个全新的 VueComponent

VueComponent.prototype.__proto__ === Vue.prototypeVueComponent.prototype.__proto__:指向Vue

Vue.prototype:指向Vue

this指向问题:

组件的this指向组件的本身,如school中的this指向school,student的this指向student,而Vue实例的this指向vm

<body>
    <div id="root">
        <school></school>
    </div>
</body>
<script src="../js/vue2.7.15.js"></script>
<script>
    const student = Vue.extend({
        template:`
          <div>
            <h2>学生姓名:{{studentName}}</h2>
            <h2>学生年龄:{{studentAge}}</h2>
          </div>
        `,
        data(){
            return{
                studentName:'张三',
                studentAge:18
            }
        }
    });

    // 创建一个vue组件
    const school = Vue.extend({
        template:`
             <div>
                  <h2>学校名称:{{schoolName}}</h2>
                  <h2>学校地址:{{address}}</h2>
                  <hr/>
                  <student></student>
            </div>
        `,
        data(){
            return{
                schoolName:'清华大学',
                address:'北京'
            }
        },
        components:{
            student // 组件的嵌套
        }
    });

    const vm = new Vue({
       data(){
           return {

           }
       },
       components:{
           school
       }
    });
    vm.$mount("#root");
</script>
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMonkey-D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值