前言
- VUE是前端用的最多的框架;
- 这篇文章是本人大一上学习前端的笔记;
- 欢迎点赞 + 收藏 + 关注,本人将会持续更新。
Vue学习笔记
用于构建用户界面的渐进式框架
- 构建用户界面:基于数据动态渲染页面
- 渐进式:循序渐近的学习
- 框架:一套完整项目解决方案
1、Vue核心
1.1、vue实例配置对象
| 选项 | 说明 | 
|---|---|
| data | Vue实例数据对象 | 
| methods | 定义Vue实例中的方法 | 
| components | 定义子组件 | 
| computed | 计算属性 | 
| filter | 过滤器 | 
| el | 唯一跟标签 | 
| watch | 监听数据变化 | 
1.2、初始Vue
- 想让Vue工作,就必须创建一个Vue实例,并且要传入一个配置对象
- root容器里的代码依然符合html规范
- Vue模板:root容器中的代码
- {{xxxx}}中的xxx表达式要写js表达式
- 实际开发中只有一个Vue实例
<-->引入Vue</-->
<script src=""></script>
<body>
    <-->准备好一个容器</-->
    <div id="root">
        <h2>
            hello! {{name}}
        </h2>
    </div>
    
    <script>
    var vm = new Vue({
        el: '#root',           //唯一标签
        data: {
            name: 'wy'         //data储存数据
        }
    })
    </script>
</body>
1.3、模板语法
<script src="vue.js文件地址"></script>
<body>
    <div id="root">
        <h1>
            插值语法
        </h1>
        <h3>
            hello {{name}}
        </h3>
        <h1>
            指令语法
        </h1>
			<a v-bind:href="ur1">邓紫棋</a>
        <-->b-vind:  的简写形式  :href</-->
    </div>
</body>
总结:
-  插值语法: - 用于解析标签内容
 
-  指令语法: - 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件……)
- :href是- v-bind:href的简写形式
- 备注:Vue中的很多指令都是v-???形式
 
- 功能:用于
1.4、数据绑定
<script src=""></script>
<body>
    <div id="root">
        单项数据绑定:<input type="text" v-bind:value="name">
        双向数据绑定:<input type="text" v-bind:value="name">
    </div>
    
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                name: 'wqy'
            }
        })
    </script>
</body>
总结:
- Vue的2种数据绑定 
  - 单项数据绑定(v-bind): 数据只能从data流向页面
- 双向数据绑定(v-model):数据既可以从data流向页面,还可以从页面流向data
 
- 单项数据绑定(
- 技巧: 
  - 双向绑定都应用在表单类元素上,(如: \ 等)
- v-model:value简写成v-model
 
1.5、el和data的两种写法
<script>
    const vm = new Vue({
        //1.
        el: '#root',
        data: {
            
        }
        //data的第二种写法
        data() {
        
    }
        
        
    })
    
    //el的第二种写法
    vm.$mount('#root')
</script>
总结;
- data有两种写法: 
  - 对象式
- 函数式
 
注意:Vue管理的函数,一定不要写出箭头函数,否则this就不再是Vue实例了
1.6、MVVM模型

总结:
- data中所有属性,最后都出现在vm上
1.8、事件处理
1.8.1、事件的基本用法
<script src=""></script>
<body>
    <div id="root">
        <h2>
            hello , {{name}}
        </h2>
        <boutton v-on:click="showIndo1">点我提升信息一               </boutton>
        <button @click='showIno2(66)'>
            点我提示信息二
        </button>
    </div>
    
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                name: 'wy'
            }
            methods: {
            showIno1(event) {
            console.log(event);
        }
        	showIno2(num) {
                console.log(num);
            }
        }
        })
    </script>
</body>
总结:
- 使用v-on:xxx或者**@xxx**绑定事件,其中xxx是事件名
- 事件的回调需要配置在methods对象中,最总会出现在vm上
- methods中配置函数,不要使用箭头函数
- methods中配置的函数,都是被Vue所管理的函数,this指向是vm或者实例化对象
- @click="demo和- @click="demo($event)"效果一致,但后者可以传参
1.8.2、事件修饰符
- prevent:阻止默认事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用)
- capture:使用事件捕获(执行顺序是有外部到内部 P31页)
- self: 只有event.target是当前操作的元素时才触发事件,简单理解:只触发自己本身的元素
- passive: 事件的默认行为为立即执行函数
技巧:修饰符可以连续写: @click.prevent.stop=“show”
1.8.3、键盘事件
<script  src=""></script>
<body>
    <div id="root">
        <input type="text" @keydow.enter="show">
    </div>
    
    <body>
        const vm = new Vue({
        el: '#root',
        methods: {
        show(e) {
        console.log(e.target.value)
        }
        }
        })
    </body>
</body>
总结:
键盘上的每个按键都有自己的名称和编码,例如:Enter(13)。而Vue还对一些常用按键起了别名方便使用
Vue中常用的按键名:
- 回车:enter
- 删除:delete
- 退出:src
- 换行: tab(必须结合keydown使用)
- 上:up
- 下:down
- 左:left
- 右:right
注意:
- 系统修饰符:ctrl shifr alt 
  - 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
- 配合keydown使用:正常触发事件
 
- Vue.config.keyCodes.自定义键名 = 键码,可以自定义键别名
1.9、计算属性
<script src=""></script>
<body>
    <div id="root">
        姓:<input type="text" v-model="firstName"><br>
        名: <input tyep="text" v-model="lastName"><br>
        姓名:<span>{{fullName}}</span>
    </div>
    
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                firstName: '张',
                lastName: '三'
            },
            computed: {
                fullName: {
                    get() {
                     return this.firstName + '-' +lastName
                    }
                    set(vaule) {
                	const arr = value.split('-'),
            		this.firstName = arr[0];
                	this.lastName = arr[1]
            		}
                }
            }
        })
    </script>
</body>
总结:
- 计算属性: 
  - 定义:要用的属性不存在,需要计算的来
- 原理:Object.defineProperty()
- get函数(重要): 
    - 当初读取时会执行一次
- 依赖数据改变时会再次调用
 
 
- 备注: 
  - 计算属性最后会出现在vm上
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发送改变
- 如果计算属性不发生修改,简写形式为:
 
<script>
    new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        computed: {
            fullName() [
                return this.firstName + '-' + this.lastName
            ]
        }
    })
</script>
1.10、监视属性
1.10.1、监视属性的基本用法
<body>
    <div id="root">
        <h2>
            今天天气好{{info}}
        </h2>
        <button @click="changeWeather">
            点击切换天气
        </button>
    </div>
    
    <script>
        new Vue({
            el: '#root',
            data: {
                isHot: true,
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
             methods: {
                changeWeather() {
           			this.isHot = !this.isHot
        }
			},
             watch: {
               isHot: {
                immdiate: true,  //初始化时让handler调用一下
                //当isHot改变时会调用
                handler(newVaule,oldValue) {
            	console.log(newValue,oldValue)
        }
                } 
		}
        })
    </script>
</body>
总结:
- 当监视的属性被变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视
- 两种写法: 
  - 同上
- 同下:
 
vm.$watch('isHot',{
	immediate:true,
	handler(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue)
	}
})
1.10.2、深度监视
- 深度监视: 
  - Vue中的watch默认不监视对象内部的值
- 改变:deep: true
 
<body>
    <div id="root">
        <h3>
            a的值为:{{number.a}}
        </h3>
        <-->简单的代码可以这样操作</-->
        <button @click="number.a++">
            点我a加 1 
        </button
        <h3>
            b的值为:{{number.b}}
        </h3>
        <button @click="number.b++">
            点我b加 1
        </button>
    </div>
    <script>
       const vm = new Vue({
           el: '#root',
           data: {
               number: {
                   a:1,
                   b:2,
               }
           },
           watch: {
              number: {
               deep: true,
               handler() {
                   console.log('number改变了')
               }
              }
           }
       })
    </script>
</body>
1.10.4、监听属性 vs 计算属性
- computed和watch之间的区别: 
  - computed可以完成的东西,watch都可以完成
- 但是watch可以完成的东西,computed不一定能完成,如:watch可以进行异步操作
 
- 两个重要原则: 
  - 所有被Vue管理的函数,最好写出普通函数
- 不被Vue管理的函数,最好写出箭头函数,如:计算器
 
使用计算属性:
<body>
    <div id="root">
        姓:<input type='text' v-model='firstName'>
        名:<input type='text' v-model='lastName' >
        姓名:{{fullname}}
    </div>
    
    <script>
        const vm = new Vue({
            el: '#root',
            data: {
                firstName = '张',
                lastName = '三'
            },
            conputed: {
            fullName: {
            get() {
                return this.firstName + this.lastName;
            }
            set(value) {
                let arr = fullName.split('-');
            	this.firstName = arr[0];
                this.lastName = arr[1];
			}
        }
        },
        })
    </script>
</body>
使用监视属性:
<script>
    new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三',
            fullName: '张-三'
        },
        watch: {
        firstName: {
        handler(val) {
        setTimeout(()=>{
            this.fullName = val + '-' + lastName;
        },1000)
        },
        lastName: {
         handler(val) {
             this.fullName = this.firstName + '-' + val;
         }
        }
    }
    }
    })
</script>
1.11、绑定样式
写法:
<body>
    <div id="root">
        绑定class样式--字符串写法,通用于类名不确定,需要动态指定
        <div class="basic" :class="mood"' @click="changeMood"></div><br>
        绑定class样式--数组写法,适用于:要绑定的样式个数不确定,
        <div class="basic" :class="classArr"></div><br>
        绑定class样式---对象写法,适用于:要绑定的样式个数不确定、名字确定
        <div class="basic" :class="classObj"></div><br>
         
         绑定style样式--对象写法 
        <div class="basic" :style="styleObj"></div><br>
        绑定style样式--数组写法 
        <div class="basic" :style="styleArr"></div><br>
    </div>
</body>
总结:
-  class样式: - 写法:class="xxx",xxx可以是字符串、对象、数组
- 字符串写法适用于:类名不确定,要动态获取
- 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
- 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
 
- 写法:
-  style样式: - :style="{fontSize: xxx}"其中xxx是动态值
- :style="[a,b]"其中a、b是样式对象
 
1.12、条件渲染
- v-if: 
  - 写法: 
    - v-if
- v-else-if
- v-else
 
 
- 写法: 
    
- v-show: 
  - 写法: 
    - v-show=“表达式”
 
 
- 写法: 
    
<body>
    <div id="root">
        <h2 v-show="true">
            hello
        </h2>
        
        <div v-if="2===1"></div> <br>
        <div v-else-if="3===1"></div> <br>
        <div v-else></div> 
    </div>
</body>
1.13、列表渲染
1.13.1、基本列表
v-for
<body>
		<div id="root">
			<h2>人员列表(遍历数组)</h2>
			<ul>
				<li v-for="(p,index) in persons" :key="index">
					{{p.name}}-{{p.age}}
				</li>
			</ul>
			<h2>汽车信息(遍历对象)</h2>
			<ul>
				<li v-for="(value,k) in car" :key="k">
					{{k}}-{{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 type="text/javascript">
			Vue.config.productionTip = false
			
			new Vue({
				el:'#root',
				data:{
					persons:[
						{id:'001',name:'张三',age:18},
						{id:'002',name:'李四',age:19},
						{id:'003',name:'王五',age:20}
					],
					car:{
						name:'奥迪A8',
						price:'70万',
						color:'黑色'
					},
					str:'hello'
				}
			})
		</script>
    </body>
</html>
总结:
v-for指令:
- 用于展示列表数据
- 语法:
- ,key既可以是index,也可以是遍历数组的唯一标识
- 可遍历:数组、对象、字符串、指定次数
1.13.2、key的作用与原理


<body>
		<div id="root">
			<h2>人员列表</h2>
			<button @click.once="add">添加老刘</button>
			<ul>
				<li v-for="(p,index) in persons" :key="index">
					{{p.name}} - {{p.age}}
					<input type="text">
				</li>
			</ul>
		</div>
		<script type="text/javascript">
			Vue.config.productionTip = false
			
			new Vue({
				el:'#root',
				data:{
					persons:[
						{id:'001',name:'张三',age:18},
						{id:'002',name:'李四',age:19},
						{id:'003',name:'王五',age:20}
					]
				},
				methods: {
					add(){
						const p = {id:'004',name:'老刘',age:40}
						this.persons.unshift(p)
					}
				},
			})
		</script>
</html>
1.13.3、列表过滤
<body>
    <div id="root">
        <h2>
            人员列表
        </h2>
        <input type="text" v-model="keyWord">
        <ul>
            <li v-for="(p,index) of filPersons" :key="index"></li>
            {{p.name}} - {{p.age}} - {{p.sex}}
        </ul>
    </div>
    
    <script>
        new Vue({
            el: '#root',
            data: {
                keyWord: '',
                persons: [
                    {id:'001',name:'马冬梅',age:19,sex:'女'},
					{id:'002',name:'周冬雨',age:20,sex:'女'},
					{id:'003',name:'周杰伦',age:21,sex:'男'},
					{id:'004',name:'温兆伦',age:22,sex:'男'}
                ]
            },
            computed: {
                filPersons() {
                    return this.person.filter((p) => {
                        return                    p.name.indexOf(this.keyWord) !== -1;
                    }
                }
            }
        })
    </script>
</body>
注意:在Vue修改数组请用下面方法:
- 使用这些API:**push() \ pop() \ shift() \ splice() \ sort() \ reserse() **,这些才会更新,用[]不会,但是vue3可以
1.15、过滤器
- 定义:对要显示的数据进行特定格式化处理后再显示
- 语法: 
  - 注册过滤器:Vue.filter(name,callback)或new Vue{filters:{}}
- 使用过滤器:{{ xxx | 过滤器名}}或v-bind:属性 = "xxx | 过滤器名"
 
- 注册过滤器:
具体使用请看视频
1.16、内置指令
| v-model | 双向数据绑定 | 
|---|---|
| v-on | 监听事件 | 
| v-bind | 单项数据绑定 | 
| v-text | 插入文本内容 | 
| v-html | 插入包含html的文本内容 | 
| v-for | 列表渲染 | 
| v-if | 条件渲染 | 
| v-show | 显示隐藏 | 
v-text:
- v-text会替换掉节点中的内容,但是- {{xx}}则不会
v-html:(有安全隐患)
- v-html会替换掉节点中所有的内容,但是- {{xx}}则不会
- v-html可以识别html结构
v-clock指令
- 没有值:{{name}}
- 配合css解决配速慢的问题
- 一个特殊值,Vue实例创建完毕后,会删掉v-clock
v-once指令
- v-所在节点在初次渲染后,就视为静态内容
<div id="root">
    <h2 v-once>
        n的值为{{n}}
    </h2>
    <h2>
        n现在的值为{{n}}
    </h2>
    <button @click="n++">
        点我n+1
    </button>
</div>
v-pre
-  可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译 
-  Vue其实很简单
1.17、自定义指令
-  局部指令: <script> new Vue({ directives: {指令名:配置对象} }) </script><script> new Vue({ directives: {指令名:回调函数} }) </script>
-  全部指令: - Vue.directive(指令名,配置对象)
- Vue.directive(指令名,回调函数)
 
<script>
    Vue.directive('find',{
    //指令与元素一上来就绑定成功
    bind(element,binding){
        element.value = bind.value
    },
    //指令所在元素被插入页面时
     inserted(element,binding){
         element.focus()
     }
    //指令所在的模板被重新加载时
    update(element,binding) {
        element.value = binding.value
    }
    
                  })
</script>
- 配置对象中常用的3个回调函数 
  - bind(element,binding):指令与元素成功绑定时调用
- inserted(element,binding):指令所在元素被插入页面时调用
- update(element,binding):指令所在模板结构被重新解析时调用
 
- 注意: 
  - 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
 
1.18、生命周期

总结:
常用生命周期钩子:
- mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
- beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作



















