1.Vue
-
官方介绍
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。 -
引入方式
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
2.Vue拦截原理
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因
注意:
Object.defineProperty有以下缺点
1、无法监听es6的Set、Map 变化;
2、无法监听Class类型的数据;
3、属性的新加或者删除也无法监听;
4、数组元素的增加和删除也无法监听。
针对Object.defineProperty的缺点,ES6 Proxy都能够完美得解决,唯一的缺点就是,对IE不友好
3.Vue模板语法
v-show v-if指令
<div v-show="isShow">动态显示和隐藏</div>
<div v-if="isCreated">动态创建和删除</div>
todolist
<body>
<div id="box">
<!-- 双向绑定的指令 -->
<input type="text" v-model="mytext"/>
<button @click="handleAdd()">add</button>
<div v-show="!datalist.length">待办事项空空如也</div>
<ul v-show="datalist.length">
<li v-for="(item,index) in datalist">
{{item}}--{{index}}
<button @click="handleDel(index)">del</button>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"11111",
datalist:["111","222","333"]
},
methods:{
handleAdd(){
console.log("add",this.mytext)
this.datalist.push(this.mytext)
this.mytext = "" //清空value
},
handleDel(index){
console.log("del",index)
this.datalist.splice(index,1)
}
}
})
</script>
</body>
v-html指令
<div v-html="myhtml"></div>
4.class与style
- 点击变色:
<body>
<div id="box">
<ul>
<li v-for="(item,index) in datalist" :class=" current===index?'active':'' " @click="handleClick(index)">
{{item}}
</li>
</ul>
</div>
<script>
new Vue({
el:"#box",
data:{
current:0,
datalist:["1","2","3"]
},
methods:{
handleClick(index){
console.log(index)
this.current = index
}
}
})
</script>
</body>
- vue2-class&style
<body>
<div id="box">
<div :class="classobj">动态切换class-1-对象</div>
<div :class="classarr">动态切换class-2-数组</div>
<div :style="styleobj">动态切换style-1-对象</div>
<div :style="stylearr">动态切换style-2-数组</div>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
classobj:{
aa:true,
bb:true,
cc:false
},
classarr:["aa","bb"],
styleobj:{
backgroundColor:'red'
},
stylearr:[{backgroundColor:"yellow"}]
}
})
// vue2 解决方案, Vue.set(对象,属性,true) Vue.set(vm.classobj,"dd",true)
// vue3 支持动态增加属性的拦截
</script>
</body>
- vue3-class&style
<script>
var obj = {
//函数式
data(){
return {
myname:"kerwin",
mytext:"",
classobj:{
aa:true,
bb:true,
cc:false
}
}
},
methods:{
handleAdd(){
console.log("add",this.mytext)
this.classobj.dd=true
}
}
}
var vm = Vue.createApp(obj).mount("#box")
</script>
5.条件渲染
<div v-if="isCreated">111111</div>
<div v-else>222222</div>
<body>
<div id="box">
<template v-if="isCreated">
<div>11111111</div>
<div>22222222</div>
<div>33333333</div>
</template>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
isCreated:true
}
})
/*
template 就是一个包装元素, 不会真正创建在页面上.
*/
</script>
</body>
6.列表渲染
<body>
<div id="box">
<ul>
<li v-for="(item,index) of datalist" :key="item">
{{item}}--{{index}}
</li>
</ul>
<ul>
<li v-for="(item,key) of obj">
{{key}} - {{item}}
</li>
</ul>
<ul>
<li v-for="item in 10">
{{item}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
datalist:["1111","2222","3333"],
obj:{
name:"kerwin",
age:100,
location:"dalian"
}
}
})
</script>
</body>
7.模糊查询
<div id="box">
<!-- input change事件区别 -->
<input type="text" @input="handleInput" v-model="mytext"/>
<ul>
<li v-for="data in datalist" :key="data">
{{data}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"",
datalist:["aaa","add","bbb","bbc","ccc","ddd","eee","ade"],
originList:["aaa","add","bbb","bbc","ccc","ddd","eee","ade"]
},
methods:{
handleInput(){
console.log("input",this.mytext)
// es5 filter
setTimeout(()=>{
this.datalist = this.originList.filter(item=> item.includes(this.mytext) )
},2000)
// console.log(newlist)
}
}
})
var arr =["aaa","add","bbb","bbc","ccc","ddd","eee","ade"]
var newlist = arr.filter(item=> item.includes("a") )
console.log(newlist,arr)
</script>
函数表达式方案
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"",
datalist:["aaa","add","bbb","bbc","ccc","ddd","eee","ade"],
},
methods:{
test(){
console.log("test--------------")
return this.datalist.filter(item=> item.includes(this.mytext) )
}
}
})
</script>
8.事件处理器
1、监听事件-直接触发代码
2、方法事件处理器-写函数名 handleClick
3、内联处理器方法-执行函数表达式 handleClick($event) $event 事件对象
<body>
<div id="box" >
{{count}}
<button @click="handleAdd1($event,1,2,3)">add-1-函数表达式</button>
<button @click="handleAdd2">add-2-函数名</button>
<input type="text" @input="handleInput"/>
</div>
<script type="text/javascript">
new Vue({
el:"#box",
data:{
count:1
},
methods:{
handleAdd1(evt,a,b,c){
console.log(evt,a,b,c)
this.count++
},
handleAdd2(evt){
this.count++
console.log(evt.target)
},
handleInput(evt){
console.log("input",evt.target.value)
}
}
})
</script>
</body>
9.事件修饰符
事件修饰符https://cn.vuejs.org/v2/guide/events.html
stop
prevent
capture
self
once
passive
模态框案例
<head>
<style>
#overlay {
background: rgba(0, 0, 0, 0.6);
width: 100%;
margin: auto;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#center {
background: #ffff;
border-radius: 5px;
padding-top: 15px;
padding-left: 30px;
padding-bottom: 15px;
width: 290px;
height: 160px;
position: fixed;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
</head>
<body>
<!-- 模态框 -->
<div id="box">
<button @click="isShow=true">show</button>
<div id="overlay" v-show="isShow" @click.self="isShow=false">
<div id="center">
<div>用户名:<input type="text"/></div>
<div>密码:<input type="password"/></div>
<div>
<button>登录</button>
</div>
</div>
</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
isShow: false,
}
})
</script>
</body>
10.表单控件绑定
<body>
<div id="box">
{{mytext}}
<textarea v-model="mytext"></textarea>
<div>
<div>用户名:<input v-model="mytext"/></div>
<input type="checkbox" v-model="isRemember"/> 记住用户名
<button @click="handleLogin">登录</button>
</div>
<div>
<h2>注册页面-兴趣爱好</h2>
<input type="checkbox" v-model="checkList" value="vue"/> vue
<input type="checkbox" v-model="checkList" value="react"/> react
<input type="checkbox" v-model="checkList" value="wx"/> 小程序
</div>
{{checkList}}
<div>
<h2>性别选择</h2>
<input type="radio" v-model="select" value="a"/> 男
<input type="radio" v-model="select" value="b"/> 女
</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
mytext: localStorage.getItem("username"),
isRemember:true,
checkList:[],
select:"a"
},
methods:{
handleLogin(){
if(this.isRemember){
localStorage.setItem("username",this.mytext)
}
console.log(this.mytext,this.checkList,this.select)
}
}
})
</script>
</body>
11.表单修饰符
.lazy :失去焦点同步一次
.number :格式化数字
.trim : 去除首尾空格
<body>
<div id="box">
<!-- lazy修饰符 -->
<input v-model.lazy="mytext"/>
{{mytext}}
<input type="number" v-model.number="myage"/>
<input type="text" v-model.trim="myusername"/>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
mytext:"",
myage:0,
myusername:""
}
})
</script>
</body>
12.计算属性
计算属性是基于它们的依赖进行缓存的。
计算属性只有在它的相关依赖发生改变时才会重新求值
<body>
<div id="box">
{{ myname.substring(0,1).toUpperCase() + myname.substring(1) }}
{{ myComputedName }}
{{ myComputedName }}
{{ myComputedName }}
{{ myMethodName() }}
{{ myMethodName() }}
{{ myMethodName() }}
</div>
<script>
//计算属性(防止模板过重,难以维护),负责逻辑放在计算属性中来写。
// 计算属性 有缓存, 基于依赖的缓存
var vm = new Vue({
el:"#box",
data:{
myname:"zzz",
},
//方法:
methods:{
myMethodName(){
console.log("myMethodName-方法")
return this.myname.substring(0,1).toUpperCase() + this.myname.substring(1)
}
},
//计算的
computed:{
myComputedName(){
console.log("myMethodName-计算属性")
return this.myname.substring(0,1).toUpperCase() + this.myname.substring(1)
}
}
})
/*
0. data => 状态,被拦截。
1. 方法==》 事件绑定, 逻辑计算。可以不用return,没有缓存
2. 计算属性(重视结果)=》 解决模板过重问题,必须有return ,只求结果 ,有缓存,同步。
3. watch (重视过程), 监听一个值的改变。 不用返回值 ,异步同步
*/
</script>
</body>
13.watch
<body>
<div id="box">
<!-- input change事件区别 -->
<input type="text" v-model="mytext"/>
<ul>
<li v-for="data in datalist" :key="data">
{{data}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"",
datalist:["aaa","add","bbb","bbc","ccc","ddd","eee","ade"],
originList:["aaa","add","bbb","bbc","ccc","ddd","eee","ade"]
},
watch:{
mytext(newval){
console.log("改变了",newval)
setTimeout(()=>{
this.datalist = this.originList.filter(item=> item.includes(newval) )
},1000)
}
}
})
</script>
</body>
14.fetch-get
-
fetch
why:
XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱,
而且基于事件的异步模型写起来不友好。
兼容性不好
polyfill:https://github.com/camsong/fetch-ie8
//get
get url路径 ?name=kerwin&age=100
post body请求体 ,
(1)x-www-formurlencoded , name=kerwin&age=100
(2)json , `{"name":"kerwin",age:100}`
15.fetch-post
// post-1
fetch("**",{
method:'post',
headers: {
"Content‐Type": "application/x‐www‐form‐urlencoded"
},
body: "name=kerwin&age=100",
}).then(res=>res.json()).then(res=>{console.log(res)});
// post-2
fetch("https://m.vip.com/server.html?rpc&method=pageCache&f=www&_=1563946036520",{
method:'post',
headers: {
"Content‐Type": "application/json"
},
body: JSON.stringify({
name:"kerin",
age:100
})
}).then(res=>res.json()).then(res=>{console.log(res)});
16.axios
axios.post("****","name=kerwin&age=100") // (1)
axios.post("****",{name:"kerwin",age:100}) //(2)
17.猫眼数据
<body>
<div id="box">
<button @click="handleAjax">click-ajax</button>
<ul>
<li v-for="item in datalist" :key="item.id">
<img :src="handleImg(item.img)"/>
{{item.nm}}
</li>
</ul>
</div>
<script >
new Vue({
el:"#box",
data:{
datalist:[]
},
methods:{
handleAjax(){
axios.get("./json/maoyan.json").then(res=>{
console.log(res.data.movieList)
this.datalist = res.data.movieList
//for 处理
})
},
handleImg(url){
return url.replace('w.h/','')+'@1l_1e_1c_128w_180h'
}
}
})
</script>
</body>
18.组件定义
组件化:
扩展 HTML 元素,封装可重用的代码
- 起名字 :js驼峰, html 链接符-
- dom片段 没有代码提示 没有高亮显示 – vue单文件组件解决
- css 只能写成 行内。- vue单文件组件解决
- template 包含一个根节点
- 组件是孤岛,无法直接访问外面的组件的状态或者方法。- 间接的组件通信来交流。
- 自定义的组件 data 必须是一个函数,
- 所有的组件都在一起, 太乱了-vue单文件组件解决
//定义一个全局的组件
Vue.component("kerwinNavbar",{
//dom, js ,css
template:`<section style="background:red;border:5px solid black;">
<button @click="handleLeft">left</button>
猫眼电影-{{myname}}
<button @click="handleRight">right</button>
<child></child>
<kerwin-child></kerwin-child>
</section>`,
methods:{
handleLeft(){
console.log("left")
},
handleRight(){
console.log("right")
}
},
computed:{},
watch:{},
//data必须是函数写法
data(){
return {
myname:"11111111"
}
},
//局部
components:{
"kerwinChild":{
template:`
<div>child-{{myname}}</div>
`,
data(){
return {
myname:"child-11111"
}
}
}
}
})
Vue.component("child",{
template:`
<div style="background:yellow">公司标语</div>
`
})
//根组件
new Vue({
el:"#box",
data:{
}
})
19.父传子
<script>
Vue.component("navbar",{
props:{
myname:{
type:String,
default:""
},
myright:{
type:Boolean,
default:true
},
myparent:{
type:String,
default:""
}
},//接受myname属性, 属性验证, 默认属性
template:`<div>
<button>left</button>
<span>{{myname}}--{{myparent}}</span>
<button v-show="myright">right</button>
</div>`
})
new Vue({
el:"#box",
data:{
parent:"11111111111111111111111111"
}
})//创建根组件
</script>
20.子传父
<body>
<div id="box">
<navbar @myevent="handleEvent"></navbar>
<sidebar v-show="isShow" ></sidebar>
</div>
<script>
Vue.component("navbar", {
template: `
<div style="background-color: red;">
<button @click="handleClick()">点击</button>-导航栏
</div>
`,
methods:{
handleClick(){
// console.log("子传父, 告诉父组件 ,取反您的isShow")
this.$emit("myevent",1000000000)
}
}
})
Vue.component("sidebar", {
template: `
<div style="background-color: yellow;" >
<ul>
<li>11111</li>
<li>11111</li>
</ul>
</div>
`
})
new Vue({
el: "#box",
data: {
isShow: true
},
methods:{
handleEvent(data){
console.log("父组件的定义的事件",data)
this.isShow = !this.isShow
}
}
})
</script>
</body>