Vue学习笔记(1)

1.初识Vue

<script src="./js/vue.js"></script>
</head>

<body>
    <!-- 
        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.表达式:一个表达式会生成一个值,可以放在任意地方

     -->
    <!-- 准备好一个容器 -->
    <div id="root">
        <h1>hellow,{{name}}</h1>
    </div>

    <script>
        Vue.config.productionTip = false;
        //创建Vue实例
        new Vue({
            el: '#root', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器
            data: { //data中用于存储数据,数据供el指定容器使用,值我们暂时先写成一个对象
                name: '范腾龙'
            }
        });
    </script>

2.模板语法

<!-- 
        Vue模板语法有2大类:
        1.插值语法:
        功能:用于解析标签体内容
        写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
        2.指令语法:
        功能:用于解析标签(包括:标签属性 标签体内容 绑定事件。。。)
        举例:v-bind:href='xxx'或 简写为:href='xxx',xxx同样要写js表达式
        且可以直接读取到data中的所有属性
        备注:Vue中有很多的指令,且形式都是:v-????,此处我们只是拿v-bind举例
     -->
    <div id="root">
        <h1>插值语法</h1>
        <h1>你好,{{name}}</h1>
        <hr>
        <h1>指令语法</h1>
        <a v-bind:href="school.url">点我去{{school.name}}学习1</a>
        <a :href="school.url">点我去{{school.name}}学习2</a>
    </div>

    <script>
        Vue.config.productionTip = false;
        new Vue({
            el: '#root',
            data: {
                name: '范腾龙',
                school: {
                    name: 'jack',
                    url: 'http://www.atguigu.com'
                }

            }
        })
    </script>

3.数据绑定

 <!-- 
        1.Vue中有两种绑定方式
        2.单项绑定:v-bind:数据只能从data流向页面
        3.双向绑定:v-model:数据不仅能从data流向页面,还可以从页面流向data
        备注:1.双向绑定一般都应用在表单类元素上(例如:input select等)
        2.v-model:value可以简写为v-model因为v-model默认收集的就是value值
     -->
    <div id="root">
        <!-- 普通写法 -->
        单向数据绑定: <input type="text" v-bind:value="name"> 双向数据绑定: <input type="text" v-model:value="name">
        <!-- 简写 -->
        单向数据绑定: <input type="text" v-bind:value="name"> 双向数据绑定: <input type="text" v-model="name">
        <!-- 以下代码是错误的,因为v-model只能应用在表单类元素(输入类元素) -->
        <h2 v-model:x="name">你好啊</h2>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
            el: '#root',
            data: {
                name: '尚硅谷'
            }
        })
    </script>
</body>

</html>

4.el和data的2种写法

 <!-- data和el的两种写法 
    1.el有两种写法
    (1new Vue时候配置el属性
    (2)先创建Vue实例,随后再通过v.$mount('#root')指定el的值
    2.data有两种写法
    (1).对象式
    (2).函数式
    3.一个重要原则:由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不是vue了
    -->
    <div id="root">
        <h1>你好,{{name}}</h1>
    </div>
    <script>
        Vue.config.productionTip = false;
        //el的两种写法
        // const v = new Vue({
        //     el: '#root', //第一种写法
        //     data: {
        //         name: '尚硅谷'
        //     }
        // })
        // console.log(v);
        // // v.$mount('#root'); //第二种写法



        //data的两种写法
        new Vue({
            el: '#root',
            //data的第一种写法:对象写法
            // data: {
            //     name: '尚硅谷'
            // }


            //data的第二种写法
            data: function() {
                console.log(this); //此处this是Vue
                return {
                    name: '尚硅谷'
                }
            }
        })

5.MVVM模型

MVVM模型

1.M:模型(Model):data中的数据

2.V:视图(View):模板代码

3.VM:视图模型(ViewModel):Vue实例

观察发现:1.data中所有属性,最好都出现在了vm身上

2.vm身上所有的属性以及vue原型上的所有属性,在vue模板中都可以直接使用

6.Obeject.definePerproty()

<script>
        let number = 18;
        let person = {
            name: '张三',
            sex: '男',
            // age: 18
        }
        Object.defineProperty(person, 'age', {
            // value: 18,
            // enumerable: true, //控制属性是否可以枚举(遍历)
            // writable: true, //是否可以被改写
            // configurable: true //目标属性是否可以被删除
            //当有人读取person的age属性时,get(getter)函数就会被调用,且返回值就是age的值
            get() {
                return number;
            },
            //当有人修改person的age属性时,get(getter)函数就会被调用,且返回值就是age的值
            set(value) {
                return value;
            }
        })
        console.log(Object.keys(person));
    </script>

7.简单数据代理

let Obj = {
            x: 100
        };
        let Obj2 = {
            y: 200
        };
        Object.defineProperty(Obj2, 'x', {
            get() {
                return obj.x;
            },
            set(value) {
                obj.x = value;
            }
        })

8.Vue中的数据代理

数据代理

1.Vue中的数据代理

通过vm对象来代理data对象中属性的操作(读/写)

2.Vue中数据代理的好处

更加方便的操作data中的数据

3.基本原理:

通过Object.defineProperty()把data对象中所有属性

添加到vm上,为每一个添加到vm上的属性,都指定一个getter/setter

在getter/setter内部去操作(读/写)data中对象的属性

9.事件处理

9.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)"效果一致,但后者可以传参
    -->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <button v-on:click="showInfo1">点我提示信息1(不传参)</button>
        <button @click="showInfo2(66,$event)">点我提示信息2(传参)</button>
        
        
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el:'#root',
            data(){
                return{
                    name:'尚硅谷',
                    money:0,
                    doller:0
                }
            },
            methods:{
               showInfo1(e){
                // console.log(e.target)事件对象
                // this是vm
                    alert('同学你好!')
                },
                showInfo2(number,a){
                // console.log(e.target)事件对象
                // this是vm
                console.log(number,a);
                    alert('同学你好!!')
                }
            }
            
            
        })

9.2事件修饰符

 <!-- 
        Vue中的事件修饰符
        (修饰符可以连续写:eg:@click.prevent.stop="showInfo")
        1.prevent:阻止默认事件(常用)
        2.stop:阻止事件冒泡(常用)
        3.once:事件只触发一次(常用)
        4.capture:使用事件的捕获模式
        5.self:只有event.target是当前操作的元素时才触发事件
        6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
     -->
    <div id="root">
                <h2>欢迎来到{{name}}学习</h2>
                <!-- 阻止默认事件(常用) -->
                <a href="http://atguigu.com " @click.prevent="showInfo">点我提示信息</a>
                <!-- 阻止事件冒泡 -->
                <div class="demo1" @click="showInfo">
                    <button @click.stop="showInfo">点我提示信息2</button>
                </div>
                <!-- 事件只触发一次once -->
                <button @click.once="showInfo">点我提示信息3</button>
                <!-- 使用事件的捕获模式capture -->
                <div class="box1" @click.capture="showMsg(1)">
                    div1
                    <div class="box2" @click="showMsg(2)">
                        div2
                    </div>
                </div>
                <!-- 只有event.target是当前操作的元素时才触发事件 -->
                <div class="demo1" @click.self="showInfo">
                    <button @click="showInfo">点我提示信息2</button>
                </div>
                <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->
                <ul class="list" @wheel.passive="demo">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    
                </ul>
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el:'#root',
            data:{
                name:'尚硅谷'
            },
            methods:{
                showInfo(e){
                     
                    alert('同学你好')
                },
                showMsg(a){
                console.log(a);
                },
                demo(){
                for(let i=0;i<100000;i++){
                      console.log(('#'));
                }
                console.log('累坏了');
                }
            }
        })

9.3键盘事件

<!-- 
        1.Vue中常用的按键别名:
        回车=>enter
        删除=>delete(捕获"删除”和“退格”键)
        退出=>esc
        空格=>space
        换行=>tab(特殊,必须配合keydown去使用)
        上=>up
        下=>down
        左=>left
        右=>right
        2.Vue未提供别名的按键,可以使用按键原始的key值取绑定,但注意要转为kebab-case(短横线命名)
        3.系统修饰键(用法特殊):ctrl alt shift meta
        (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
eg:@keyup.ctrl.y='showMsg '
        (2).配合keydown使用:正常触发事件
        4.也可以使用keyCode去指定具体的按键(不推荐)
        5.Vue.config.keyCodes.自定义键名=键码,可以去定制按键别名

     -->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <input type="text" placeholder="按下回车提示输入信息" @keyup.enter="showInfo">
    </div>
    <script>
        Vue.config.productionTip=false;
        new Vue({
            el:'#root',
            data:{
                name:'尚硅谷'
            },
            methods:{
                showInfo(e){
                    
                    console.log(e.target.value);
                }
            }
        })
    </script>

10.计算属性

 <!-- 计算属性
    1.定义:要用的属性不存在,要通过以有属性计算得来
    2.原理:底层借助了Object.defineproperty方法提供的getter和setter方法
    3.get函数什么时候执行?
    (1)初次读取时会执行一次
    (2)当依赖的数据发生改变时会被再次调用
    4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调式更方法
    5.备注:
        1.计算属性最终会出现在vm上,直接读取使用即可
        2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
    -->
    <div id="root">
         姓:<input type="text" v-model="firstname"><br><br>
         名:<input type="text" v-model="lastname"><br><br>
         全名:<span>{{fullname}}</span>
    </div>
    <script>
        Vue.config.productionTip=false;
        const vm =new Vue({
            el:'#root',
            data:{
                firstname:'张',
                lastname:'三'
            },
           computed:{
            fullname:{
                //get有什么用?当有人读取fullname时,get就会被调用,且返回值就是fullname值
                //get什么时候调用?1.初次读取fullname时,2.所依赖的数据发生变化时
                get(){
               console.log('get被调用');
            //    console.log(this);此处this是vm
               return  this.firstname+'-'+this.lastname;
                },
                //set什么时候调用?当fullname被修改时
                set(value){
                        console.log('set',value);
                        const arr=value.split('-');
                        this.firstname=arr[0]
                        this.lastname=arr[1]
                }
            }
           }
        })

10.1计算属性简写方法

当只有读取没有修改的时候,不考虑修改的时候才可以

 //简写写法
computed:{
        fullname(){
            console.log('get被调用');
            return  this.firstname+'-'+this.lastname;
        }
               
            
            }
        

11.监视属性

<!-- 
        监视属性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
            },
            methods: {
                changeWeather(){
                   this.isHot=!this.isHot;
                }
            },
            computed:{
                Info(){
                    return this.isHot ? '炎热':'凉爽';
                }
            },
        // watch:{
        //      isHot:{
        //         immediate:true,//初始化时让handeler调用一下 
        //         // 什么时候调用,当ishot发生改变时调用
        //         handler(newValue,oldValue){
        // console.log('ishot被修改了',newValue,oldValue);
        //         }
        //      }
        // }
            //简单写法
        // isHot(newValue,oldValue){
        //     console.log('ishot被修改了',newValue,oldValue);
        // }

        })
        vm.$watch('isHot',{
            immediate:true,//初始化时让handeler调用一下 
                // 什么时候调用,当ishot发生改变时调用
                handler(newValue,oldValue){
        console.log('ishot被修改了',newValue,oldValue);
                }
        })

11.1深度监视

<!-- 
        深度监视:
        (1).Vue中的watch默认不监测对象内部值的改变(一层)
        (2).配置deep:true可以监测对象内部值改变(多层)
        备注:(1).Vue自身可以监测对象内部值的改变,但是Vue提供的wtch不可以
            (2).使用watch时根据数据的具体结构,决定是否采用深度监视
     -->
    <div id="root">
        <h2>今天天气很{{Info}}</h2>
        <button @click="changeWeather">切换天气</button>
        <hr>
        <h3>a的值是{{numbers.a}}</h3>
        <button @click="numbers.a++">点我让a+1</button>
        <!--  -->
    </div>
    <script>
        Vue.config.productionTip=false;
        const vm=new Vue({
            el:'#root',
            data:{
                isHot:true,
                numbers:{
                    a:1,
                    b:2
                }
            },
            methods: {
                changeWeather(){
                   this.isHot=!this.isHot;
                }
            },
            computed:{
                Info(){
                    return this.isHot ? '炎热':'凉爽';
                }
            },
        watch:{
             isHot:{

                immediate:true,//初始化时让handeler调用一下 
                // 什么时候调用,当ishot发生改变时调用
                handler(newValue,oldValue){
        console.log('ishot被修改了',newValue,oldValue);
        
                }
               
             },
             numbers:{
                    deep:true,
                    handler(){
                        console.log('numbers被改变了');
                    }
                }
        },
       

        

        })

11.2监视简写

当不考虑deep:true,
       immediate:true,时候可以简写
 // watch:{
            //  isHot:{
                //正常写法
                //  deep:true,
                // immediate:true,//初始化时让handeler调用一下 
                // 什么时候调用,当ishot发生改变时调用
        //         handler(newValue,oldValue){
        // console.log('ishot被修改了',newValue,oldValue);
        
        //         }
        //简单写法
        // isHot(newValue,oldValue){
        //     console.log('ishot被修改了',newValue,oldValue);
        // }
               
        //      }
        })
        //正常写法
        // vm.$watch('isHot',{
        //     immediate:true,
        //     deep:true,
        //     handler(newValue,oldValue){
        //     console.log('ishot被修改了',newValue,oldValue);
        //     }
        // })
        vm.$watch('isHot',function(newValue,oldValue){
            console.log('ishot被修改了',newValue,oldValue);
        })

12.watch和computed的区别

1.computed能完成的功能,watch都可以完成

2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作

两个原则:

1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象

2.所有不被Vue所管理的函数(定时器的回调函数,ajax的回调函数等,promise的回调函数)最好写成箭头函数,这样this的指向才是vm或组件实例对象

13.绑定样式

 <!-- 
        绑定样式:
              1.class样式
              写法  :class='xxx'xxx可以时字符串 对象 数组
              字符串写法适用与:类名不确定,要动态获取
              对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
              数组写法使用于:要绑定多个样式,个数不确定,名字不确定
              2.style样式
              :style="{fontSize:xxx}" 其中xxx是动态值
              :style='[a,b]' 其中a ,b是样式对象
     -->
    <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
    <div class="basic" :class="mod" @click="changeMod" >{{name}}</div>
    <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不定,名字也不确定 -->
    <div class="basic" :class="arr">{{name}}</div>
     <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定,名字也确定,但要动态决定用不用 -->
    <div class="basic" :class="classObj">test</div>

<!-- 绑定style样式 对象写法 -->
    <div class="basic" :style="styleObj">test</div>
    <script>
        new Vue({
            el:'#root',
            data:{
                name:'尚硅谷',
                mod:normal,
                classarr:['happy','sad','normal'],
                classObj:{
                    atguigu1:false,
                    atguigu2:false,
                },
                styleObj:{
                    fontSize:'40px',
                }
            },
            methods: {
                changeMod(){
                    const arr=['happy','sad','normal'];
                    const index=Math.floor(Math.random()*3);//包含0但是不包含1,所以向下取整
                    this.mod=arr[index];
                }
            },
        })

14.条件渲染

<!-- 
        条件渲染
        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元素未被移除,仅仅是使用样式隐藏掉
        备注:使用v-if的时候,元素可能无法获取到,而使用v-show一定可以获取到
     -->
    <div id="root">
        <h2>当前的n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
        <!-- 使用v-show做条件渲染 -->
        <!-- <h2 v-show="false">欢迎来到{{name}}</h2>
        <h2 v-show="1===1">欢迎来到{{name}}</h2> -->

        <!-- 使用v-if做条件渲染 -->
         <!-- <h2 v-if="false">欢迎来到{{name}}</h2>
         <h2 v-if="1===1">欢迎来到{{name}}</h2> -->



            <!-- v-else和v-else-if -->
         <!-- <div v-if="n===1">Angular</div>
         <div v-else-if="n===2">React</div>
         <div v-else-if="n===3">Vue</div>
         <div v-else>哈哈</div> -->
         <!-- v-if与template的配合使用 template不影响结构 -->
          <template v-if="n===1">
            <div>React</div>
            <div>Vue</div>
            <div>哈哈</div>
          </template>
        
    </div>

15.列表渲染

<!-- 
        v-for指令
        1.用于展示列表数据
        2.语法:v-for="(item,index)in xxx" :key="yyy"
        3.可遍历:数组 对象  字符串 (用的很少) 指定次数(用的很少)
     -->
    <div id="root">
        <!-- 遍历数组(用的最多) -->
        <h2>人员列表</h2>
        <ul>
            <li v-for="p in personList" :key="p.id">{{p.name}}-{{p.age}}</li>
        </ul>
        <!-- 遍历对象 -->
        <!-- 注意:先收到的是每一项的值 -->
        <h2>汽车信息</h2>
        <ul>
            <li v-for="(value,key) in car" :key="key">
                {{key}}-{{value}}</li>
        </ul>

        <!-- 遍历字符串(少) -->
        <h2>人员列表</h2>
        <ul>
            <li v-for="(char,index) in str" :key="index">
                {{char}}-{{index}}</li>
        </ul>



        <!-- 遍历指定次数(少) -->
        <h2>人员列表</h2>
        <ul>
            <li v-for="(number,index) in 5" :key="index">
                {{index}}-{{number}}</li>
        </ul>
    </div>
    <script>
    Vue.config.productionTip=false;
    new Vue({
        el:'#root',
        data:{
            personList:[
                {id:'001',name:'张三',age:18},
                {id:'002',name:'李四',age:19},
                {id:'003',name:'王五',age:20}
            ],
            car:{
                name:'奥迪A8',
                price:'70万',
                color:'黑色'
            },
            str:'HELLOW'
        }
    })

15.2key的内部原理

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

1.虚拟DOM中key的作用:

​ key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据(新数据)生成(新的虚拟DOM),随后Vue进行(新虚拟DOM)与(旧虚拟DOM)的差异比较,比较规则如下:

2.对比规则:

(1).旧虚拟DOM中找到了与新虚拟DOM相同的key

​ 1.1若虚拟DOM内容没变,直接使用之前的真实DOM!

​ 1.2,若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

(2).旧虚拟DOM中未找到新虚拟DOM相同的key

​ 创建新的真实DOM,随后渲染到页面

3.用index作为key可能会引发的问题:

​ 3.1若对数据进行:逆序添加、逆序删除等破坏顺序操作:

​ 会产生没有必要的真实DOM更新===>界面效果没问题,但效率低

​ 3.2如果结构中还包含输入类的DOM:

会产生错误DOM更新===>界面有问题

4.开发中如何选择key?

4.1最好使用每条数据的唯一标识作为key,比如id 手机号 身份证号 学号等唯一值

4.2如果不存在对数据的逆序添加, 逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的

16.列表过滤

 <div id="root">
        <!-- 遍历数组(用的最多) -->
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord">
        <ul>
            <li v-for="p in filPerons" :key="p.id">
                {{p.name}}-{{p.age}}-{{p.sex}}</li>
        </ul>
        
    </div>
    <script>
    Vue.config.productionTip=false;
    //用watch实现
    // #region
    // new Vue({
    //     el:'#root',
    //     data:{
    //         keyWord:'',
    //         personList:[
    //             {id:'001',name:'马冬梅',age:18,sex:'女'},
    //             {id:'002',name:'周冬雨',age:19,sex:'女'},
    //             {id:'003',name:'周杰伦',age:21,sex:'男'},
    //             {id:'004',name:'温兆伦',age:22,sex:'男'}
    //         ]
            
    //     },
    //     filPerons:[],
    //     watch:{
    //         keyWord:{
    //             immediate:true,
    //             handler(val){
    //                 this.filPerons=this.personList.filter((p) => {
    //                 return p.name.indexOf(val)!==-1;
    //             })
    //         }
    //         }
    //     }
    // })
    // #endregion

    // 用computed实现
    new Vue({
         el:'#root',
        data:{
      keyWord:'',
             personList:[
                 {id:'001',name:'马冬梅',age:18,sex:'女'},
                 {id:'002',name:'周冬雨',age:19,sex:'女'},
                 {id:'003',name:'周杰伦',age:21,sex:'男'},
                 {id:'004',name:'温兆伦',age:22,sex:'男'}
             ]
      
         },
         computed:{
            filPerons(){
                 return this.personList.filter((p)=>{
                 return p.name.indexOf(this.keyWord)!==-1;
                })
            }
         }
    
        
     })

17.Vue监测数据变化原理

 <!-- 
            Vue监视数据的原理:
              1.vue会监视data中所有层次的数据
               2.如何监测对象中的数据?
                通过setter实现监视,且要在new Vue时就传入要监测的数据
                (1.)对象中后追加的属性,Vue默认不做响应式处理
                (2.)如需给后添加的属性做响应式,请使用如下API
                Vue.set(target, propertyName/index,  value)或
                vm.$set(target, propertyName/index,  value)
                3.如何监测数组中的数据?
                通过包裹数组更新元素的方法实现,本质就是做了两件事:
                (1) 调用原生对应的方法对数组进行更新
                (2)重新解析模板,进而进行更新页面
                4.Vue修改数组中的某个元素一定要用如下方法:
                1.使用这些APIpush(), pop(), shift(), unshift()  splice() sort() reverse()
                2.Vue.set或vm.$set()
        特别注意:Vue.set()和vm.$set()不能给vm(data)或vm(vm.—_data)的根数据对象添加属性!!!
     -->
    <div id="root">
        <h1>学生信息</h1>
        <button @click="student.age++">年龄+1岁</button><br>
        <button @click="addSex">添加性别属性,默认值:男</button><br>
        <button @click="student.sex='未知' " >修改性别</button><br>
        <button @click="addFriend">在列表首位添加一个朋友</button><br>
        <button @click="updateName">添加一个朋友的名字为张三</button><br>
        <button @click="addHobby">添加一个爱好</button><br>
        <button @click="updateHobby">修改第一个爱好为:开车</button><br>
        <h3>姓名:{{student.name}}-{{student.age}}-{{student.sex}}</h3>
        <button @click="filterHobby">过滤一个爱好抽烟</button><br>
        <h3>爱好</h3>
        <ul>
            <li v-for="(h,index) in student.hobby" ::key="index">
                {{h}}
            </li>
        </ul>
        <h3>朋友们:</h3>
        <ul>
            <li v-for="(f,index) in student.friends" ::key="index">
                {{f.name}}--{{f.age}}
            </li>
        </ul>
    </div>
</body>
<script>
    Vue.config.prodctionTip=false;
    new Vue({
        el:'#root',
        data:{
            student:{
                name:'tom',
                age:18,
                hobby:['抽烟','喝酒','烫头'],
                friends:[
                    {name:'jerry',age:35},
                    {name:'tony',age:36}
                ]
            }
        },
        methods: {
            addSex(){
                // Vue.set(this.student, 'sex','男')
                this.$set(this.student,'sex','男')
            },
            addFriend(){
                 this.student.friends.unshift({name:'jack',age:70});
            },
            updateName(){
                this.student.friends[0].name='张三';
            },
            addHobby(){
                this.student.hobby.push('学习')
            },
            updateHobby(){
                // this.student.hobby.splice(0,1,'开车');
                Vue.set(this.student.hobby,0,'开车')
            },
            filterHobby(){
                this.student.hobby= this.student.hobby.filter((val)=>{
                       return val!=='抽烟';
                })
            }
        },
    })
</script>

18.收集表单数据

 <!-- 
        收集表单数据
        若:<input type="text"/> 则v-model收集的是value值,用户输入的就是value值
        若 :<input type="radio"/> 则v-model收集的是value值,且要给标签配置value值
        若:<input type="checkbox"/>
            1.没有配置input的value属性,那么收集的就是checked(勾选or不勾选,是布尔值)
            2.配置input的value属性:
             (1).v-model的初始值是非数组,那么收集的就是checked(勾选or不勾选,是布尔值)
             (2).v-model的初始值是数组,那么收集的就是value组成的数组
        备注:v-model的三个修饰符
              lazy:失去焦点再收集数据
              number:输入字符串转换为有效的数字
              trim:输入首尾空格过滤
     -->
    <div id="root">
          <form >
            账号:<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="male">
            女:<input type="radio" name="sex" v-model="userInfo.sex" value="female"><br><br>
            爱好:
            学习 <input type="checkbox" v-model="userInfo.hobby" value="study">
            打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
            吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"><br><br>
            所属校区
            <select v-model="userInfo.city">
                <option value="">请选择小区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="wuhan">武汉</option>
            </select><br><br>
            其他信息
            <textarea v-model.lazy="userInfo.other">

            </textarea><br><br>
            <input type="checkbox" v-model="userInfo.agree"> 阅读并接受<a href="javascript:;">《用户协议》</a>
            <button @click.prevent="demo">提交</button>

            
          </form>
    </div>
</body>
<script>
    Vue.config.productionTip=false;
    const vm=new Vue({
        el:'#root',
        data:{
            userInfo:{
            account:'',
            password:'',
            age:'',
            sex:'',
            hobby:[],
            city:'',
            other:'',
            agree:''
            }
        },
        methods: {
            demo(){
                console.log(JSON.stringify(this.userInfo));
            }
        }
        
    })
</script>

19.内置指令

<!-- 学过的指令
    v-bind :单项绑定解析表达式,可简写为:xxx
    v-model:双向数据绑定
    v-for:遍历数组、对象、字符串
    v-on:绑定事件监听,可简写为@
    v-if:条件渲染(动态控制节点是否存在)
    v-else:条件渲染(动态控制节点是否存在)
    v-show:条件渲染(动态控制节点是否展示)
    v-text指令:
    1.作用:向其所在的节点中渲染文本内容
    2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会
    v-html指令:
         1.作用:向指定节点中渲染包含html结构的内容
         2.与插值语法的区别:
          (1).v-html会替换掉节点中所有的内容,{{xx}}则不会
          (2).v-html可以识别html结构
         3.严重注意:v-html有安全性问题!!!!
       (1).在网站上动态渲染任意HTML是有危险的,容易导致XSS攻击
        (2).一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上!
v-cloak指令(没有值)
     1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
     2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
     v-once指令(没有值):
            1.v-once所在节点在初次动态渲染后,就视为静态内容了
           2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
     v-pre指令(没有值):
               1.跳过其所在节点的编译过程
               2.可利用它跳过:没有使用指令语法。没有使用插值语法的节点,会加快编译
    -->
    <div id="root">
           <div v-text="name"></div>
    </div>
    
</body>
<script>
    Vue.config.productionTip=false;
    new Vue({
        el:'#root',
        data:{
            name:'尚硅谷'
        }
    })
</script>

20.自定义指令

 <!-- 
          一。定义语法:
             (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命名



     -->
    <div id="root">
    <h2>当前的n值是: <span v-text="n"></span></h2>
    <h2>放大10倍后的n值是: <span v-big="n"></span> </h2>
    <button @click="n++">点我n+1</button>
    <hr>
    <input type="text" v-fbind:value="n">
    </div>
    <script>
        Vue.config.productiobTip=false;
        //定义全局指令
        Vue.directive('fbind', {bind(element,binding){
                        //指令与元素成功绑定时候调用
                        //注意此处的this是window
                        element.value=binding.value;
                    },
                    inserted(element,binding){
                        //指令所在元素被插入页面时调用
                        element.focus();
                    },
                    update(element,binding){
                        //指令所在的模板被重新解析时
                        element.value=binding.value;
                    }
                }
)
        new Vue({
            el:'#root',
            data:{
                n:1,
            },
            directives:{
             //big函数何时会被调用?
             //1.指令与元素成功绑定(一上来)的时候调用
             //指令所在的模板被重新解析时
                big(element,binding){ 
                    element.innerText=binding.value*10
                },
                fbind:{
                    bind(element,binding){
                        //指令与元素成功绑定时候调用
                        //注意此处的this是window
                        element.value=binding.value;
                    },
                    inserted(element,binding){
                        //指令所在元素被插入页面时调用
                        element.focus();
                    },
                    update(element,binding){
                        //指令所在的模板被重新解析时
                        element.value=binding.value;
                    }

                }
               
            }
        })
    </script>

21.生命周期

 <!-- 
        生命周期:
           1.又名:生命周期回调函数,生命周期函数,生命周期钩子
           2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
           3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求写的
           4.生命周期函数中的this指向是vm或组件实例对象
     -->
    <div id="root">
           <h2 :style="{opacity}">欢迎学习Vue</h2>


    </div>
    <script>
        Vue.config.productionTip=false;
        const vm=new Vue({
            el:'#root',
            data:{
                opacity:1,
            },
            methods: {
                
                },
                //Vue完成模板的解析并把初始的真实的DOM元素放入页面后(挂载完毕)调用mounted
                mounted() {
                    setInterval(()=>{
                this.opacity-=0.01
                 if(this.opacity<=0) this.opacity=1;
         },16)
                },
            
        })
        // 通过外部的定时器实现(不推荐)
        // setInterval(()=>{
        //         vm.opacity-=0.01
        //         if(vm.opacity<=0) vm.opacity=1;
        // },16)
    </script>

21.1常用钩子函数

 <!-- 
        常用的生命周期钩子:
        1.mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等(初始化操作)
        2.beforDestroy:清除定时器,解绑自定义事件,取消订阅消息等(收尾工作)
        关于销毁Vue实例
         1.销毁后借助Vue开发工具看不到任何信息
         2.销毁后自定义事件会失效,但原生DOM依然有效
         3.一般不会在beforeDesrtoy操作数据,因为即便操作数据,也不会再触发更新流程!
     -->
    <div id="root">
           <h2 :style="{opacity}">欢迎学习Vue</h2>
           <button @click="stop">点我停止</button>
           <button @click="stop">点我停止</button>


    </div>
    <script>
        Vue.config.productionTip=false;
        const vm=new Vue({
            el:'#root',
            data:{
                opacity:1,
            },
            methods: { 
                stop(){
                    // clearInterval(this.timer);
                    this.$distroy();
                }
                
                },
                //Vue完成模板的解析并把初始的真实的DOM元素放入页面后(挂载完毕)调用mounted
            mounted() {
                    this.timer=setInterval(()=>{
                this.opacity-=0.01
                 if(this.opacity<=0) this.opacity=1;
         },16)
                },
            beforeDestroy() {
                clearInterval(this.timer);
            },
            
        })
    </script>

22.组件的定义

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

23.非单文件组件

<!-- 
           Vue中使用组件的三大步骤:
           一:定义组件(创建组件)
           二:注册组件
           三:使用组件(写组件标签)
        一:如何定义一个组件?
          使用Vue.extend(opitons)创建,其中options和new Vue(opitons)时传入的那个opitons一样但也有一些区别
          区别如下:
                   1.el不要写,为什么? ---最终所有的组件都要经过一个vm的管理,由vm中的el决定
                   2.data必须写成函数,为什么?---避免组件被复用时,数据存在引用关系
                   注:使用temolate可以配置组件结构
        二:如何注册组件?
           1.局部注册:靠new Vue的时候传入components选项
           2.全局注册:靠Vue.component'组件名',组件)
        三:编写组件标签:
           <school></school>


     -->
    <div id="root">
        <!-- 第三步:编写组件标签 -->
        <school></school>
        <hellow></hellow>
         <hr>
         <student></student>
         


    </div>
    <div id="root2">
        <hellow></hellow>
    </div>
    <script>
        Vue.config.prodcutionTip=false;
           // 第一步:创建school组件
           const school=Vue.extend({
            template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{adress}}</h2>
                <button @click="showName">点我提示学校名</button>
         
            </div>
            `,
            //一定不要写el配置项,因为最终所有的组件都要被vm所管理
            data(){
                return {
                    schoolName:'尚硅谷',
                    adress:'北京昌平',
                }
            },
            methods: {
                showName(){
                    alert(this.schoolName);
                }
            },
           })
           //第一步:创建student组件
           const student=Vue.extend({
            template:`<div>
                <h2>学生姓名:{{studentName}}</h2>
         <h2>学校年龄:{{age}}</h2></div>`,
            data(){
                return {
                    studentName:'张三',
                    age:18
                }
            }
           })

           const hellow=Vue.extend({
            template:`
            <div>你好啊!{{name}}</div>
            `,
            data(){
                return {
                    name:'Tom'
                }
            }
           })
           
           
           
           //第二步:全局注册组件
           Vue.component('hellow',hellow)
           //创建vm
        new Vue({
            el:"#root",
            data:{
                msg:'你好啊!'
            },
            //第二部:注册组件(局部注册)
            components:{
              school,
              student
            }
            
        })
        new Vue({
            el:'#root2'
        })
    </script>

23.1几个注意点

1.关于组件名:

​ 一个单词组成:

​ 第一种写法(首字母小写):school

​ 第二种写法(首字母大写):School

​ 多个单词组成:

​ 第一种写法(kebab-case命名):my-school

​ 第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)

​ 备注:

​ (1)组件名尽可能回避HTML中已有的元素名称,例如:h2 H2都不行

​ (2)可以使用name配置项指定组件在开发者工具中呈现的名字

2.关于组件标签:

第一种写法:

第二种写法:

​ 备注:不使用脚手架时,会导致后续组件不能渲染

3.一个简写方式:

const school=Vue.extend(options)可简写为:const school=options

23.2Vuecomponent构造函数

关于VueCommpoent:

​ 1.school组件本质是一个名为VueCommpoent的构造函数,且不是程序员定义的,是Vue,extend生成的

​ 2.我们只需要写或者,Vue解析时会帮哦我们创建school组件的实例对象

​ 即Vue帮我们执行的:new VueComponet(opitons)

​ 3.特别注意:每次调用Vue。extend,返回的都是一个全新的VueComponet!!!

​ 4.关于this的指向:

​ (1)组件配置中:

​ data函数。methods中的函数,watch中的函数,computed中的函数,他们的this均指向VueComponet实例对象

​ (2)new Vue(opitons)配置中:

​ data函数。methods中的函数,watch中的函数,computed中的函数,均指向Vue实例对象

​ 5.VueCommpoent的实例对象,以后简称vc(也可称之为:组件实例对象)

​ Vue的实例对象,以后简称vm

23.3一个重要的内置关系

VueComponent.prototype.__proto__===Vue.prototype
为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型的属性、方法

24.render函数

关于不同版本的Vue

1.Vue.js与vue.runtime.xxx.js的区别:

(1)vue.js是完整版的Vue,包含:核心功能+模板解析器

(2)vue.runtime.xxx.js是运行版的vue,只包含:核心功能

2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的creatElement函数去指定具体内容

render(creatElement){
      return creatElement('h1','你好啊!')
  }
简写如下:
render:q=> q('h1','你好啊!'),

25.vue.config.js配置文件

使用vue inspect> output.js可以查看到Vue脚手架的默认配置

使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh

26.ref属性

ref属性

1.被用来给元素或子组件注册引用信息(id的替代者)

2.应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)

3.使用方式:

打标识:

<button ref="btn" @click="showDOM">点我输入上方的DOM元素

获取:this.$refs.xxx

若,:ref='index',index为变量,则可以使用this.$ref [index]

27.配置项props

功能:让组件接受外部传过来的数据
(1)传递数据
    <Student name="李四" sex="女" :age="19"></Student> 
 (2)接受数据
    // props:['name','sex','age'] 简单声明接受接受
    //接受的同时对数据进行类型限制
    // props:{
    //   name:String,
    //   sex:String,
    //   age:Number
    // }

    //接受的同时对数据:进行类型限制+默认值的设置
    props:{
      name:{
        type:String,//name的类型是字符串
        required:true //name是必要的
      },
      age:{
        type:Number,
        default:99
      },
      sex:{
        type:String,
        required:true
              }
    }
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据

28.mixin混合

功能:可以把多个组件共用的配置提取成一个混入对象

使用方式:第一步定义混合,例如:

{

data(){....},

methods:{....}

}

第二步使用混入,例如:

​ (1)全局混入:Vue.mixin(xxx)

​ (2)局部混入:mixins:['xxxx']

//引入一个混合
import {mixin} from '../mixin'
export default {
    name:'School',
    data() {
        return {
          name:'尚硅谷',
          adress:'北京'
        }
    },
    mixins:[mixin],
    
    }

29.插件

功能:用于增加Vue

本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据

定义插件:

对象.install=function(){

//1.添加过滤器

Vue.filter(...)

//2.添加全局指令

Vue.directive(.....)

//3.配置全局混入

Vue.mixin(....)

//4.添加实例方法

Vue.prototype.$myMethod=function(){}

}

使用插件:Vue.use()

posted @   前端4u  阅读(53)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示