VUE基础笔记

112 阅读9分钟

Vue是一套用于动态构建用户界面的渐进式 JavaScript 框架

一,Vue特点

  1. 采用组件化模式,提高代码复用率,且让代码更好维护
  2. 声明式编码,让编码人员无需直接操作DOM,提高开发效率
  3. 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点

2,搭建开发环境

js里面关Vue生产提示

<script type="text/javascript">
    Vue.config.productionTip = false;   //阻止vue生成生产提示
</script>

3,使用Vue

  1. 想让vue工作,必须创建一个vue实例,且要传入一个配置对象
  2. root容器里面的代码被称为【Vue模板】
  3. Vue里面实例和容器是一一对应的
  4. {{xxx}}中要写js表达式,且可以自动读取到date里面的的所有属性
  5. 一旦data里面的数据发生改变,那么页面中用到该数据地方也会发生改变

二,Vue模板语法

1,插值语法

用于解析标签体内容

语法: 语法: {{xxx}} ,xxxx会作为 js 表达式解析

<h1>hello {{name}}</h1>

2,指令语法

  1. 功能: 解析标签属性、解析标签体内容、绑定事件
  2. 举例:v-bind:href = 'xxxx'xxxx 会作为 js 表达式被解析
  3. 说明:Vue 中有有很多的指令,此处只是用 v-bind 举个例子
<a v-bind:href="url">11</a>
<script type="text/javascript">
    Vue.config.productionTip = false;   //阻止vue生成生产提示
    const x = new Vue({
        el:'#root',  //用于指定vue实例为哪个容器服务,值通常为css字符串,
        data:{
            name:'你好',
            url:'www.baidu.com'
        }
    })
</script>

三,数据绑定

1,单向数据绑定

语法:v-bind:href ="xxx" 或简写为 :href

特点:数据只能从 data 流向页面

2,双向数据绑定

语法:v-mode:value="xxx" 或简写为 v-model="xxx"

特点:数据不仅能从 data 流向页面,还能从页面流向data

注意:使用v-model不能绑定props传递过来的数据,因为props是不可以修改的

eldata的俩种写法

第一种写法

<script type="text/javascript">
    Vue.config.productionTip = false;   //阻止vue生成生产提示
    const x = new Vue({
        el: '#root',  //用于指定vue实例为哪个容器服务,值通常为css字符串,
        data: {
            name:'你好',
            url:'www.baidu.com'
        }
    })
</script>

第二种写法

<script type="text/javascript">
    Vue.config.productionTip = false;   //阻止vue生成生产提示
    const v = new Vue({
        data(){
            return{
                name:'你好',
                url:'www.baidu.com'
            }
            
        }
    })
    v.$mount('#root');
</script>

四,MVVM模型

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

观察发现

data中所有属性,最后都出现在了vm身上

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

五,数据代理

  1. Vue中的数据代理:

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

2,Vue中数据代理的好处

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

3,基本原理

通过Object.defineProperty()把data对象中所有的属性添加到wm上,

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

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

通过一个对象代理对另一个对象中属性的操作(读/写)

<script type="text/javascript">
let obj = {x:100}
let obj2 = {y:200}
// 通过obj可以访问和修改obj2的y属性
Object.defineProperty(obj,'y',{
    get(){
        return obj2.y
    },
    set(value){
        return obj2.y = value
    }
})
</script>

六,事件处理

1,绑定监听

  1. v-on:xxx="fun"
  2. @xxx="fun"
  3. @xxx="fun(参数)"
  4. 默认事件形参: event
  5. 隐含属性对象: $event

注意:methods里面函数不要用箭头函数!否则this就不是指向vm

2,事件修饰符

Vue中的事件修饰符
  1. prevent:阻止默认行为

    //第一种方法:事件加prevent属性
    <a href="http://www.bilibili.com" target="_blank" @click.prevent="pre">
    // 第二种方法:方法里面使用 e.preventDefault()
    <a href="http://www.bilibili.com" target="_blank" @click="pre">
                提示
    </a>
    <script type="text/javascript">
        Vue.config.productionTip= false;
        new Vue({
            el:'#root',
            methods:{
                pre(e){
                    e.preventDefault()
                    alert('你好')
                },
            }
        })
    </script>
    
  2. stop:阻止事件冒泡

    //第一种方法:事件加stop属性
    <div class="demo1" @click="pre">
          <button @click.stop="pre">点我</button>
    </div>
    // 第二种方法:方法里面使用 e.preventDefault()
    <div class="demo1" @click="pre">
          <button @click="pre">点我</button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip= false;
        new Vue({
            el:'#root',
            methods:{
                pre(e){
                    e.stopPropagation()
                    alert('你好')
                },
            }
        })
    </script>
    
  3. once:事件只触发一次

    <button @click.once="getNum">触发一次</button>
    
  4. capture:使用事件的捕获模式

    // 在外层加capture属性
    <div class="box1" @click.capture="premsg(1)">
        div1
        <div class="box2" @click="premsg(2)">
            div2
        </div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip= false;
        new Vue({
            el:'#root',
            methods:{
                 premsg(msg){
                    console.log(msg);
                }
            }
        })
    </script>
    
  5. self:只有even.target是当前操作的元素才触发事件

  6. passive:事件的默认行为立即执行,无需等待回调函数执行完毕

注意:修饰符可以连续写

// 先阻止默认行为,再阻止冒泡
<a href="http://www.bilibili.com" target="_blank" @click.prevent.stop="pre">

七,键盘事件

1,Vue常用的按键别名

  • 回车=>enter

  • 删除=>delete(捕获"删除"和"退格"键)

  • 退出=>esc

  • 空格=>space

  • 换行=>tab(特殊,必须配合keydown去使用)

  • 上=>up

  • 下=>down

  • 左=>left

  • 右=>`right=// 按下回车键输出内容

    <input type="text" placeholder="按下输出文字" @keyup.enter="keyup">
    

2,系统修饰键

ctrl,alt,shift,meta

配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发

// 必须有其他键同时使用才能触发
<input type="text" placeholder="按下输出文字" @keyup.ctrl.enter="keyup">

配合keydown使用:正常触发事件

<input type="text" placeholder="按下输出文字" @keydown.ctrl="keyup">

3,自定义键名

// 语法
Vue.config.keyCodes.自定义键名 = 键码
Vue.config.keyCodes.a =65

注意:e.target.value是输出·当前输入的值

八,计算属性

使用插值语法放在标签里,{{fullname}}

1,定义:要用的属性不存在,要通过已有的属性计算得来

2,原理:底层借助了Object.defineproperty方法提供的gettersetter

3,get函数什么时候执行?

(1),初次读取时会执行一次。

(2),当依赖的数据发生改变时会被再次调用

4,备注:

1,计算属性最终会出现在vm上,直接读取使用即可

2,如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

5,优势

mothods实现相比,内部有缓存机制(复用),效率更高,调试方便。

computed:{
    fullname:{
        get(){
            console.log('get被调用了');
            return this.name.firstname+'-'+this.name.lastname
        },
        set(value){
             let arr = value.split('-');
             this.name.firstname=arr[0];
             this.name.lastname= arr[1];
         }
    }
}

简写:

computed:{
    fullname(){
        return this.name.firstname+'-'+this.name.lastname;
    }
}

九,监视属性

当被监视属性变化时,回调函数自动调用,进行相关操作

监视的属性必须存在,才能进行监视!

监视属性的俩种写法

1,new Vue()时,传入watch配置

watch: {
    // isFo 为监视的属性
    isFo: {
        immediate: true, //初始化时让handler调用一下
         //handler什么时候调用?当isFo发生改变时
         handler(newValue, oldValue) {
            console.log('isFo被改变了', newValue, oldValue);
        }
    }
}

2,通过vm.$watch监视(写在new Vue()外面)

vm.$watch('isFo',{
    immediate:true,
    handler(newValue,oldValue){
        console.log('isFo被修改了',newValue,oldValue);
    }
})

3,深度监视

配置deep:true可以监测对象内部值的改变(多层)

<div id="root">
    <h2>{{number.a}}</h2>
    <button @click="isInfo">点击a+1</button>
    <h2>{{number.b}}</h2>
    <button @click="isIn">点击b+1</button>
</div>
// js部分
watch:{
	number:{
	//深度监视
   		deep:true,
        handler(){
        console.log('值被改变了');
    	}
	}
}

4,简写形式,只调用handler时可以使用

watch: {
    // isFo 为监视的属性
    isFo(newValue, oldValue): {
            console.log('isFo被改变了', newValue, oldValue);
    }
}

十,绑定样式

1,绑定class样式

字符串写法,适用于样式的类名不确定,需要动态指定

<div :class="mood"></div>
data:{
    mood:'a',
}

数组写法:适用于要绑定的样式个数不确定,名字也不确定

<div  :class="classArr" ></div>
data:{
   classArr:['a','b','c'],
}

对象写法:适用于要绑定的样式个数确定,名字也确定,但要动态决定用不用

<div  :class="classArr"></div>
data:{
   classArr:{
       a:true,
       b:false,
       c:false
   }
}

2,绑定style样式

<div  :style="[styleObj,styleObj2]" ></div>
data:{
    styleObj:{
        width:'100px',
        height:'200px',
    	},
      styleObj2:{
      	backgroundColor:'red'
        }
    }

十一,条件渲染

1,v-if

适用于:切换频率较低的场景

特点:不显示的DOM元素直接被移除

注意:if,else-if中间不能被打断

  <!-- v-if做条件渲染 -->
<h2 v-if='n==1'>hello</h2>
<h2 v-else-if="n==2">1</h2>
<h2 v-else>2</h2>

2,v-show

适用于:切换频率较高的场景

特点:不显示的DOM元素未被移除,仅仅使用样式隐藏

备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到

<h2 v-show = 'n==1'>你好1</h2>

注:使用template,不影响结构,只能配合v-if使用

<template v-if="n===1">
    <h2>你好</h2>
    <h2>你好</h2>
    <h2>你好</h2>
</template>

十二,列表渲染

1,v-for遍历数据

<div id="root">
    <input type="text" v-model="keyword">
    <ul >
        <li v-for="(item, index) in arr" :key="item.id">
            {{item.id}}-{{item.name}}-{{item.age}}</li>
    </ul>
</div>

2,使用watch过滤数据

watch:{
    keyword:{
           // 必须初始化时让handler调用一下
            immediate:true,
            handler(newValue){
            this.arr = this.student.filter((item)=>{
                // console.log(item.name.includes(newValue));
                return item.name.includes(newValue)===true
            })
        }

    }
}

3,使用computed过滤数据

computed:{
    // arr 必须是没定义的
    arr(){
        return this.student.filter((item)=>{
            return item.name.includes(this.keyword)===true
        })
    }
}

4,列表排序

computed:{
    arr(){
        let sortArr =  this.student.filter((item)=>{
            return item.name.includes(this.keyword)===true
        })
        if(sortType){
            sortArr.sort((a,b)=>{
                return sortType===1?a.age-b.age:b.age-a.age
            })
        }
        return sortArr
    }
}

5,添加响应式数据

必须是给对象里面添加

// 第一种
Vue.set(vm.student,'age','21')
// 第二种
vm.$set(vm.student,'age','21')

十三,总结数据监测

1,Vue会监视data中所有层次的数据

2,如何监测对象中的数据

通过setter实现监视,且要在new Value时就传入要检测的数据

(1)对象中后追加的属性,Vue默认不做响应式处理

(2)如需给后添加的属性做响应式,使用如下API

Vue.set(vm.student,'age','21')vm.$set(vm.student,'age','21')

3,如何检测数组中的数据

通过包裹数组更新元素的方法实现,本质是做了两件事:

(1)调用原生对应的方法对数组进行更新

(2)重新解析模板,进而更新页面

4,在Vue中修改数组中的某个元素一定要用以下方法:

  1. push()pop()shift()unshift()splice()sort()reverse()
  2. 使用Vue.set()vm.$set(),注意不能给vm的根数据对象添加属性!!!

十四,收集表单数据

1,v-model的三个修饰符

  • lazy:失去焦点再收集数据
  • number:输入字符串转为有效的数字
  • trim:输入首尾空格过滤
<form @submit.prevent="demo">
            年龄:<input type="number" v-model.number="user.age"><br>
            性别:
            男<input type="radio" name="sex" v-model="user.sex" value="male"><input type="radio" name="sex" v-model="user.sex" value="femle"><br>
            爱好:
            学习<input type="checkbox" value="study" v-model="user.hobby">
            打游戏<input type="checkbox" value="game" v-model="user.hobby">
            运动<input type="checkbox" value="play" v-model="user.hobby"><br>
            所属小区
            <select v-model="user.city">
                <option></option>
                <option value="china">中国</option>
                <option value="japan">日本</option>
                <option value="us">美国</option>
            </select>
            <button >dianwo</button>
            <input type="submit" value="提交">
            <!-- <button>提交</button> -->
        <input type="checkbox">已阅读并同意<a href="">用户协议</a><a href="">隐私政策</a>
 </form>

十五,过滤器

  1. 功能: 对要显示的数据进行特定格式化后再显示
  2. 注意: 并没有改变原本的数据, 是产生新的对应的数据

语法:

1,注册过滤器:new Vue(flilters:{ })

filters:{
    timeFormater(value,str='YY-MM-DD HH:mm:ss'){
        return dayjs(value).format(str);
    }
}

2,使用过滤器:{{xxx | 过滤器名}}v-bind:属性 = “xxx | 过滤器名”

<h2>现在是{{time|timeFormater}}</h2>

案例:把时间戳转换为特点格式的时间

1,引用第三方关于时间的库

下载地址:github.com/iamkun/dayj…

2,使用过滤器

<div id = "root">
    <!-- 过滤器实现 -->
    <h2>现在是{{time|timeFormater}}</h2>
    <!-- 过滤器传参 -->
    // time当前时间戳,timeformat为过滤器,必须同时使用
    <h2>现在是{{time|timeFormater('YYYY-MM-DD')}}</h2>
</div>
// 局部过滤
<script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
        el:'#root',
        data:{
            time:1646709662939
        },
        filters:{
            timeFormater(value,str='YY-MM-DD HH:mm:ss'){
                return dayjs(value).format(str);
            }
        }
    })
</script> 

// 全局过滤

// 在new Vue实例之前使用,参数为过滤器名
Vue.filter('timeFormater',function(value){
	return dayjs(value).format('YY-MM-DD HH:mm:ss');
})

十六,内置指令

1,v-text

写法

<div v-text="name"></div>

相当于

<div>{{name}}</div>

作用:向所在节点中渲染文本内容

与插值语法区别:v-text会替换节点中内容,插值语法不会

2,v-html

写法

<div v-html="str"></div>
data:{
	str: '<h3>你好啊</h3>'
}

作用:更新元素的 innerHTML

v-html可以识别html结构

严重注意:v-html有安全问题

  • 在网站动态渲染任意HTML是非常危险的,容易XSS攻击
  • 一定在可信的内容上使用v-html,用不要用在用户提交的内容上

3,v-cloak(没有值)

使用**css配合v-cloak**可以解决网速慢页面展示出 {{xxx}} 的问题

<style>
	[v-cloak]{
		display:none
	}
</style>
<body>
	<div id = root>
		<h2 v-clock>
	</div>
</body>

4,v-once

只执行一次

v-once所在节点在初次动态渲染后,就视为静态内容了

以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

<div id = "root">
    <h2 v-once>初始{{n}}</h2>
    <h2>当前{{n}}</h2>
    <button v-on:click="n++">n+1</button>
</div>

5,v-pre

跳过其所在节点的编译过程。

可利用他跳过:没有使用指令语法、没有使用插值语法的2节点,会加快编译

<h2 v-pre>当前{{n}}</h2>
// 页面显示  当前{{n}}

十七,自定义指令

1,注册全局指令

Vue.directive('max',function(el,binding){
    el.innerText = binding.value+100
})
// 使用
 <button v-max="n"></button>

2,注册局部指令

new Vue({
    directives:{
        big(element,binding){
            element.innerText = binding.value*10
        },
    }
})
el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含指令的绑定值等

注:指令如果是多个单词,单词之间用-隔开

十八,生命周期

未命名图片.png

常用的生命周期钩子

1,mountedVue完成模板的解析并把初始的真实的DOM元素放入页面后(挂载完毕)调用;发送ajax请求 ,启动定时器,绑定自定义事件,,订阅消息等【初始化操作】

2,beforeDestory:清除定时器,解绑自定义事件,取消订阅消息等【收尾工作】

十九,组件

1, 模块

理解: 向外提供特定功能的 js程序, 一般就是一个js 文件

为什么: js 文件很多很复杂

作用: 复用js, 简化js 的编写, 提高 js 运行效率

2,组件

理解: 用来实现局部(特定)功能效果的代码集合(html/css/js/image…..)

为什么: 一个界面的功能很复杂

作用: 复用编码, 简化项目编码, 提高运行效率

3,模块化

当应用中的js 都以模块来编写的, 那这个应用就是一个模块化的应用。

4,组件化

当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用,。

5,局部组件

// 使用组件
<div id="root">
    <school></school><hr>
</div>
<script>
    Vue.config.productionTip = false
//定义组件
const school = Vue.extend({
    template:`
<div>
<h2>{{age}}</h2>
<span>{{name}}</span>
</div>
`,
    data() {
        return {
            name:'保定学院',
            age:12321312312
        }
    }
})
// 注册组件
new Vue({
    el:'#root',
    components:{school,home}
})
</script>

6,全局组件

<div id="root">
    <home></home>
</div>
  <script>
        Vue.config.productionTip = false
		// 定义组件
        const home = Vue.extend({
            template:`
            <div>
            <span>{{nname}}</span>
            <span>{{aage}}</span>
            </div>
            `,
            data() {
                return {
                    nname:'家',
                    aage:12321312312
                }
            },
        })
        // 全局注册
        Vue.component('home',home)
        new Vue({
            el:'#root',
            components:{school}
        })
    </script>

注意点:

1656154779415.png

7,组件的嵌套

<script>
        Vue.config.productionTip = false
        const school = Vue.extend({
            name:'school',
            template:`
            <div>
            <h2>{{age}}</h2>
            <span>{{name}}</span>
           </div>
            `,
            data() {
                return {
                    name:'保定学院',
                    age:12321312312
                }
            }
        })
        const home = Vue.extend({
            name:'home',
            template:`
            <div>
            <span>{{nname}}</span>
            <span>{{aage}}</span>
		
            <school></school> // 必须写
            </div>
            `,
            data() {
                return {
                    nname:'家',
                    aage:12321312312
                }
            },
            components:{school}
        })
        new Vue({
            el:'#root',
            components:{home}
        })
</script>

8,VueComponent

1,school组件本质是一个名为VueComponent的构造函数,是Vue.extend生成的

2,我们只需写<school/><school></school>Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(optains)

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

4,this执向:

  1. 组件配置中:data函数、methodswatch中的函数、computed中的函数,他们的this执向均是【VueComponent实例对象】
  2. new Vue(options)配置中, data函数、methodswatch中的函数、computed中的函数,他们的this执向均是【Vue实例对象】
  3. VueComponent的实例对象,以后简称vc(以后也称为组件实例对象), Vue实例对象,以后简称为vm
  4. VueComponent.prototype._proto===Vue.prototype
  5. 让组件实例对象(vc)可以访问到Vue原型上的属性、方法.