Vue基础第一天之“实例 、模板语法、数据绑定、MVVM、数据代理、事件、计算属性、监听”

一、vue介绍
1.vue是什么?
一套用于构建用户界面的“渐进式”js框架(vue关注你给定数据,我构建界面)
渐进式:(逐渐、递进、方式)
简单应用:只需要一个轻量的核心库,只需要100kb
复杂应用:可以引入各式各样的vue插件

2.vue是谁开发的?
尤雨溪
2013年在谷歌工作,受到Angular框架的启发,觉得Angular太重了,开始开发的轻量级框架,

3.vue特点
3-1.采用组件化模式,提高代码复用率,且让代码更好维护,比如:轮播是一个组件,侧边栏是一个组件(html、js、css)
3-2.声明式编码,让编码人员无需直接操作DOM,提高开发效率,比如:之前是用原生的js"命令式编码"  vue用的“声明式编码”使用v-for去遍历
3-3.使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点

4.学习vue之前要掌握的js基础知识?
ES6语法规范:解构赋值、模板函数、箭头函数
ES6模块化:默认暴露、分别暴露、统一暴露、
包管理器:npm cnpm
原型、原型链:重点  
数组常用方法:过滤数组、加工数组、筛选最值
axios
promise
异步和同步
...


二、官网使用指南
教程和API参考是最重要的
风格指南 代码规范性  
示列
cookbook {js和vue}代码是否写的太复杂了,没有做二次封装  教你技巧
生态系统的-工具-核心插件
vue cli脚手架


三、搭建vue环境
Download the Vue Devtools extension for a better development experience:缺少vue开发者工具
Vue Devtools
在浏览器上面,打印Vue.config,可以在vue官网API中,看到全局配置信息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入vue -->
    <script type="text/javascript" src="./js/vue.js"></script>
</head>
<style>
    .box1{
        width: 500px;
        height: 500px;
        background: red;
    }
    .box2{
        width: 250px;
        height: 250px;
        background: greenyellow;
    }
</style>
<body>
    <!-- 容器root -->
    <!--
    一、vue实例 
    1.想让vue工作,就必须创建一个vue实例,且要传入一个配置对象
    2.root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法
    3.root容器里的代码被称为【vue模板】
    
    二、vue实例的特点
    1.vue实例和容器是一一对应的
    2.真实开发中只有一个vue实例,并且会配合着组件一起使用

    
    三、vue模板语法有2大类
    1.插值语法:
    功能:用于解析标签体内容
    写法:{{xxx}},xxx是js表达式,并且可以直接读取到data中所有属性
    
    1-1.{{xxx}}中的xxx要写js表达式,并且xxx可以自动读取到data中的所有属性
    1-2.一旦data中的数据发生改变,那么页面中用的该数据的地方也会自动更新

    注意区分:js表达式 和 js代码(语句)
    1-2-1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
    (1).a
    (2).a+b
    (3).demo(1)
    (4). x===y? 'a':'b'
    1-2-2.js代码(语句)
    (1).if(){}
    (2).for(){} 

    2.指令语法:
    功能:用于解析标签(包括:标签属性、标签体内容、绑定事件。。。。。)
    举例:v-bind:href='xxx' 或 简写为:href='xxx',xxx统一要写js表达式,并且可以直接读取到data中的所有属性
    备注:vue中有很多的指令,并且形式都是:v-???,此处我们只拿v-bind举例

    四、vue的数据绑定
    1.单向的数据绑定(v-bind),数据只能从data流向页面
    2.双向的数据绑定(v-model),数据不仅能从data流向页面,还可以从页面流向data
    3.备注:
    3-1.双向绑定一般都应用在表单类元素上(如:input、select等)
    3-2.v-model:value 可以简写为v-moderl,因为v-model默认收集的值就是value值


    五、el与data的2种写法
    1.vue实例中:
    1-1.带$符号都是提供给程序员用的
    1-2.不带$符合的是vue底层在用
   
    2.el有2种写法
	(1).new Vue时候配置el属性。
	(2).先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。
	3.data有2种写法
	(1).对象式
	(2).函数式
	如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
	4.一个重要的原则:
	由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。

    
    六、理解MVVM
    MVVM模型
	1. M:模型(Model) :data中的数据
	2. V:视图(View) :模板代码(标签)
	3. VM:视图模型(ViewModel):Vue实例vm
    简述:模型(Model)中的数据-经过vm视图模型-在V视图中展示页面
         如果V视图中的数据要进行更改-经过vm视图模型-最终回到(模型(Model)中的数据)

	观察发现:
	1.data中所有的属性,最后都出现在了vm身上。
	2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

    七、回顾Object.defineProperty方法
    1.vue的数据劫持用到了这个方法
    2.数据代理用到了这个方法
    3.计算属性用到了这个方法

    八、js中的数据代理
    1.通过一个对象代理对另一个对象中属性的操作 读/写

    九、vue中的数据代理
    1.Vue中的数据代理:
	通过vm对象来代理data对象中属性的操作(读/写)
	2.Vue中数据代理的好处:
	更加方便的操作data中的数据
	3.基本原理:
	通过Object.defineProperty()把data对象中所有属性添加到vm上。
	为每一个添加到vm上的属性,都指定一个getter/setter。
	在getter/setter内部去操作(读/写)data中对应的属性。
    4._data是=data _data里面的不是数据代理,是数据劫持


    十、事件处理
    1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
	2.事件的回调需要配置在methods对象中,最终会在vm上;
	3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
	4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
	5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
    
    十一、事件修饰符
    0.可以多个写法:prevent.stop
    1.prevent:阻止默认事件(常用);
	2.stop:阻止事件冒泡(常用);
	3.once:事件只触发一次(常用);
	4.capture:使用事件的捕获模式;
	5.self:只有event.target是当前操作的元素时才触发事件;
	6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;


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

    十三、姓名案列使用插值语法实现
    十四、姓名案列使用vue计算属性实现
	1.定义:要用的属性不存在,要通过已有属性计算得来。
	2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
	3.get函数什么时候执行?
	(1).初次读取时会执行一次。
	(2).当依赖的数据发生改变时会被再次调用。
	4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
	5.备注:
	1.计算属性最终会出现在vm上,直接读取使用即可。
	2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
    6.计算属性的简写方式,只有get没用set

    十五、天气案列
    绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 
	<button @click="isHot = !isHot">切换天气</button> 


    十六、监视属性
    0.如果要监测对象下的a.需要使用字符串抱起来'numberlist.a':{}
	1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
	2.监视的属性必须存在,才能进行监视!!
	3.监视的两种写法:
	(1).new Vue时传入watch配置
	(2).通过vm.$watch监视
    


    -->
    <div id="root">
        <h1>插值,{{name}}</h1>
        <h2> {{Date.now()}}</h2>
        <h3>{{yingwen.toUpperCase()}}</h3>
        <h4>
            <a v-bind:href="url" >百度{{$options}}</a>
        </h4>
        单向的数据绑定<input type="text" :value = 'iptValueOne'><br>
        双向的数据绑定<input type="text" v-model = 'iptValueTwo'>
        <!-- 双向的数据绑定<input type="text" v-model:value = 'iptValueTwo'> -->

    </div>
    <div id="root1">

        <button v-on:click="showInfo1">点我提示消息1</button>
        <button @click="showInfo2(66,$event)">点我提示消息2</button>
        <a :href="url" @click.prevent="showInfo3">prevent阻止默认事件(常用)</a>
        <div class="box2" @click='showInfo3'>
            <button @click.stop='showInfo3'>阻止冒泡事件</button>
        </div>
        <button @click.once='showInfo3'>事件只执行一次后,就不会执行了</button>
        <div class="box1" @click.capture="showMsg(1)">
            <div class="box2" @click="showMsg(2)">使用事件的捕获模式</div>
        </div>
        <input type="text" @keyup.down="keyfun"><br>
        <input type="text" v-model="xing"><br>
        <input type="text" v-model="ming"><br>
        全名:{{xingMing()}}<br>
        全名:{{quanming}}<br>
        全名:{{quanmin}}<br>
        在模板语法里面,用插值语法调方法
        没加小括号:把函数展示到页面上,不会有值
        加小括号:我是想要把方法里的返回值展示到页面上来,存在值
        事件里面加与不加没有区别,有区别的是在插值语法里面<br>

        <!-- <div>今天天气很{{isHot?'炎热':'凉爽'}}</div> -->
        <div>今天天气很{{isHota}},{{num}}</div>
        <button @click='isHot = !isHot'>切换天气</button>
        <button @click='tianQiClick'>切换天气</button>
        <p>a的值{{numberlist.a}}</p>
        <button @click='numberlist.a++'>点击+1</button>
        <p>b的值{{numberlist.b}}</p>
        <button @click='numberlist.b++'>点击+1</button>

    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false//阻止 vue在启动时生成生产提示
    
        //创建vue实例
        const vm =  new Vue({
            // el:'#root',//el用于指定当前vue实例为哪个容器服务,值通常为css选择器字符串-el第一种写法
            // data:{//data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象-data第一种写法
            //     name:'学习',
            //     yingwen:'agese',
            //     url:'http://www.baidu.com',
            //     iptValueOne:'单向的数据绑定',
            //     iptValueTwo:'双向的数据绑定',
            // }
            //data的第二种写法
            // data:function(){//简写:为下面写法
            // data:()=>{//如果写成箭头函数,那么this,就会变成Window对象,因为箭头函数会往外面找,找到Window
            data(){
                console.log("this指向为vue的实例对象",this)
                return{
                    name:'学习',
                    yingwen:'agese',
                    url:'http://www.baidu.com',
                    iptValueOne:'单向的数据绑定',
                    iptValueTwo:'双向的数据绑定',
                }
            }
        })

        console.log(vm)
        vm.$mount("#root")//el第二种写法,mount方法为v下面的Prototype下面的$mount
    </script>
    <script type="text/javascript">
        let obj1 = {x:100}
        let obj2 = {y:200}

        Object.defineProperty(obj2,'x',{
            get:()=>{
                return obj1.x
            },
            set(value){
                obj1.x = value
            }
        })
            
        
    </script>
    <script type="text/javascript">
        Vue.config.productionTip = false//阻止 vue在启动时生成生产提示

         const vm1 = new Vue({
            el:"#root1",
            data(){
                return{
                    name:'xx',
                    url:'http://www.baidu.com',
                    xing:'张',
                    ming:'小明',
                    isHot:false,
                    num:0,
                    numberlist:{
                        a:0,
                        b:1
                    }
                }
            },
            computed:{
                quanming:{
                    //get有什么作用?当有人读取quanming时,get就会被调用,且返回值就作为fullName的值
					//get什么时候调用?1.初次读取quanming时。2.所依赖的数据发生变化时。
                    get(){
                        return this.xing + '-' + this.ming
                    },
                    //set什么时候调用? 当quanming被修改时。
                    set(value){
                        let arr = value.split('-');
                        console.log(value,arr)
                        this.xing = arr[0];
                        this.ming = arr[1];
                    }
                },
                quanmin(){//计算属性的简写方式,只有get没用set
                    return this.xing + '-' + this.ming
                },
                isHota(){
                    return this.isHot?'炎热':'凉爽'
                }

            },
            watch:{
                isHot:{
                    immediate:true,//初始化的时候让handler执行一次
                    //当isHot发生了变化时,handler会被调用
                    handler(newValue,oldValue){
                        console.log('isHot发生了变化',newValue,oldValue)//新的值、旧的值
                    }
                },
                isHota:{
                    immediate:true,//初始化的时候让handler执行一次
                    //当isHot发生了变化时,handler会被调用
                    handler(newValue,oldValue){
                        console.log('isHot发生了变化',newValue,oldValue)//新的值、旧的值
                    }
                },
                //监视多级结构中某个属性的变化
                'numberlist.a':{
                    handler(newValue,oldValue){
                        console.log('numberlist.a发生了变化',newValue,oldValue)//新的值、旧的值
                    }
                },
                //监视多级结构中所有属性的变化
                numberlist:{
                    immediate:true,//初始化的时候让handler执行一次
                    deep:true,//开启深度监测
                    handler(newValue,oldValue){
                        console.log('numberlist发生了变化',newValue,oldValue)//新的值、旧的值
                    }
                },
                //简写
				/* numberlist(newValue,oldValue){
					console.log('isHot被修改了',newValue,oldValue,this)
				} */                
              
            },
            methods:{
                showInfo1(event){
                    // alert('弹出消息',event)
                    console.log('2',event.target.innerText,this)
                },
                showInfo2(number,event){
                    // alert('弹出消息',event)
                    console.log('有event',event.target.innerText,this)
                    console.log('无event的时候',number,event)
                },
                showInfo3(){
                    alert('事件执行了')
                },
                showMsg(num){
                    console.log(num)
                },
                keyfun(e){
                    console.log(e.key)
                    if(e.keyCode === 13){
                        console.log(e.target.value)
                         console.log(e.keyCode)
                        
                    }
                },
                xingMing(){//插值语法实现
                    return this.xing.slice(0,3)+'--'+this.ming
                },
                tianQiClick(){
                    this.num++
                    this.isHot = !this.isHot 
                    console.log(this.isHot)
                }
            },
            
        })
        vm1.$watch('isHot',{
            handler(newValue,oldValue){
                        console.log('isHot发生了变化11',newValue,oldValue)//新的值、旧的值
                    } 
        })
        //简写
		/* vm.$watch('isHot',(newValue,oldValue)=>{
			console.log('isHot被修改了',newValue,oldValue,this)
		}) */


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

 

上一篇:Jmeter(一)测试消息推送接口


下一篇:【无标题】