## 基础
### 过滤器
通过`{{msg | filter}}`这个形式,可以声明一个带过滤器的模板语法,msg会作为参数传个filter这个函数的第一个参数,将返回值作为最后渲染到DOM的值。
filter是一个JS函数,可以接收多个参数,当参数不唯一时,`{{msg | filter(arg1, arg2)}}`,会将msg作为第一个参数传给filter函数,arg1和arg2作为第二三个参数。
同时,也支持多个过滤器串联,`{{msg | filter1 | filter2}}`会将msg作为参数传给filter1,将处理完成后的返回值作为参数传给filter2。
### 计算属性
set(一般不写)
get(默认写的方法是get方法)
可以理解为缓存,只有在改变时才会重新调用。
### v-on
**修饰符:**
`.stop`:阻止事件冒泡
`.prevent`:阻止默认事件。(例:表单submit按钮点击默认会跳转页面)
`.{keyCode|keyAlisa}`:键盘指定按键按下时才会触发。(例:@keyup.enter=“enterClick”)
`.once`:使得事件只触发一次。
`.native`:监听组件根元素的原生事件。
### v-for
`:key`:为了提高插入删除列表的性能,key不应该重复。(相当于把一个数组变成了链表)
- vue操作数组时,通过索引修改数组值的方式不是响应式的!不会动态渲染到页面!要使用`splice`来替换值,或者通过vue内建的函数set来更改。例:`Vue.set(this.list, index, "something")`
### v-model
**修饰符:**
`.lazy`:当键入enter或失去焦点时才更新绑定值,默认是实时输入实时修改的。
`.number`:将输入框中的值转化为数值类型,默认输入的值一律作为字符串。
`.trim`:将输入获取的值前后去空格。
## 组件化
### 定义组件
> 定义、注册、使用组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <body> <div id="app"> <cpn4></cpn4> <cpn3></cpn3> <cpn1></cpn1> </div> </body> <script> // 定义组件 const cpn4 = Vue.extend({ template:` <div> <h2>我是标题4</h2> <p>我是内容4</p> </div> ` }) // 注册全局组件 Vue.component("cpn4", cpn4)
// 语法糖写法,直接注册时定义组件 Vue.component("cpn3",{ template:` <div> <h2>我是标题3</h2> <p>我是内容3</p> </div> ` })
const cpn2 = Vue.extend({ template:` <div> <h2>我是标题2</h2> <p>我是内容2</p> </div> ` })
const cpn1 = Vue.extend({ // 注:模板中只能由一个根元素!推荐用div把模板包裹起来 // 子组件可以使用全局组件和注册的子组件 template: ` <div> <h2>我是标题1</h2> <p>我是内容1</p> <cpn2></cpn2> <cpn3></cpn3> </div> `, // 注册子组件 components: { cpn2: cpn2, } })
var vm = new Vue({ el: "#app", data: {}, components: { // 注册局部组件 cpn1: cpn1 } })
|
### 模板分离
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template id="tp1"> <div> <div>模板分离!</div> <hr> </div> </template>
<script> Vue.component("cpn", { template: "#tp1" }) </script>
|
### 数据绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <body> <div id="app"> <cpn></cpn> <cpn1></cpn1> </div> </body>
<template id="t1"> <div> <h2>T1!</h2> </div> </template> <template id="t2"> <div> <h2>T2!</h2>
<div>{{ msg }}</div> </div> </template>
<script> Vue.component("cpn1",{ data: function (){ return{ msg: "这是cpn1!" } }, template:"#t2" })
var vm = new Vue({ el: "#app", data:{}, components: { cpn:{ template: "#t1", } } }) </script>
|
### 数据传递
> 父传子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <body> <div id="app">
<cpn :message="msg" :mv="movie"></cpn> </div> </body>
<template id="t0"> <div> <h2>{{ message }}</h2> <ul> <li v-for="item in mv">{{ item }}</li> </ul> </div> </template> <script> var cpn = { template: "#t0",
props: { prop1: [String, Number], message: { type: String, default: "aaa", required: true }, mv: Array, testLs: { type: Array, default: function (){ return [] } }, prop2: { validation: function (value){ return ["yes", "no"].indexOf(value) !== -1 } } }
}
var vm = new Vue({ el: "#app", data:{ msg: "这是数据", movie: ["哪吒","姜子牙","喜剧之王"] }, components:{ cpn } })
|
vm根组件中的data数据,通过cpn标签的v-bind绑定到message和mv属性中,cpn组件通过props将属性值message和mv存储为data,可以被组件内使用,实现数据传递。
- 注:属性值字段不支持驼峰命名,如果使用,在html传值时要转化为短横线命名。例如:`props=["cArc"]`,则在html中传值时要`
`
> 子传父
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| <body>
<div id="app"> <parent></parent> </div>
</body>
<template id="c"> <div>
<button @click="onclicked">我是子组件</button> </div> </template> <template id="p"> <div> <h2>我是父组件</h2>
<children @btnclick="clicked"></children> </div> </template>
<script> var children = { template: "#c", methods: { onclicked:function (){ this.$emit("btnclick") }, } }
Vue.component("parent",{ template:"#p", components: {children}, methods: { clicked: function (){ console.log("子组件被点击了"); alert("1"); } }, })
var vm = new Vue({ el:"#app", data:{}, }) </script>
|
### 组件间访问
> 父访问子 $children \$refs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <body> <div id="app"> <cpn></cpn> <cpn></cpn> <cpn ref="aaa"></cpn> <button @click="btnClick">点我</button> <button @click="btnRef">Ref点我</button> </div> </body>
<template id="c"> <div> <h2>我是一个组件</h2> </div> </template>
<script> let cpn = { template:"#c", data: function (){ return { msg: "子组件的msg" } }, methods:{ printMsg: function (){ console.log("子组件打印的") } } }
const app = new Vue({ el: "#app", data: {}, methods: { btnClick:function (){ console.log(this.$children); console.log(this.$children[0].msg); this.$children[0].printMsg(); }, btnRef: function (){ console.log(this.$refs); console.log(this.$refs.aaa.msg); this.$refs.aaa.printMsg(); } }, components:{ cpn } }) </script>
|
> 子访问父 $parent \$root(访问根组件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| <body> <div id="app"> <cpn></cpn> </div> </body>
<template id="c"> <div> <h2>我是一个组件</h2> <kid></kid> </div> </template>
<template id="kid"> <div> <h2>子子组件</h2> <button @click="kidClick">子子组件的按钮</button> </div> </template> <script> let kid = { template: "#kid", data: function (){ return { msg: "子子组件的msg" } }, methods: { kidClick: function (){ console.log("子子组件的parent:"); console.log(this.$parent.msg); console.log("子子组件的root:"); console.log(this.$root.msg); } } }
let cpn = { template:"#c", data: function (){ return { msg: "子组件的msg" } }, methods:{}, components: { kid } }
const app = new Vue({ el: "#app", data: { msg: "root的msg" }, methods: { btnClick:function (){ console.log(this.$children); console.log(this.$children[0].msg); this.$children[0].printMsg(); }, btnRef: function (){ console.log(this.$refs); console.log(this.$refs.aaa.msg); this.$refs.aaa.printMsg(); } }, components:{ cpn } }) </script>
|
### 插槽
> slot
会用标签内部的内容替换插槽,可以预先定义插槽默认值,缺省使用默认值。当存在多个插槽时,标签内的内容会映射到每一个插槽。
> 具名插槽
1
| <slot name="xxx"></slot>
|
这样,在默认使用插槽时,只会替换具名插槽,要使用具名插槽需要添加`slot`属性显式的指定使用的插槽名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <body> <div id="app">
<cpn></cpn> <cpn>
<p>我是插槽内的p标签</p> </cpn> <ncpn>
<p slot="right">我是右边插槽的</p> <p slot="left">我是右边插槽的</p>
<p>我是不使用具名插槽的</p> </ncpn> </div>
</body> <template id="cpn"> <div> <h2>我是组件</h2> <slot>我是默认值</slot> <slot>我是默认值</slot> </div> </template>
<template id="ncpn"> <div> <h2>我是具名插槽组件</h2> <slot>我是默认值</slot> <slot>我是默认值</slot> <slot>我是默认值</slot> <slot name="left"></slot> <slot name="center"></slot> <slot name="right"></slot> </div> </template> <script> let cpn = { template: "#cpn" } let ncpn = { template: "#ncpn" } const app = new Vue({ el: "#app", components:{ cpn, ncpn } }) </script>
|
> 作用域插槽
在组件作用域外获取组件的数据。
1. 给slot插槽定义属性,并将属性通过v-bind绑定到需要的data上。
2. 在使用组件时,标签内填充插槽时,通过`v-slot:插槽名=“插槽属性名”`获取到插槽的所有属性,通过`插槽属性.属性名`获取属性名对应的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <body> <div id="app"> <cpn>
<template v-slot:user="slotProps">
{{ slotProps.data }} </template> </cpn> </div> </body>
<template id="cpn"> <div>
<slot name="user" :data="msg"></slot> </div> </template>
<script> let cpn = { template: "#cpn", data: function (){ return { msg: "cpn里的data!" } } } const app = new Vue({ el: "#app", data: {}, components: {cpn} }) </script>
|
## webpack
是一个`打包工具`!