尚硅谷_vue核心基础部分

01 初始vue

1. 想让vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
3. root容器里的代码被称为【Vue模板】;
4. Vue实例和容器是一一对应的;
5. 真实开发中只有一个Vue实例并且会配合着组件一起使用;
6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所对应的属性;
7. 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新;

注意区分:js表达式 和 js代码(又称为“语句”)
    1. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方,如:
        Date.now() // 获取当前时间戳
        a+b
        demo(1)
        x === y ? 'a' : 'b'
    2. js代码(语句)
        if(){}
        for(){}
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="../js/vue.js">script>
    <title>初始vuetitle>
head>
<body>
    <div id="root">
        
        <h1>hello, {{name.toUpperCase()}}, {{address}}h1>
    div>
    <script>
        Vue.config.productionTip = false;
        // 创建vue实例
        new Vue({
            // el用于指定当前vue实例为那个容器服务,值通常为css选择器字符串
            el: '#root',
            // data中用于存储数据,数据供el所所指定的容器去使用。值我们暂时写成一个对象。
            data: {
                name: 'badi',
                address: "贵州花溪"
            }
        });
    script>
body>
html>

02 Vue模板语法

1. 插值语法:
    功能:用于解析标签体内容;
    写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
2. 指令语法:
    功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...)
    举例:v-bind:href="xxx" 或简写为 :href="xxx", xxx同样需要写为js表达式。且可以直接读取到data中所有的属性。

注:Vue中有很多的指令,且形式都是:v-???,此处我们只是拿v-bind举个例子。
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板语法title>
    <script src="../js/vue.js">script>
head>
<body>
    
    <div id="root">
        <h1>插值语法h1>
        <h3>你好, {{name}}h3>
        <hr>
        <h1>指令语法h1>
        
        <a v-bind:href="school.url">点击我去{{school.name}}学习1a>
        <a :href="school.url">点击我去{{school.name}}学习2a>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: 'zhangsan',
                school: {
                    name: "尚硅谷",
                    url: 'http://www.atguigu.com/'
                }
            }
        });
    script>
body>
html>

03 数据绑定

Vue当中有两种数据绑定的方式:
	1. 单向绑定(v-bind):数据只能从data流向页面;
	2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
注:
	3. 双向绑定一般都应用在表单类元素上(如:input、select等)
	4. v-model:value可以简写为v-model,因为v-model默认收集的就是value的值。
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="root">
        
        

        
        单向的数据绑定:<input type="text" :value="name"><br>
        双向的数据绑定:<input type="text" v-model="name"><br>

        
        
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: "尚硅谷"
            }
        });
    script>
body>
html>

04 el与data的两种写法

data与el的2种写法:
  1. el有2中写法
      1)new Vue()时配置el属性;
      2)先创建Vue实例,随后在通过vm.$mount("#root")指定el的值;
  2. data有2中写法
      1)对象式;
      2)函数式;

      如何选择?目前那种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
  3. 一个重要的原则:
      有Vue管理的函数,一定不要写箭头函数,一旦写成了箭头函数,函数的this就不再是Vue实例了。
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="root">
        <h1>hello, {{name}}h1>
    div>
    <script>
        Vue.config.productionTip=false;
        const x = new Vue({
            // el的第一种写法
            // el: "#root",

            // data的第一种写法,对象式
            // data:{
            //     name: 'zhangsan'
            // }

            // data的第二种写法,函数式
            // 也可以写成data(){}这种方式
            data: function(){
                return {
                    name: 'zhangsan'
                }
            }
        });
        // el的第二种写法
        x.mount("#root");
    script>
body>
html>

05 MVVM模型

MVVM模型总结:
    1. M模型(Model):data中的数据
    2. V视图(View):模板代码
    3. VM视图模型(ViewModel):Vue实例
观察发现:
    1. data中所有的属性,最后都出现再了vm身上;
    2. vm身上所有的属性以及Vue原型上所有属性,在Vue模板中都可以直接使用。
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="root">
        <h1>学校名称:{{name}}h1>
        <h1>学校地址:{{url}}h1>
        <h1>测试1:{{1+1}}h1>
        <h1>测试2:{{$options}}h1>
    div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            data:{
                name: "尚硅谷",
                url: "北京"
            }
        });
        console.log(vm);    
    script>
body>
html>

06 数据代理

06.1 回顾Object.defineproperty

<script>
   let number = 20;
   let person = {
       name: 'zhangsan',
       sex: 'male'
       // age: 20
   }
   // 给person对象添加age属性
   Object.defineProperty(person, 'age', {
       // 给age属性赋值
       // value: 20,
       // // 通过defineProperty()方法添加的属性默认不能被遍历(枚举),可以使用下面的属性进行指定。
       // enumerable: true,
       // writable: true, // 是否可以被修改,默认为false
       // configurable: true // 是否可以被删除,默认为false
       
       // 取值
       get(){
           console.log('有人读取age属性了');
           return number;
       },

       // 当有人修改person的age属性时,set函数(setter)就会被调用,且会受到修改的具体值
       // 设置值
       set(value){
           console.log('有人修改了age属性,且值为:', value);
           number = value;
       }
   });

   // 遍历person对象中的属性
   // console.log(Object.keys(person));
   console.log(person);
script>

06.2 何为数据代理


<script>
    let obj = {x: 100};
    let obj2 = {y: 200};
    // 通过在obj2对象当中添加x属性来操作obj中的x属性。
    Object.defineProperty(obj2, 'x', {
        get(){
            return obj.x;
        },
        set(value){
            obj.x = value;
        }
    });
script>

06.3 Vue当中的数据代理

1. Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写);
2. Vue中数据代理的好处:更加方便的操作data中的数据;
3. 基本原理:
    通过Object.defineProperty()把data对象中所有属性添加到vm上;
    为每一个添加到vm上的属性,都指定一个getter/setter,在getter/setter内部去操作data中对应的属性;
<body>
    <div id="root">
        <h1>学校名称:{{name}}h1>
        <h1>学校地址:{{address}}h1>
    div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            data: {
                name: '尚硅谷',
                address: '滨江区'
            }
        });
    script>
body>

07 事件处理

07.1 事件的基本使用

事件的基本使用:
    1. 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名称;
    2. 时间的回调函数需要配置在methods对象中,最终会在vm上;
    3. methods中配置的函数,不要使用箭头函数!否则this就不再是vm了;
    4. methods中配置的函数,都是被Vue所管理的函数,this的只想是vm 或 组件实例对象;
    5. @click="demo" 和 @click="demo($event)" 效果是一样的,但后者可以传指定的参数;
<body>
    <div id="root">
        <h1>欢迎来到{{name}}学习h1>
        
        

        
        <button @click="showInfo1">点我弹出提示信息1(不传递参数)button>
        
        <button @click="showInfo2(666, $event)">点我弹出提示信息2(传递参数)button>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: '尚硅谷'
            },
            // 在vue当中编写函数
            // 其实在methods中的函数也可以定义在data中,但是不建议这样做,这样会使得Vue的工作量变得很大,因为函数本身是不需要做数据代理的。
            methods:{
                // 在对象当中定义函数时,不需要function关键字,直接编写函数名即可
                showInfo1(event){
                    // 通过event事件对象的target属性获取发生该事件的元素
                    // console.log(event.target);
                    // 此处的this是Vue实例
                    // console.log(this); 
                    alert("同学你好!");
                },
                showInfo2(number, event){
                    console.log(number);
                    console.log(event);
                    // alert("同学你好!!");
                }
            }
        });
    script>
body>

07.2 事件修饰符

Vue中的时间修饰符:
    1. prevent:阻止默认事件(常用);
    2. stop:阻止时间冒泡(常用);
    3. once:事件只触发一次(常用);
    4. self:只有event.target是当前操作的元素时才触发事件;
    5. passive:事件的默认行为立即执行,无需等待时间回调执行完毕;
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
    <style>
        *{
            margin-top: 5px;
        }
        #wrapper{
            height: 100px;
            background-color: #bfa;
            line-height: 100px;
        }
        #box1, #box2{
            padding: 5px;
        }

        #box1{
            height: 100px;
            background-color: #bfa;
        }
        #box2{
            height: 40px;
            background-color: orange;
        }
        #list{
            height: 100px;
            background-color: skyblue;
            overflow: auto;
        }
        #list li{
            margin: 20px;
        }
    style>
head>
<body>
    <div id="root">
        <h2>欢迎来到{{name}}学习h2>
        
        
        <a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息a>
        
        
        <div id="wrapper" @click="wrapperInfo">
            
            
            <a href="#" @click.stop.prevent="wrapperInner">去百度a>
        div>

        
        <button @click.once="showInfo">我只会触发一次button>

        
        <div id="box1" @click.capture="showMsg(1)">
            div1
            <div id="box2" @click="showMsg(2)">
                div2
            div>
        div>

        
        <div id="demo1" @click.self="showEvent">
            div1
            <div id="demo1" @click="showEvent">
                div2
            div>
        div>

        
        
        <ul id="list" @scroll="demo">
            <li>1li>
            <li>2li>
            <li>3li>
            <li>4li>
        ul>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: '尚硅谷'
            },
            methods:{
                showInfo(evnet){
                    // 阻止超链接a标签的默认跳转行为
                    // event.preventDefault();
                    alert("同学你好!");
                },
                wrapperInfo(){
                    alert("wrapper");
                },
                wrapperInner(){
                    alert("wrapper inner");
                },
                showMsg(msg){
                    console.log(msg);
                },
                showEvent(event){
                    console.log(event.target);
                },
                demo(){
                    // 默认情况下,一些元素的默认行为要等到回调函数执行完毕之后才会执行,当回调函数太复杂时,可以使用passive事件修饰符进行修饰。
                    for(i = 0; i < 1000000; i++){
                        console.log(i);
                    }
                    console.log('累坏了');
                }
            }
        });
    script>
body>
html>

07.3 键盘事件

1.Vue中常用的按键别名:
    回车 => enter
    删除 => delete (捕获“删除”和“退格”键)
    退出 => esc
    空格 => space
    换行 => tab (特殊,必须配合keydown去使用)
    上 => up
    下 => down
    左 => left
    右 => right

2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名,如:CapsLock要替换为caps-lock)

3.系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)
    (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
    (2).配合keydown使用:正常触发事件。

4.也可以使用keyCode去指定具体的按键(不推荐)

5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名(不推荐使用,因为一般情况下默认的都已经够使用了)
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="root">
        <h1>键盘事件测试h1>
        
        
        <input type="text" placeholder="请输入你的字符" @keyup.ctrl.y="demo">
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                
            },
            methods:{
                demo(event){
                    // event.key 按键名称;
                    // event.keyCode 按键编码;
                    console.log(event.key,event.keyCode);
                }
            }
        });
    script>
body>
html>

08 计算属性

08.1 姓名按钮_插值语法实现

<div id="root">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    
    全名:<span>{{firstName.substring(0,3)}}-{{lastName}}span>
div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",    
        data:{
            firstName: '张',
            lastName: '三'
        }
    });
script>

08.2 姓名按钮_methods实现

<div id="root">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    
    
    全名:<span>{{fullName()}}span>
div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",    
        data:{
            firstName: '张',
            lastName: '三'
        },
        methods:{
            fullName(){
                return this.firstName + '-' + this.lastName;
            }
        }
    });
script>

08.3 姓名按钮_计算属性实现

计算属性:
     1.定义:要用的属性不存在,要通过已有属性计算得来。
     2.原理:底层借助了Objcet.defineProperty方法提供的getter和setter。
     3.get函数什么时候执行?
         (1).初次读取时会执行一次。
         (2).当依赖的数据发生改变时会被再次调用。
     4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
     5.备注:
         1.计算属性最终会出现在vm上,直接读取使用即可{{fullName}}。
         2.如果计算属性要被修改,那必须写set函数去响应修改(否则会报错),且set中要引起计算时依赖属性数据发生改变后,该计算属性的值才有效。
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="root">
        姓:<input type="text" v-model="firstName"><br>
        名:<input type="text" v-model="lastName"><br>
        
        
        全名:<span>{{fullName}}span> <br><br>
        
    div>
    <script>  
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",    
            data:{
                firstName: '张',
                lastName: '三'
            },
            // 计算属性
            computed:{
                // 这个fullName并不会直接出现在vm的_data属性中,因为fullName计算属性是通过计算出来的。
                fullName:{
                    // 当fullName这个属性被调用时,get()方法会被执行。
                    // get()什么时候调用?
                    //  1. 初次读取fullName时,一般情况下之后都是读取缓存的内容;
                    //  2. 所依赖的数据发生变化时,get()也会被调用;
                    get(){
                        // 此处的this就是vm
                        
                        // 延迟1秒
                        /*setTimeout(function() {
                            // 在计算属性中这样写是不行的,因为计算属性靠的就是get函数的返回值,而这里的返回值会被当成是
                            // setTimeout里面回调函数的返回值。但是在watch当中却可以。即:计算属性不支持异步任务,但是watch却可以。
                            return this.firstName + '-' + this.lastName;
                        }, 1000);*/
                        return this.firstName + '-' + this.lastName;
                    },
                    set(value){
                        const temp = value.split("-");
                        this.firstName = temp[0];
                        this.lastName = temp[1];
                    }
                }
            }
        });
    script>
body>
html>

08.4 计算属性的简写

Vue.config.productionTip=false;
const vm = new Vue({
    el: "#root",    
    data:{
        firstName: '张',
        lastName: '三'
    },
    // 计算属性
    computed:{
        // 完整写法
        // fullName:{
        //     get(){
        //         // 此处的this就是vm
        //         return this.firstName + '-' + this.lastName;
        //     },
        //     set(value){
        //         const temp = value.split("-");
        //         this.firstName = temp[0];
        //         this.lastName = temp[1];
        //     } 
        // }

        // 简写形式
        /* 
        因为我们使用计算属性时大多数情况都是只读取而很少去改变,即大多数都是使用get方法。所以我们可以直接将get方法简写为:

        fullName: function(){

        }

        当然还可以简写为:
        fullName(){

        }
        一定要注意,上面的fullName计算属性并不是一个函数,而是将fullName这个计算属性的get方法执行的返回值返回给fullName计算属性。
        在Vue模板当中使用fullName属性时,也是直接写fullName,而不是fullName()。
        */
       fullName(){
        return this.firstName + "-" + this.lastName;
       }
    }
});

09 监视属性

09.1 天气案例

如果methods中的方法实现的功能很简单,如这里只是对当前的天气取反,那么可以直接在@click后面进行编写,即@后面可以编写一些简单的js语句。
但是不建议编写较为复杂的语句。

@xxx="yyy";xxx事件名,yyy执行的语句。



以下的代码会报错:
	
	因为被Vue所管辖的模板当中,所有的方法、变量都是在vue实例当中取寻找,如果找不到则报错,而不会跳转到上一级作用域当中去寻找(window)。
<div id="root">
    <h2>今天天气很{{info}}h2>
    <button @click="changeWeather">切换天气button>
div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            isHot: true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        methods: {
          changeWeather(){
            // 要修改当前的天气,直接取反即可
            this.isHot = !this.isHot;
          }  
        },
    });
script>

09.2 天气案例_属性监视

监视属性watch:
    1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
    2.监视的属性必须存在(不存在也不会报错,但是没有意义),才能进行监视!!
    3.监视的两种写法:  
        (1).new Vue时传入watch配置
        (2).通过vm.$watch监视
<div id="root">
    <h2>今天天气很{{info}}h2>
    <button @click="changeWeather">切换天气button>
div>
<script>
    Vue.config.productionTip=false;
    const vm = new Vue({
        el: "#root",
        data:{
            isHot: true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        methods: {
          changeWeather(){
            this.isHot = !this.isHot;
          }  
        },
        // 属性监视
        // 第一种方式
        // watch:{
        //     // 这里监视的属性不仅可以是data中的属性,也可以是computed中的计算属性。
        //     isHot:{
        //         immediate: true, // 让handler()在初始化的时候就执行一次。
        //         // 当isHot属性被修改时handler()函数会被执行
        //         // 该函数有两个参数,第一个为属性的改变后的值,第二个为属性修改之前的值。
        //         handler(newValue, oldValue){
        //             console.log("handler()被执行了:" + newValue, oldValue);
        //         }   
        //     }
            
        // }
    });

    // 属性监视的第二种方式
    vm.$watch('isHot', {
        immediate: true,
        handler(newValue, oldValue){
            console.log("handler()被执行了:" + newValue, oldValue);
        }   
    });
script>

09.4 天气案例_深度监视

深度监视:
    1. Vue中的watch默认不监视对象内部值的改变(默认只能监视一层);
    2. 配置deep:true可以检测对象内部值的改变(可以监视多层);
注:
    1. Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以;
    2. 使用watch时根据数据的具体结构,决定是否采用深度监视;
<div id="root">
  <h2>今天天气很{{info}}h2>
  <button @click="changeWeather">切换天气button>
  <hr>
  <h2>a的值是{{numbers.a}}h2>
  <button @click="numbers.a++">点我给a+1button>
  <h2>b的值是{{numbers.b}}h2>
  <button @click="numbers.b++">点我给b+1button>
div>
<script>
  Vue.config.productionTip=false;
  const vm = new Vue({
      el: "#root",
      data:{
          isHot: true,
          numbers: {
              a:1,
              b:1
          }
      },
      computed:{
          info(){
              return this.isHot ? '炎热' : '凉爽';
          }
      },
      methods: {
        changeWeather(){
          this.isHot = !this.isHot;
        }  
      },
      // 属性监视
      // 第一种方式
      watch:{
          // 这里监视的属性不仅可以是data中的属性,也可以是computed中的计算属性。
          isHot:{
              immediate: true, // 让handler()在初始化的时候就执行一次。
              // 当isHot属性被修改时handler()函数会被执行
              // 该函数有两个参数,第一个为属性的改变后的值,第二个为属性修改之前的值。
              handler(newValue, oldValue){
                  console.log("handler()被执行了:" + newValue, oldValue);
              }   
          },
          // 监视多级结构中某个属性的变化
          // 注意:在JavaScript对象中:
          // key: value 这里的key并没有使用''包裹起来,这是一种简写,正常情况下应该使用单引号包裹起来。
          // 'numbers.a': {
          //     handler(){
          //         console.log("a改变了");
          //     }
          // }
          
          // 监视多级结构中对象所有的属性的变化
          numbers: {
              // 开启深度监测
              deep: true,
              handler(){
                  console.log("numbers属性变化了");
              }
          }
      }
  });     
script>

09.5 天气案例_深度监视_简写属性

<div id="root">
    <h2>今天天气很{{info}}h2>
    <button @click="changeWeather">切换天气button>
div>
<script>
    Vue.config.productionTip=false;
    const vm = new Vue({
        el: "#root",
        data:{
            isHot: true,
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        methods: {
          changeWeather(){
            this.isHot = !this.isHot;
          }  
        },
        /*
        watch:{
            //完整写法
            // isHot:{
            //     // immediate: true, // 初始化时执行handler()方法
            //     // deep: true, // 深度监视
            //     handler(newValue, oldValue){
            //         console.log("handler()被执行了:" + newValue, oldValue);
            //     }   
            // },

            // 简写形式
            // 当我们监视的属性只是简单的调用handler()方法而不处理没有其它的配置时,如:immediate、deep等。
            // 我们就可以使用简写的方式,这里的(){}就相当于是handler()函数。
            isHot(newValue, oldValue){
                console.log("isHot", newValue, oldValue);
            }
        }*/
    });  
    // watch的第二种写法
    // vm.$watch('isHot', function(newValue, oldValue){
    //     console.log("天气的值改变了", newValue, oldValue);
    // }); 
    
    vm.$watch('isHot', {
        // immediate: true, // 初始化时执行handler()方法
        // deep: true, // 深度监视
        handler(newValue, oldValue){
            console.log("handler()被执行了:" + newValue, oldValue);
        }   
    });
script>

09.5 姓名案例_watch实现

computed和watch之间的区别:
     1.computed能完成的功能,watch都可以完成。
     2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
两个重要的小原则:
     1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
     2.所有不被Vue所管理的函数(如定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
         这样this的指向才是vm 或 组件实例对象。
     3. 其实以上两个步骤的目的就是想让函数的this指向vm。
<div id="root">
    姓:<input class="firstName" type="text" v-model="firstName"><br>
    名:<input class="lastName" type="text" v-model="lastName"><br>
    全名:<span>{{fullName}}span> <br><br>
div>
<script>  
    Vue.config.productionTip=false;
    const vm = new Vue({
        el: "#root",    
        data:{
            firstName: '张',
            lastName: '三',
            // 让全名默认是firstName-lastName
            fullName: '姓-名'
        },
        watch:{
            // 拥有两个形参,第一个是新的值,第二个是改变后的值
            firstName(val){
                // 这里应该特别注意箭头函数与普通函数的区别:
                // 由于setTimeout中的函数是有js引擎来调用,如果我们这里使用普通函数做回调,则回调函数的this为window。
                // 如果使用箭头函数的话由于这个函数本身没有this,它会向外层寻找this,找到firstName的回调函数时,
                // 将firstName的回调传给setTimeout作为回调函数的this。
                setTimeout(() => {
                    this.fullName = val + '-' + this.lastName;
                }, 1000);
            },
            lastName(val){
                this.fullName = this.firstName + '-' + val;
            }
        }
    });
script>

10 绑定样式

绑定样式:
   1. class样式
       写法:class="xxx" xxx可以是字符串、对象、数组。
           字符串写法适用于:类名不确定,要动态获取。
           对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
           数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
   2. style样式(了解)
       :style="{fontSize: xxx}"其中xxx是动态值。
       :style="[a,b]"其中a、b是样式对象。
DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>title>
		<style>
			.basic{
				width: 400px;
				height: 100px;
				border: 1px solid black;
			}
			
			.happy{
				border: 4px solid red;;
				background-color: rgba(255, 255, 0, 0.644);
				background: linear-gradient(30deg,yellow,pink,orange,yellow);
			}
			.sad{
				border: 4px dashed rgb(2, 197, 2);
				background-color: gray;
			}
			.normal{
				background-color: skyblue;
			}

			.atguigu1{
				background-color: yellowgreen;
			}
			.atguigu2{
				font-size: 30px;
				text-shadow:2px 2px 10px red;
			}
			.atguigu3{
				border-radius: 20px;
			}
		style>
		<script type="text/javascript" src="../js/vue.js">script>
	head>
	<body>
		
		<div id="root">
            
			<div class="basic" :class="mood" @click="changeMood">{{name}}div>
            <br><br>
			
			
            <div class="basic" :class="classArr">{{name}}div>
			<br><br>

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

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

		div>
	body>

	<script type="text/javascript">
		Vue.config.productionTip = false;
		
		const vm = new Vue({
			el: '#root',
            data:{
                name: 'my mood',
                mood: 'normal',
                classArr: ['atguigu1', 'atguigu2', 'atguigu3'],
				classObj:{
					// 默认不启用该属性
					atguigu1: false,
					atguigu2: false
				},
				// 下面的都是样式对象,什么是样式对象?指的是对象的key是不能随便起名的。
				styleObj:{
					// 这里的键名不能随便写,是跟css样式的名一样的,只是多个单词之间使用驼峰命名法进行命名
					fontSize: '40px',
					color: 'blue',
				},
				styleObj2:{
					backgroundColor: '#bfa'
				},
				styleArr:[
					{
						fontSize: '40px',
						color: 'blue',
					},
					{
					backgroundColor: '#bfa'
					}
				]
            },
            methods: {
                changeMood(){
                    // 让mood随机生成
                    const arr = ['happy', 'normal', 'sad'];
                    // random()函数自动生成0~1之前的数,但是娶不到1.
                    this.mood = arr[Math.floor(Math.random()*3)];
                }
            },
		});
	script>
	
html>

11 条件渲染

条件渲染:
     1.v-if
         写法:
             (1).v-if="表达式" 
             (2).v-else-if="表达式"
             (3).v-else="表达式"
         适用于:切换频率较低的场景。
         特点:不展示的DOM元素直接被移除。
         注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

     2.v-show
         写法:v-show="表达式"
         适用于:切换频率较高的场景。
         特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉,底层为display:none
         
     3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
<div id="root">
    
    
    

    
    
    

    

    
    <h2>n的值是:{{n}}h2>
    <button @click="n++">点我n的值会加1button>

    
    

    
    
    
    


    
    <template v-if="n===1">
        <h2>htmlh2>
        <h2>cssh2>
        <h2>jsh2>
    template>
    
div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            name: '尚硅谷',
            n: 0
        }
    });
script>

12 列表渲染

12.1 基本列表

v-for指令:
    1.用于展示列表数据
    2.语法:v-for="(item, index) in xxx" :key="yyy",这里的key要求是唯一的;
    3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
<div id="root">
    <h2>人员列表h2>
    <ul>
        
        
        <li v-for="(person, index) in persons" :key="person.id">
            {{person.name}}-{{person.age}}--{{index}}
        li>
    ul>

    <h2>汽车信息h2>
    <ul>
        <li v-for="(car, key) of cars" :key="key">
            {{car}}---{{key}}
        li>
    ul>

    <h2>遍历字符串(使用的少)h2>
    <ul>
        <li v-for="(char,index) of strs" :key="index">
            {{char}}---{{index}}
        li>
    ul>

    <h2>直接遍历次数(使用的少)h2>
    <ul>
        
        <li v-for="(number, index) of 10" :key="index">
            {{number}}---{{index}}
        li>
    ul>
div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            persons:[
                {id: '001',name: '张三', age:18},
                {id: '002',name: '李四', age:19},
                {id: '003',name: '王五', age:16},
            ],
            cars:{
                name: 'audi a6',
                price: '50w',
                color: 'black'
            },
            strs: 'hello'
        }
    });
script>

12.2 key的作用与原理

面试题:react、vue中的key有什么作用?(key的内部原理)

    1. 虚拟DOM中key的作用:
        key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 
        随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
                    
    2.对比规则:
        (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
            ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
            ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

        (2).旧虚拟DOM中未找到与新虚拟DOM相同的key
                    创建新的真实DOM,随后渲染到到页面。
                            
    3. 用index作为key可能会引发的问题:
        1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
                会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

        2. 如果结构中还包含输入类的DOM:
            会产生错误DOM更新 ==> 界面有问题。

    4. 开发中如何选择key?:
        1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
        2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
            使用index作为key是没有问题的。
    5. 值得注意的是:如果么有指定key,key的默认值为index; 

尚硅谷_vue核心基础部分_第1张图片
尚硅谷_vue核心基础部分_第2张图片

<div id="root">
    <h2>人员列表h2>
    <button @click.once="add">添加人员信息button>
    <ul>
        <li v-for="(person, index) in persons" :key="person.id">
            {{person.name}}-{{person.age}}--{{index}}
            <input type="text">
        li>
    ul>
div>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el: "#root",
        data:{
            persons:[
                {id: '001',name: '张三', age:18},
                {id: '002',name: '李四', age:19},
                {id: '003',name: '王五', age:16},
            ],
            cars:{
                name: 'audi a6',
                price: '50w',
                color: 'black'
            },
            strs: 'hello'
        },
        methods:{
            add(){
                const liu = {
                    id:'004',
                    name: '老刘',
                    age: 40
                };
                // unshift(),在数组的首位插入元素
                this.persons.unshift(liu);
            }
        }
    });
script>

13 收集表单数据

收集表单数据:
	若:,则v-model收集的是value值,用户输入的就是value值。
	若:,则v-model收集的是value值,且要给标签配置value值。
	若:
	    1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
	    2.配置input的value属性:
	        (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
	        (2)v-model的初始值是数组,那么收集的的就是value组成的数组
	备注:v-model的三个修饰符:
	    lazy:失去焦点再收集数据
	    number:输入字符串转为有效的数字
	    trim:输入首尾空格过滤
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="root">
        <h2>用户注册h2>
        <form @submit.prevent="demo">
            
            账号:<input type="text" v-model.trim="userInfo.account"><br><br>
            密码:<input type="password" v-model="userInfo.password"><br><br>
            
            年龄:<input type="number" v-model.number="userInfo.age"><br><br>
            性别:
            男 <input type="radio" name="sex" v-model="userInfo.sex" value="1"><input type="radio" name="sex" v-model="userInfo.sex" value="2"><br><br>
            爱好:
            学习<input type="checkbox" v-model="userInfo.hobbies" value="learn">
            打篮球<input type="checkbox" v-model="userInfo.hobbies" value="basketball">
            吃饭<input type="checkbox" v-model="userInfo.hobbies" value="eat"><br><br>
            
            所属校区:
            <select v-model="userInfo.city">
                <option value="default" style="display: none;">请选择校区option>
                <option value="gh">贵州option>
                <option value="hz">杭州option>
                <option value="bj">北京option>
            select><br><br>

            其他信息:
            
            <textarea cols="30" rows="10" v-model.lazy="userInfo.otherInfo">textarea><br><br>
            
            <input type="checkbox" v-model="userInfo.agreement">阅读并接受<a href="#">《用户协议》a><br><br>
            <button>提交button>
        form>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                userInfo:{
                    account: '',
                    password: '',
                    age: '',
                    sex: '',
                    hobbies: [],
                    city: 'default',
                    otherInfo: '',
                    agreement:''
                } 
            },
            methods: {
                demo(){
                    console.log(1);
                    console.log(JSON.stringify(this.userInfo));
                }
            },
        });
    script>
body>
html>

14 过滤器

过滤器:
    定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
    语法:
        1.注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
        2.使用过滤器:{{ xxx | 过滤器名}}  或  v-bind:属性 = "xxx | 过滤器名"
    备注:
        1.过滤器也可以接收额外参数(管道符前面的参数不用手动传递)、多个过滤器也可以串联
        2.并没有改变原本的数据, 是产生新的对应的数据
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
    <script src="../js/dayjs.min.js">script>
head>
<body>
    <div id="root">
        <h2>时间的格式化h2>
        <h3>时间戳:{{datetime}}h3>
        
        <h3>计算属性格式化后的时间:{{fmtDatetime}}h3>
        
        <h3>methods方式格式化之后的时间:{{getFmtDatetime()}}h3>
        
        
        <h3>filter格式化之后的时间:{{datetime | datetimeFormatter}}h3>

        
        
        <h3>filter格式化时间2:{{datetime | datetimeFormatter('YYYY-MM-DD')}}h3>

        
        <h3>filter之间的串联:{{datetime | datetimeFormatter('YYYY-MM-DD') | datetimeFormatter('YYYY')}}h3>

        
        
    div>
    <script>
        Vue.config.productionTip=false;
        // 全局过滤器,全局作用域只能一个一个注册
        // Vue.filters('datetimeFormatter', function(value, dateStr='YYYY-MM-DD HH:mm:ss'){
        //     return dayjs(value).format(dateStr);
        // });

        new Vue({
            el: "#root",
            data:{
                datetime: 1663725651593,
            },
            computed: {
                fmtDatetime(){
                    return dayjs(this.datetime).format('YYYY-MM-DD HH:mm:ss');
                }  
            },
            methods: {
                getFmtDatetime(){
                    return dayjs(this.datetime).format('YYYY-MM-DD HH:mm:ss');
                }
            },
            // 局部过滤器
            filters:{
                // 注意过滤器的本质就是一个函数
                // dateStr提供一个可以自定义时间格式字符串的参数,默认值为:YYYY-MM-DD HH:mm:ss
                datetimeFormatter(value, dateStr='YYYY-MM-DD HH:mm:ss'){
                    return dayjs(value).format(dateStr);
                } 
            },
        });
    script>
body>
html>

15 内置指令

15.1 v-text

<body>
    
    <div id="root">
        
        <div>{{name}}div>

        
        <div v-text="name">div>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: '尚硅谷'
            }
        });
    script>
body>

15.2 v-html

<body>
    
    <div id="root">
        <div v-html="name">div>
        <div v-html="str">div>
        
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                name: '

尚硅谷

'
, str: '来点有意思的东西' } });
script> body>

15.3 v-cloak

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>title>
    <script src="../js/vue.js">script>
    <style>
        /* 选择所有带有v-cloak属性的元素 */
        [v-cloak]{
            display: none;
        }
    style>
head>
<body>
    
    <div id="root">
        <h3 v-cloak>{{name}}h3>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
              name: '尚硅谷'  
            }
        });
    script>
body>
html>

15.4 v-once

<body>
    
    <div id="root">
        <h2 v-once>n的初始值为:{{n}}h2>
        <h2>n的当前值为:{{n}}h2>
        <button @click="n++">点我n加1button>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                n: 1
            }
        });
    script>
body>

15.5 v-pre

<body>
    
    <div id="root">
        
        <h2 v-pre>Vue其实很简单h2>
        <h2>当前的n值是:{{n}}h2>
        <button @click="n++">点我n加1button>
    div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el: "#root",
            data:{
                n: 1
            }
        });
    script>
body>

16 自定义指令

 自定义指令总结:
    一、定义语法:
        (1).局部指令:
            new Vue({									new Vue({
                directives:{指令名:配置对象}   或   		     directives{指令名:回调函数}
            }) 											})
        (2).全局指令:
            Vue.directive(指令名,配置对象) 或   Vue.directive(指令名,回调函数)

    二、配置对象中常用的3个回调:
        (1).bind:指令与元素成功绑定时调用。
        (2).inserted:指令所在元素被插入页面时调用。
        (3).update:指令所在模板结构被重新解析时调用。

    三、备注:
        1.指令定义时不加v-,但使用时要加v-;
        2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
<body>
    <div id="root">
        

         <h2>{{name}}h2>
         
         <h2>n的当前值是:<span v-text="n">span>h2>
         
         
         <h2>n放大10倍之后的值是:<span v-big="n">span>h2>
         <button @click="n++">点我给n+1button>
         <hr>
         <input type="text" v-fbind:value="n">
    div>
    <script>
        Vue.config.productionTip=false;
        // 全局写法
        // 函数式
        // Vue.directive('big', function(){
        //     // do thing
        // });

        // 对象式写法
        // Vue.directive('fbind', {
        //     // do thing
        // });
        
        new Vue({
            el: "#root",
            data:{
                name: '尚硅谷',
                n: 1
            },
            // 自定义指令,自定义指令不用写前面的v
                // 1. 使用函数式定义指令,缺点是不能实现一些细节上的操作,优点是方便简洁;
                // 2. 使用对象式定义指令,缺点是定义起来相对较为麻烦,优点是能实现一些细节上的配置。
            directives:{
                // 这里的big函数什么时候调用?
                // 1. 指令与元素成功绑定时;
                // 2. 指令所在的模板被重新解析时;

                // 第一个参数:引用该指令的html实体元素;第二个参数:指令所绑定的变量的指令对象。
                big(element, binding){
                    // console.log(binding);
                    element.innerText = binding.value * 10;
                },

                // 如果指令名之间有-这种符号,应使用如下方式进行定义。
                // 'big-number'(){}

                fbind:{
                    // 注意:以下函数的this都是window

                    // 指令与元素成功绑定时调用
                    bind(element, binding){
                        element.value = binding.value;
                    },
                    // 指令所在元素被插入页面时调用
                    inserted(element, binding){
                        element.focus();
                    },
                    // 指令所在的模板被重新解析是时调用
                    updated(element, binding) {
                        element.value = binding.value;
                    },
                    // 从以上的代码中可以看出,bind与updated这两个函数的功能相差不大,但实际上也是这样的,
                    // 即指令的函数式写法就是bind与updated函数的简写
                }
            }
        });
    script>
body>

17 生命周期

尚硅谷_vue核心基础部分_第3张图片

17.1 引出生命周期

<body>
    
    <div id="root">
        
        <h2 :style="{opacity: opacity}">欢迎学习vueh2>
    div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            data:{
                opacity: 1
            },
            methods: {
                
            },
            // Vue完成模板的解析并把初始的真实DOM元素放入页面后(即挂载完毕后)会自动一次性调用mounted函数
            // 注意:这里一定要理解页面挂载完毕与页面更新。
            mounted() {
                console.log("mounted");
                setInterval(() => {
                    vm.opacity -= 0.01;
                    if(vm.opacity <= 0)
                        vm.opacity = 1;
                }, 16);
            },
        });

        // 通过外部定时器实现,但是不推荐使用
        // 定时器
        // setInterval(() => {
        //     vm.opacity -= 0.01;
        //     if(vm.opacity <= 0)
        //         vm.opacity = 1;
        // }, 16);
    script>
body>

17.2 分析生命周期

<body>
    <div id="root">
        <h2>当前n的值为:{{n}}h2>
        <button @click="add">点击给n加1button>
        <button @click="bye">点击销毁vmbutton>
    div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            // es6模板写法
            // template: 
            // ` 
            //     

当前n的值为:{{n}}

// // `, data:{ n: 1 }, methods: { add(){ this.n++; }, bye(){ // 注意:$destroy方法执行完毕之后vm就被销毁了,但是vm在页面的工作成功是还存在的。 this.$destroy(); } }, // 生命周期函数 beforeCreate() { console.log('beforeCreate'); // console.log(this); // // 浏览器解析到此处时会停止代码的运行 // debugger; }, created() { console.log('created'); }, beforeMount() { console.log('beforeMount'); }, mounted() { console.log('mounted'); }, // 生命周期更新数据,这时dom数据与页面的数据不同步 beforeUpdate() { console.log('beforeUpdate'); }, updated() { console.log('updated'); }, // vm销毁 // 这个阶段可以访问数据、访问方法但是却无法修改数据,且这两个钩子无法触发更新函数。 beforeDestroy() { console.log('vm will be destroyed'); }, destroyed() { console.log('vm was destroyed'); }, });
script> body>

17.3 生命周期的总结

<body>
    
    <div id="root">
        <h2 :style="{opacity: opacity}">欢迎学习vueh2>
        <button @click="opacity=1">透明度设置为1button>
        <button @click="stop">点击停止变换button>
    div>
    <script>
        Vue.config.productionTip=false;
        const vm = new Vue({
            el: "#root",
            data:{
                opacity: 1
            },
            methods: {
                stop(){
                    // 方法一:直接直接清除定时器。巧妙思想,直接给当前this对象属性上面添加一个timer属性,而不用去定义一个全局作用域的变量了
                    // clearInterval(this.timer);

                    // 方法二:直接干掉vm
                    this.$destroy();
                }
            },
            mounted() {
                console.log("mounted");
                this.timer = setInterval(() => {
                    console.log('timer');
                    vm.opacity -= 0.01;
                    if(vm.opacity <= 0)
                        vm.opacity = 1;
                }, 16);
            },

            beforeDestroy() {
                // 清除定时器
                clearInterval(this.timer);
            },
        });
    script>
body>

18 非单文件组件

18.1 理解组件

组件定义:实现应用中局部功能代码和资源的集合。

尚硅谷_vue核心基础部分_第4张图片
尚硅谷_vue核心基础部分_第5张图片
尚硅谷_vue核心基础部分_第6张图片

18.2 组件的基本使用

<body>
    
    <div id="root">
        
        <school>school>
        <hr>
        
        <student>student>
        
    div>
    <script>
        Vue.config.productionTip=false;
        // 1. 创建组件,其实组件的配置与Vue实例配置类似,只是存在一些细微的差别
        // 学校组件
        const school = Vue.extend({
            // 组件里面不用编写el选项,因为组件都是交给Vue实例进行管理。
            // 定义模板
            template: `
                

学校名称:{{schoolName}}

学校地址:{{address}}

`
, data(){ return { schoolName: '尚硅谷', address: '贵州' }; }, methods: { showSchoolName(){ alert(this.schoolName); } }, }); // 学生组件 const student = Vue.extend({ template:`

学生姓名:{{studentName}}

学生年龄:{{age}}

`
, data(){ return { studentName: '张三', age: 20 }; } }); // 全局注册(也是属于第二步),使用的较少 // Vue.component('school', school); new Vue({ el: "#root", // 2. 注册组件(局部注册) components:{ // 对象属性,key: value,在js中key与value相同时的可以只写key。 // 注册school组件 school, student } });
script> body>

18.3 几个注意点

<body>
    
    <div id="root">
        <h2>欢迎你:{{msg}}h2>
        <school>school>
    div>
    <script>
        Vue.config.productionTip=false;
        // 定义组件
        const school = Vue.extend({
            // 可以给当前组件取一个名字,在Vue开发工具当中会显示的当前设置的名字
            name: 'schoolTest',
            template:`
                

学校名称:{{schoolName}}

`
, data(){ return { schoolName: '尚硅谷' } } }); new Vue({ el: "#root", data:{ msg: '周巴弟' }, components:{ school } });
script> body>

18.4 组件的嵌套

<body>
    <div id="root">
        <app>app>
    div>
    <script>
        Vue.config.productionTip=false;

        // 定义student组件
        const student = Vue.extend({
            template: `
            

学校名称:{{studentName}}

`
, data(){ return { studentName: '张三' } } }); // 定义school组件 const school = Vue.extend({ template:`

学校名称:{{schoolName}}

`
, data(){ return { schoolName: '尚硅谷' } }, // 将student组件嵌套在school组件当中 components:{ student } }); // 定义hello组件,与school组件平级 const hello = Vue.extend({ template:`

欢迎学习{{language}}

`
, data(){ return { language: 'Vue' }; } }); // 定义app组件 const app = Vue.extend({ template:`
`
, components:{ // 页面的所有组件都在app组件中进行注册 school, hello } }); new Vue({ el: "#root", components:{ // vm当中只需要注册app组件即可 app } });
script> body>

18.5 VueComponent

<body>
    
    <div id="root">
        <hello>hello>
        <school>school>
    div>
    <script>
        Vue.config.productionTip=false;

        // 定义组件
        const school = Vue.extend({
            template: `
                

学校名称:{{schoolName}}

`
, data() { return { schoolName: '尚硅谷' } }, methods: { showInfo(){ // 这里的this是VueComponent console.log('showInfo : ', this); } }, }); // 定义hello组件 const hello = Vue.extend({ template: '

欢迎你:{{msg}}

'
, data(){ return { msg: '张三' } } }); new Vue({ el: "#root", components:{school, hello} });
script> body>

18.6 一个重要的内置关系

<body>
    
    <div id="root">
        <school>school>
    div>
    <script>
        Vue.config.productionTip=false;
        Vue.prototype.x = 10000;

        // 定义school组件
        const school = Vue.extend({
            template:`
                

学校名称:{{schoolName}}

`
, data(){ return { schoolName: '贵州师范大学' }; }, methods: { showInfo(){ console.log(this.x); } }, }); const vm = new Vue({ el: "#root", data:{ y: 100 }, components:{school} });
script> <script> // ================= // 定义一个构造函数 function Demo(){ this.a = 1; this.b = 2; }; // 创建一个Demo的实例对象 const d = new Demo(); // console.log(Demo.prototype); // 显示原型属性 // console.log(d.__proto__); // 隐示原型属性 // 通过显示原型属性操作原型对象,追加一个x属性,值为99 Demo.prototype.x = 99; // console.log(d.x); // ================= script> body>

19 单文件组件

School.vue

<template>


<div id="demo">
    <h3>学校名称:{{schoolName}}h3>
    <h3>学校地址:{{schoolAddress}}h3>
div>
template>

<script>
// 组件交互相关代码

// es6默认暴露方式
export default {
    // 定义组件名,该名称一般与自身的文件名保持一致
    name: 'School',
    data() {
        return {
            schoolName: '尚硅谷',
            schoolAddress: '贵州'     
        }
    },
}
script>

<style>
/* 组件代码样式 */
.demo{
    background-color: #bfa;
}
style>

Student.vue

<template>
    <div>
       <h3>学生姓名:{{name}}h3>
        <h3>学生年龄:{{age}}h3> 
    div>
template>

<script>
export default {
    name: 'Student',
    data() {
        return {
            name: '张三',
            age: 20
        }
    },
}
script>

App.vue

<template>
    
    <div>
        
        <School>School>
        <Student>Student>
    div>
template>

<script>
    // 引入组件,在vue脚手架里面这里的.vue后缀可写可不写。
    import School from './School.vue'
    import Student from './Student.vue'

    export default {
        name: 'App',
        // 注册组件
        components:{
            School,
            Student
        }
    }
script>

应用入口文件main.js

import App from './App.vue'

new Vue({
    el: '#root',
    components:{
        App
    }
});

index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>简单练习一下vue单文件的语法title>
head>
<body>
    
    <div id="root">
        <App>App>
    div>
    
    <script src="../js/vue.js">script>
    <script src="./main.js">script>
body>
html>

20 补充

非单文件组件与单文件组件的区别:可以简单的理解为在非单文件组件当中可以写多个component,但是这种方式使用的较少,不推荐使用;而单文件组件则是在一个vue文件当中只编写一个组件,推荐使用。

你可能感兴趣的:(Spring,vue.js,javascript,前端)