#### vue note
---
1、vue.js是什么?
构建数据驱动的web应用开发框架
2、为什么如此受欢迎?
-声明式渲染, 符合前后端分离的趋势
-渐进式框架, 适应葛总业务需求及场景
-快速交付, 可以结合各种第三方UI框架
-企业需求 , 必备技能
3、MVC,MVP,MVVM架构模型对比
-MVC:Controller薄,view 厚, 业务逻辑大多集中在View。
-MVVM:MVVM是认为Controller做了太多数据加工的事情,所以MVVM把`数据加工`的任务从`Controller`中解放了出来,使得`Controller`只需要专注于数据调配的工作,`ViewModel`则去负责数据加工并通过通知机制让View响应ViewModel的改变。(vue并不是完全遵守MVVM模型)双向数据绑定 ,view的变动映射在viewmodel,反之一样。
-MVP:view薄,不部署任何业务逻辑,被称为被动视图(passive view)
---
``` html
<div id="box">
{{name}}
<span>{{age}}</span>
<div>{{htmlname}}</div> //此处只是添加文本,无法添加html标签,支持加减乘除、三目运算,位运算等
<p v-htlm="showhtml">ss</p>
<p v-if="isShow">
动态添加和删除 # 直接删除
</p>
<p v-show="isShow">
动态显示和隐藏 # display:none
</p>
<button v-on:click="handleClick">
</button>
<div v-bind:class="isShow?'sss':'ddd'">
v-bind=:
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
name:"xiaoming", // vue中的变量改变时,会动态渲染前端页面,如果页面有使用到此变量
age:18,
htmlname: "<b>xiaoming</b>",
showhtml:"<b>xiaoming</b>",
isShow:true,
}
methods:{
met:function(){
console.log('111')
}
handleClick(){
console.log(11);
this.name = "asd";
this.age = true;
}
}
})
</script>
```
*计算属性*
```html
<div id="box">
{{name.substring(0,1).toUpperCase()+name.substring(1)}}
<span>{{age}}</span>
<div>计算属性{{changeword}} </div>
<div>普通方法{{changewordmethod}} </div>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
name:"xiaoming",
age:18,
}
methods:{
changewordmethod:function(){ # 每次加载都会重新计算,因为他是普通方法
return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
}
}
computed:{ // 涉及到此属性参与的,页面都会重新渲染,在普通方法中,如果方法被两次调用,name会计算两次,但是计算属性只计算一次,并且缓存起来(如果属性参数或者其依赖改变,name也会重新计算)
changeword:function(){
return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
}
}
})
</script>
```
*watch VS computed*
```html
<div id="box">
<P>单价:<input type="text" v-model="price" /> </P>
{{price}}
<P>数量::<input type="text" v-model="number" /> </P>
{{number}}
<P>总额:<span> {{sum}}</span> </P>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
price:100,
number:10,
sum:
}
watch:{
price:function(newvalue){
this.sum = newvalue*this.number
},
number:function(newvalue){
this.sum = newvalue*this.price
}
}
computed:{
computedsum:function(){
return this.number*this.name
}
}
})
</script>
```
*setter*
```html
<div id="box">
<p class="default" :class="isShow?'aa':'bb'">class样式</p>
<div class="default" :class="active:isShow,show:isShow2">class样式</div>
<p class="default" :class="[who, 'show']"> </p>
// 省略 v-bind -> :
<p class="default" :style="{background: color}"> style样式</p>
// 和上面的等同, 都是响应式的
<p class="default" v-bind:style="obj"> style样式</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
name:xiaoming,
isShow:false,
isShow2:true,
who: "可变变量",
cloor: "red",
obj:{
background:"red",
fontSize:"30px"
}
}
})
</script>
```
**v-if* v-show **动态创建和删除DOM节点 动态隐藏和显示
```html
<div id="box">
// 互斥的两个vue标签 如果v-if一开始是假,那么不会创建此节点 如果有多个标签受同一个变量影响,写起来会比较烦,可以考虑提出这些v-if和v-else,放在同一个容器下,统一控制容器,但可能会破话布局
<P v-if="isCreated">我是v-if创建 </P>
<P v-else="isCreated">我是v-else创建</P>
<P v-if="isCreated">我是v-if创建 </P>
<P v-else="isCreated">我是v-else创建</P>
// template标签并不会实质性的去创建template标签,只是一个虚拟的控制性容器
<template v-if="isCreated">
<P v-if="isCreated">我是v-if创建 </P>
<P v-else="isCreated">我是v-else创建</P>
<P v-if="isCreated">我是v-if创建 </P>
<P v-else="isCreated">我是v-else创建</P>
</template>
// 动态隐藏和显示 如果一开始是假,那么创建出节点,并且为节点加上display=none
<div v-show="isCreated">
动态隐藏和显示
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
isCreated:false,
}
})
</script>
```
**v-for** 把一个数组对应为一组元素,可以在模板渲染时进行遍历,显示
```html
<div id="box">
<ul>
// 遍历显示
<li v-for="data in datalist"> {{data}}</li>
</ul>
<ul>
// 索引和元素的共同取用,用 in和of的效果是相同的
<li v-for="(data,index) in datalist"> {{data}}-----{{index}}</li>
</ul>
<input type="text", v-model="mytext" />
<li v-for="data in computeddatalist"> {{data}} </li>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
// 在vue中,push、pop、shift、unshift、splice、sort、reverse等方法都是可以改变下面的datalist的,并且,vue会对页面进行重新渲染;但是数组如果并未产生实际性的变动时(filter,concat,slice等),页面并不会重新渲染,但可以重新给 通过给数组进行赋值来实现动态刷新
datalist:["aaa", "bbb", "ccc"],
mytext:""
}
computed:{
computeddatalist:function(){
return this.datalist.filter(item=>item.indexOf(this.mytext)>-1)
}
}
})
</script>
```
**键盘事件监听**
```html
<div id="box">
<button @click="count=count-1">-</button>
<p>{{count}}</p>
<button @click="count=count+1">+</button>
<p>{{name}}</p>
<button @click="handleClick">click</button>
// 直接在事件中定义想要传的参数
<button @click="handleClick2('1111', '22222', $event)">click2</button>
// 只有事件源是自身的时候,事件才会发生,否则不会触发事件
<ul @click.self="handleUlClick">
// 阻断冒泡
<li @click.stop="handleClick">111</li>
// 点击只有第一次是有效的,后续不会再次触发
<li @click.once="handeOnce">222</li>
<li>333</li>
</ul>
// 只有在摁下enter的情况下才会触发事件 同理 enter,tab,esc,space,up,down,left,right
<input type="text" @keyup.enter="handleKeyUp" />
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
count:1,
name: "xiaoming"
},
methods:{
handleClick(ev){
// ev就是事件的触发源
console.log(ev.target.value);
this.name="aaa";
},
handleclick2(data1, data2, ev){
console.log(data1);
console.log(data2);
console.log(ev.target)
},
handleClick(){
console.log("li点击");
},
handleUlClick(){
console.log("ul点击")
}
handleKeyUp(ev){
console.log(ev.keyCode);
if(ev.keyCode==13){
console.log(ev.target)
}
}
}
})
</script>
```
**表单输入绑定**
```html
<div id="box">
// 输入框中输入的值和外面的值是相互绑定的
<input type="text" v-model="mytext" />
{{mytext}}
<p>
<imput type="checkbox" v-mdoel="isChecked">记住用户名
</p>
// 每次勾选都会在checkgroup添加一个checkbox的value值,取消勾选会在checkgroup中再次移除
<p><input type="checkbox" v-model="checkgroup" value="1"/>aaa</p>
<p><input type="checkbox" v-model="checkgroup" value="2"/>bbb</p>
<p><input type="checkbox" v-model="checkgroup" value="3"/>ccc</p>
// vue提供的单选框功能,无须获取dom节点,直接访问picked
<p><input type="raido" v-model="picked" value="vue"/>{{picked}}</p>
// 此处在输入框内修改输入的内容,外面的name并不会随之改变,但是当鼠标移走之后,外部的那么值会立刻改变,此为lazy。如果想限制输入的内容必须为数字的话,可以把lazy换位.number,如果想去除输入内容的头尾空格,那么可以把lazy换位trim
<p><input type="text" v-model.lazy="name" value=""/>{{name}}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
name:xiaoming,
mytext:"111",
isChecked:false,
checkgroup:[],
picked:"vue",
}
})
</script>
```
**组件的使用**封装的,可重用的html
*组件分为全局组件和局部组件
```html
<div id="box">
<hello></hello>
<hellobox></hellobox>
</div>
<div id="box2">
// 重新初始化后可以复用全局组件
<hello></hello>
//下面这个并不会被渲染出来,会报错,因为hellobox是box的独有的
<hellobox></hellobox>
</div>
<script type="text/javascript">
// 父子组件的状态是无法共享的
Vue.component("hello",{
template:
`
<div>
一个hello组件{{name}}
<ul>
// datalist 也必须用函数方法定义出来
<li v-for="data in datalist>{{data}}</li>
</ul>
</div>
`
// data:"name" 在组件中,这是无法使用的,并且会报错,必须定义为方法,才可以调用
data:function(){
return {
name:"xiaoming",
datalist:['aaa', 'bbb']
}
}
})
var vm = new Vue({
el:"#box",
data:{
},
components:{
"hellobox":{
template:
`<div>box下面独有的组件,非全局组件</div>`
}
}
var vm2 = new Vue({
el:"#box2",
data:{
}
})
})
</script>
```
**组件之间的通信**父子组件
使用vue绑定自定义事件:
每个Vue的实例都实现了事件的接口:
* 使用 $on(eventname)监听事件;
* 使用$emit(evenvname)触发事件;
```html
<div id="box">
// hello里面的handleparentclick是父组件定义的监听,也就是说这个事件监听是父组件进行的
<hello name="xiaoming" :age="100" @event="handleParentClick"></hello>
</div>
<script type="text/javascript">
var obj = {
template:`
<div> 我是{{name}}---{{age}}组件</div>
//
<button @click="handleclick">click</click>
`,
// 接收子组件的一些属性值,并存储,props是单向的,
props: {
name:String,
age:Number,
},
}
var vm = new Vue({
el:"#box",
data:{
},
components:{
hello: obj
},
methods:{
handleParentClick(){
console.log("parent_click", "click")
}
}
})
</script>
```
```html
<div id="box">
<hello name="xiaoming"></hello>
</div>
<script type="text/javascript">
var obj = {
template:`
<div> 我是{{name}}组件</div>
`,
// 接收子组件的一些属性值,并存储,props是单向的,
props: ["name"]
}
var vm = new Vue({
el:"#box",
data:{
},
components:{
hello:{
}
}
})
</script>
```
**非父子组件之间的通信**
vue的非父子 组件之间的通信一般有两种方法:
-- 中央事件总线 bus=new Vue();
* mounted生命周期中进行监听
# --vuex 状态 管理 后面再说这个
```html
<div id="box">
<hello name="xiaoming"></hello>
</div>
<script type="text/javascript">
var bus = new Vue()
var helloA = {
template:`
<div>我是组件A
<button @click="handleClick>click</button>
</div>
`
,
methods:{
handleClick(){
//将要发消息给B组件
bus.$emit("xiaoming", "来自组件A的消息")
}
}
}
var helloB = {
template:`
<div>我是组件B</div>
`,
//组件生命周期
mounted(){
console.log("b组件挂在的钩子函数");
bus.$on("xiaoming", function(value){
console.log(value)
})
}
}
var vm = new Vue({
el:"#box",
data:{
},
components:{
helloA:helloA,
helloB:helloB,
},
methods:{
handleParentClick(data){
console.log("parent", data);
}
}
})
</script>
```
**slot插槽分发**
``` html
<div id="box">
<hello name="xiaoming">
<button @click="handleClick" slot="leftbutton">leftbutton</button>
<span slot="content">title_content</span>
<button @click="handleClick" slot="rightbutton">rightbutton</button>
</hello>
<hello>
<span slot="content">标题内容</span>
<button @click="handleClick" slot="rightButton">右侧按钮</button>
</hello>
<hello>
<button @click="handleClick" slot="leftbutton">左侧按钮</button>
<span slot="content">标题内容</span>
</hello>
</div>
<script type="text/javascript">
var obj = {
template:`<div>
<slot name="leftbutton></slot>
<slot name="content></slot>
<slot name="rightbutton></slot>
div>
`
}
new Vue({
el:#box,
data:{
},
components:{
hello:obj
}
},
methods:{
handleClick(){
console.log("button_click")
}
}
)
</script>
```
**动态组件**
* component元素,动态的绑定多个组件到它的
* keep-alive,保留状态,避免组件重新渲染
```html
<div id="box">
<keep-alive>
<component :is="current"></component>
</keep-alive>
<footer>
<ul>
<li @click="handleclick('home')">home</li>
<li @click="handleclick('list')">list</li>
<li @click="handleclick('shopcar')">shopcar</li>
</ul>
</footer>
</div>
<script type="text/javascript">
var home = ({
template:`
<div>home组件</div>
`
})
var list = ({
template:`
<div>list</div>
`
})
var shopcar = ({
template:`
<div>shopcar</div>
`
})
</script>
```
网友评论