准备开发环境
下载vue开发版本
 引入
<script src="/js/vue.js"></script>
 
F12可见提示,引入成功
 
 关闭开发模式提示
Vue.config.productionTip = false;
 
创建容器和Vue实例
<div id="root"></div>
<script>
	new Vue({
        el: '#root'
    });
</script>
 
或
<div id="root"></div>
<script>
	new Vue({}).$mount('#root');
</script>
 
插值语法
用于解析标签体内容
<div id="root">
	<h1>{{message}}</h1>
</div>
<script>
	new Vue({
        el: '#root',
        data() {
	        return {
        		message: 'Hello world'
        	}
        }
    });
</script>
 
指令语法
用于解析标签(属性,标签体内容,绑定事件…)
<div id="root">
    <a v-bind:href="url">baidu</a>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data() {
        	return {
            	url: 'https://www.baidu.com'
            }
        }
    });
</script>
 
MVVM
- M model data数据
 - V view 模板
 - VM viewModel Vue实例对象(m中的属性会在vm中代理,v可以使用vm中的所有属性,通过Object.defineProperty实现数据代理)
 
数据绑定
双向绑定v-model只能用于表单类元素(有value属性的元素)上
单向:<input type="text" v-bind:value="message" />
双向:<input type="text" v-model:value="message" />
 
简写
单向:<input type="text" :value="message" />
双向:<input type="text" v-model="message" />
 
事件处理
<button v-on:click="onBtnClick($event,message)">click</button>
 
简写
<button @click="onBtnClick($event,message)">click</button>
 
new Vue({
	data() {
		message: 'hello world'
	},
    methods: {
         onBtnClick(event, message) {
		 	alert(message + ' clicked');
         }
     }
})
 
事件修饰符
<a @click.prevent.stop="onClick">click</a>
 
- prevent 阻止默认事件默认行为(例如标签阻止跳转)
 - stop 阻止事件冒泡
 - once 事件只触发一次
 - capture 使用捕获模式(默认在冒泡阶段执行回调(由内向外),此修饰符可在捕获阶段执行回调(由外向内))
 - self 只有event.target是当前元素才触发
 - passive 立即执行事件默认行为,无需等待事件回调结束(例如滚动条滚动事件,防止因回调导致滚动条卡顿)
 - 键盘事件按键绑定
 
<input @keydown.Enter="onKey"></input>
<input @keydown.caps-lock="onKey"></input>
<input @keydown.tab="onKey"></input>
<input @keydown.ctrl.x="onKey"></input>
 
- tab必须配合keydown,否则焦点离开无法触发
 - 系统修饰键 ctrl,alt,shift,meta(win键)
配合keyup时,按下修时间同时,再按下其他键,随后释放其他键触发
配合keydown时,正常触发 
计算属性
<input v-model:value="fn"/>
<input v-model:value="ln"/>
<input v-model:value="fullname"/>
 
new Vue({
	data() {
		firstname: 'san',
		lastname: 'zhang'
	},
    computed: {
         fullname: {
         	// 1. 初次读取时调用,模板中多次使用,只调用一次(如果使用method定义计算,则会多次调用)
            // 2. 所依赖的数据发生变化时调用
         	get(){
         		return this.firstname + '-' +this.lastname
         	},
         	// 可选,fullname变化时调用
         	set(value){
         		const arr = value.split('-');
         		this.firstname=arr[0];
         		this.lastname=arr[1];
         	}
         }
     }
})
 
- 简写
只可读取不可修改
使用计算属性时用fullname而不是fullname() 
computed:{
	fullname: function{
		return this.firstname + '-' +this.lastname
	}
}
 
侦听属性
通过配置
watch: {
    fullname: {
    	immediate: true, // 初始化时调用handler
        handler(newv, oldv) {
            console.log('change', newv, oldv);
        }
    }
}
 
通过api
let vm = new Vue({...});
vm.$watch('fullname',{
    immediate: true,
    handler(newv, oldv) {
        console.log('change', newv, oldv);
    }
});
 
简写
 不需要其他配置时(immediate,deep)可使用简写
watch:{
	fullname(newValue,oldValue){}
}
 
深度侦听
data() {
    return {
        name:{
            fn: 'fn',
            ln: 'ln'
        }
    }
},
watch: {
	// 监视结构中属性
	'name.fn':{},
	// 监视结构中所有属性变化
	name:{
		deep:true,
		handler(){};
	}
}
 
watch vs computed
当需要异步处理计算逻辑时得使用watch
watch:{
	name:{
		deep:true,
		handler(){
			setTimeout(()=>{
				// 注意此处使用箭头函数,this=vue实例
				// 如果使用function ,this=window
				this.fullname = name.fn + name.ln;
			},1000)
		}
	}
}
 
绑定样式
绑定字符串:名字不确定
 绑定数组:样式个数和名字都不确定
 绑定对象:个数和名字确定,但不确定用不用
<div class='basic' :class='vClass'></div>
<div class='basic' :class='vClasses'></div>
<div class='basic' :class='vClassObj'></div>
 
data:{
	vClass: 'class1',
	vClasses:['class1','class2','class3'],
	vClassObj:{
		class1: true,
		class2: false
	}
}
 
style
表达式绑定值
 绑定对象
 绑定数组
<div :style="{fontSize: styleObj.fontSize}">123</div>
<div :style="styleObj">123</div>
<div :style="styleObjs">123</div>
 
data() {
    return {
        styleObj: {
            fontSize: '40px'
        },
        styleObjs:[{},{}]
    }
}
 
条件渲染
v-show dom结构在,样式为不显示
 v-if dom结构不创建,使用if,else指令的元素必须相邻
 v-if可以配合template使用,包裹同时控制多个结构
<div v-show="!hidden"></div>
<div v-if="n==1"></div>
<div v-else-if="n==2"></div>
<div v-else></div>
 
列表渲染
可遍历:数组,对象属性,字符串,指定次数
 注:尽量使用key,可以提高性能(更新根据KEY复用/替换已经创建的dom,否则将自动根据index作为Key)
<ul>
    <li v-for="person in psersons" :key="id">{{person.name}}</li>
</ul>
<ul>
    <li v-for="(person,index) in psersons" :key="id">{{index}}-{{person.name}}</li>
</ul>
<ul>
    <li v-for="(attr,key) of car" :key="key">{{key}}:{{attr}}</li>
</ul>
<ul>
	<li v-for=(number,index) of 5></li>
</ul>
 
data(){
	persons:[{id:1,name:'a'},{id:2,name:'b'}],
	car:{
		name: 'name',
		prices: 100,
		model: 'model'
	}
}
 
过滤排序
data(){
	minAge: 10,
	sort:0,
	persons:[{id:1,name:'a',age:10},{id:2,name:'b',age:22}]
},
computed:{
	filteredPersons(){
		let arr = this.person.filter((p)=>{return p.age>this.minAge})
		if(this.sort){
			arr.sort((p1,p2)=>{return this.sort === 1 ? p1.age-p2.age : p2.age-p1.age})
		}
	}
},
watch:{
	minAge:{
		immediate: true, // 注意不写此配置,初始渲染会有问题
		handler:function(value){
			this.filteredPersons2 = this.person.filter((p)=>{return p.age>this.minAge});
		}
	}
}
 
数据更新的问题
- 直接在对象中增加属性,没有响应式特性,需使用以下API(不能直接给data添加属性)
 
let vm = new Vue({
	data() {
		myObj:{}
	}
});
Vue.set(vm._data.myObj,'newProp1','value')
// 或
vm.$set(vm.myObj,'newProp2','value')
 
- 直接替换数组中某个元素(根据索引值修改),会导致列表无法更新,需使用已下数组方法
 
替换数组元素
vm.$set(vm.myArr,index,'value')










