一.vue成员获取
vue成员中除data外其他成员需要用$options.成员名(比如$options.methods)来获取.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <h1 @click="btnClick">{{ msg }}</h1> <p>{{ 10 | add }}</p> <p>{{ $data }}</p> <p>{{ $options.arr }}</p> </div> </body> <script src="js/vue.js"></script> <script> let app = new Vue({ el: '#app', data: { msg: '数据', a: 1, b: 2, }, methods: { btnClick() { console.log(this.msg) } }, filters: { add(v) { return v+1 } }, arr: [1, 2, 3, 4], }); console.log(app.msg); console.log(app.$data); console.log(app.$options.methods); console.log(app.$options.arr); </script> </html>
二.pre指令
v-pre的内部解除vue控制
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <p v-pre> <!--v-pre的内部解除vue控制--> <!--{{}}不是插值表达式,msg不是变量,v-on不是指令,都是原义输出--> <p>{{ msg }}</p> <span v-on="abc"></span> </p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: "message" } }) </script> </html>
三.循环指令
通过v-for可遍历列表,字典或者列表套字典等可迭代对象,可以嵌套,可以拿到索引,对于字典第一个参数是value
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <p>{{ arr }}</p> <div> <!--值 遍历--> <p v-for="v in arr"> <span>{{ v }}</span> </p> </div> <div> <!--值,索引 遍历--> <p v-for="(v, i) in arr"> <span>第{{ i + 1 }}个值:{{ v }}</span> </p> </div> <p>{{ student }}</p> <div> <p v-for="(v, k, i) in student"> <span>{{ k, v, i | f1 }}</span> </p> </div> <div> <!-- name: Bob | aendge:18 | ger:男 name: Tom | age:1 | gender:男 --> <p v-for="stu in stus"> <!--<span v-for="(v, k, i) in stu">{{i?' | ':''}}{{k}}:{{v}}</span>--> <span v-for="(v, k, i) in stu">{{i|f2}}{{k}}:{{v}}</span> </p> </div> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { arr: [1, 4, 2, 3, 5], student: { 'name': 'Bob', 'age': 18, 'gender': '男' }, stus: [ { 'name': 'Bob', 'age': 18, 'gender': '男' }, { 'name': 'Tom', 'age': 20, 'gender': '男' } ] }, filters: { f1(k, v, i) { // return k + ":" + v + '(' + i + ')' return `${k}:${v}(${i})` }, f2(i) { // i为0代表假,返回'',其它索引时返回' | ' return i ? ' | ' : '' } } }) </script> </html>
四.todolist案例:
在input框中输入数据,点击提交按钮后触发点击事件,数据以数组形式添加,input内容会清空,而缓存中以json字符串保存,data中
提交的数据则是json解析后的空数组或者是缓存记录的数组,页面渲染的就是for循环之后的一条条数据,可用无需列表展示;
在展示的数据上还可以绑定删除点击事件,把索引传给methods中的删除函数, this.msgs.splice(i, 1),第二个参数是条数,第三个
参数是替换后的内容,删除后也要保存到sessionstorage后者localstorage中
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>todolist</title> <style> li:hover { color: red; cursor: pointer; } </style> </head> <body> <div id="app"> <p> <input type="text" v-model="info"> <button @click="addMsg">留言</button> <ul> <li v-for="(msg, i) in msgs" @click="delFn(i)">{{ msg }}</li> </ul> </p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { info: '', // msgs: ['11111', '22222'], // msgs: sessionStorage.msgs && JSON.parse(sessionStorage.msgs) || [], // sessionStorage存放数组和字典需要JSON字符串参与 msgs: JSON.parse(sessionStorage.msgs || '[]'), }, methods: { addMsg() { let info = this.info; if (info) { // this.msgs.push(this.info); // 尾增 this.msgs.unshift(this.info); // 首增 // 清空留言框 this.info = ''; sessionStorage.msgs = JSON.stringify(this.msgs); } }, delFn(i) { this.msgs.splice(i, 1); sessionStorage.msgs = JSON.stringify(this.msgs); } } }) </script> </html>
五.分隔符成员
修改插值表达式符号,一般修改为${ }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> {{ msg }} [[ msg }} ${ msg } </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: 'message' }, // 修改插值表达式符号 // delimiters: ['[[', '}}'], // delimiters: ['${', '}'], }) </script> </html>
六.计算属性成员(写在computed字典中)
1) 计算后属性不需要在data中重复定义
2) 计算后属性必须渲染后,绑定的方法才会生效
3) 计算后属性绑定的方法中的任意变量值更新,方法都会被调用
4) 计算后属性为只读属性(不可写)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <p> <input type="text" v-model="a"> <input type="text" v-model="b"> </p> <!--报错:计算后属性为只读属性--> <!--<input type="text" v-model="xyz">--> <!--关键:计算后属性必须渲染后,绑定的方法才会生效--> <p>{{ xyz }}</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { a: '', b: '', // 报错:计算后属性不需要在data中重复定义 // xyz: '', }, computed: { // 1) 计算后属性不需要在data中重复定义 // 2) 计算后属性必须渲染后,绑定的方法才会生效 // 3) 计算后属性绑定的方法中的任意变量值更新,方法都会被调用 // 4) 计算后属性为只读属性(不可写) xyz () { // a值一变化,该方法就会被回调 // 原因:计算后属性绑定的方法中的任意变量值更新,方法都会被调用 this.a; this.b; console.log('该方法调用了') } // 使用场景:一个计算后属性的值,可以来源于多个属性值 } }) </script> </html>
案例: 使用场景 (一个计算后属性的值,可以来源于多个属性值)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <p> 姓:<input type="text" v-model="first_name"> 名:<input type="text" v-model="last_name"> </p> <p>{{ full_name }}</p> </div> </body> <script src="js/vue.js"></script> <script> // 使用场景:一个计算后属性的值,可以来源于多个属性值 new Vue({ el: '#app', data: { first_name: '', last_name: '', }, computed: { full_name () { if (this.first_name && this.last_name) return this.first_name + ' ' + this.last_name; return '姓名' } } }) </script> </html>
七.监听属性成员(watch)
1) 监听绑定的属性,该属性可以get、set
2) 监听的属性一旦发生值更新,绑定的方法就会被调用
3) 监听的属性是已定义的属性(必须在data中定义)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <input type="text" v-model="num_a"> <p>num_a: {{ num_a }}</p> <p>num_b: {{ num_b }}</p> <p>num_c: {{ num_c }}</p> </div> </body> <script src="js/vue.js"></script> <script> new Vue({ el: '#app', data: { num_a: '', num_b: '', num_c: '', }, watch: { // 1) 监听绑定的属性,该属性可以get、set // 2) 监听的属性一旦发生值更新,绑定的方法就会被调用 // 3) 监听的属性是已定义的属性(必须在data中定义) num_a() { console.log('num_a值更新,该方法被调用'); this.num_b = this.num_a * 10; this.num_c = this.num_a * 20; }, } // computed: { // num_b() { // return this.num_a * 10 // }, // num_c() { // return this.num_a * 20 // }, // } }) </script> </html>
八.组件
组件:由 template + css + js 三部分组成(.vue文件)
1)组件具有复用性
2) 复用组件时,数据要隔离
3) 复用组件时,方法不需要隔离,因为方法使用隔离数据就可以产生区别
组件介绍:
1) 每一个组件都有自己的template(虚拟DOM),最后要替换掉真实DOM(渲染)
2) 挂载点el,在根组件没有规定template,用挂载的真实DOM拷贝出虚拟DOM,完成实例创建后再替换掉真实DOM(渲染)
3) 挂载点el,在根组件规定template,就采用自己的template作为虚拟DOM,挂载点还是必须的,用于占位
4) 所有 new Vue() 产生的组件都称之为根组件 - 项目开发时,整个项目只有一个根组件
5) template只能解析一个根标签
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> {{ msg }} </div> </body> <script src="js/vue.js"></script> <script> let num = 100; new Vue({ el: '#app', data: { msg: 'message' }, // template: '<div id="main"><p>{{ msg }}</p><p>{{ msg }}</p></div>' template: ` <div id="main"> <p>{{ msg }}</p> <p>{{ msg }}</p> <div>{{ msg }}</div> <div>${ num }</div> </div> `, }) </script> </html>
九.局部组件:
创建组件------注册组件--------组件渲染
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .ad { width: 200px; padding: 5px; margin: 5px; box-shadow: 0 0 5px 0 gold; float: left; } .ad img { width: 100%; } .ad h4 { margin: 0; font: normal 20px/30px '微软雅黑'; text-align: center; } </style> </head> <body> <div id="app"> <!--<div class="ad">--> <!--<img src="img/mn.jpg" alt="">--> <!--<h4>美女</h4>--> <!--</div>--> <!--<ad></ad>--> <!--<ad></ad>--> <!--3)组件渲染--> <local-tag></local-tag> <local-tag></local-tag> <local-tag></local-tag> </div> </body> <script src="js/vue.js"></script> <script> // 1)创建组件 let localTag = { template: ` <div class="ad"> <img src="img/mn.jpg" alt=""> <h4>美女</h4> </div> ` }; new Vue({ el: '#app', // 2)注册组件 components: { // ad: localTag, // localTag: localTag, localTag } }) </script> </html>
十.全局组件
1)创建组件: Vue.component
2)渲染组件: <global-tag></global-tag>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .ad { width: 200px; padding: 5px; margin: 5px; box-shadow: 0 0 5px 0 gold; float: left; } .ad img { width: 100%; } .ad h4 { margin: 0; font: normal 20px/30px '微软雅黑'; text-align: center; } </style> </head> <body> <div id="app"> <local-tag></local-tag> <global-tag></global-tag> </div> <div id="main"> <local-tag></local-tag> <global-tag></global-tag> </div> </body> <script src="js/vue.js"></script> <script> // 局部组件 // 1)创建组件 // 2)注册组件 // 3)渲染组件 let localTag = { template: ` <div class="ad"> <img src="img/mn.jpg" alt=""> <h4>美女</h4> </div> ` }; // 全局组件 // 1)创建组件 // 2)渲染组件 Vue.component('global-tag', { template: ` <div class="ad"> <img src="img/mn.jpg" alt=""> <h4>共享美女</h4> </div> ` }); new Vue({ el: '#app', components: { localTag } }); new Vue({ el: '#main', components: { localTag } }); </script> </html>
十一.组件复用的数据隔离
在子组件中写templates模板,data以函数的形式书写,返回的是一个字典, 有自己的作用域,每个子组件的数据都是隔离的,而调用的方法是公用的
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .ad { width: 200px; padding: 5px; margin: 5px; box-shadow: 0 0 5px 0 gold; float: left; } .ad img { width: 100%; } .ad h4 { margin: 0; font: normal 20px/30px '微软雅黑'; text-align: center; } </style> </head> <body> <div id="app"> <local-tag></local-tag> <global-tag></global-tag> </div> <div id="main"> <local-tag></local-tag> <global-tag></global-tag> </div> </body> <script src="js/vue.js"></script> <script> // 局部组件 // 1)创建组件 // 2)注册组件 // 3)渲染组件 let localTag = { template: ` <div @click="click1" class="ad"> <img src="img/mn.jpg" alt=""> <h4>美女被点了{{ num }}下</h4> </div> `, // 除了根组件,数据都是函数的返回值字典 data () { return { num: 0 } }, methods: { click1() { this.num ++ } }, }; // 全局组件 // 1)创建组件 // 2)渲染组件 Vue.component('global-tag', { template: ` <div class="ad" @click="click2"> <img src="img/mn.jpg" alt=""> <h4>共享{{ count }}次美女</h4> </div> `, data() { return { count: 0 } }, methods: { click2() { this.count ++ } } }); new Vue({ el: '#app', components: { localTag } }); new Vue({ el: '#main', components: { localTag } }); </script> </html>
十二.组件信息交互父传子
分析数据 父传子
1)父组件提供数据
2)在父组件模板中,为子组件标签设置自定义属性绑定父级数据
3)在子组件props成员中,接收自定义属性
4)在子组件模板和方法中,使用自定义属性名就可以访问父级数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .ad { width: 200px; padding: 5px; margin: 5px; box-shadow: 0 0 5px 0 gold; float: left; } .ad img { width: 100%; } .ad h4 { margin: 0; font: normal 20px/30px '微软雅黑'; text-align: center; } </style> </head> <body> <div id="app"> <local-tag :ad_dic="ad" v-for="ad in ads" :key="ad.img"></local-tag> </div> </body> <script src="js/vue.js"></script> <script> let localTag = { props: ['ad_dic'], template: ` <div class="ad"> <img :src="ad_dic.img" alt=""> <h4>{{ ad_dic.title }}</h4> </div> `, }; // 模拟后台的数据 let ads = [ { 'img': 'img/001.png', 'title': '小猫' }, { 'img': 'img/002.png', 'title': '黄蛋' }, { 'img': 'img/003.png', 'title': '蓝蛋' }, { 'img': 'img/004.png', 'title': '短腿' }, ]; new Vue({ el: '#app', data: { ads, // 后期项目是后台返回的数据 }, components: { localTag } }) // 分析数据 父传子 // 1)父组件提供数据 // 2)在父组件模板中,为子组件标签设置自定义属性绑定父级数据 // 3)在子组件props成员中,接收自定义属性 // 4)在子组件模板和方法中,使用自定义属性名就可以访问父级数据 </script> </html>
十三.组件信息交互子传父
分析数据 父传子
1)父组件提供数据 : info为空数组或缓存数组
2)在父组件模板中,为子组件标签设置自定义属性绑定父级数据
3)在子组件props成员中,接收自定义属性: props: ['msg', 'index'],
4)在子组件模板和方法中,使用自定义属性名就可以访问父级数据
分析数据 子传父 1)子组件提供数据 this.index可从父级拿 2)子组件通过系统事件激活自己的绑定方法,发送一个自定义事件,携带自身数据: 子组件模板中@click="del_fn"
子组件方法中 this.$emit('del_action', this.index)
3)在父组件模板中的子组件标签中为自定义事件绑定父组件方法:
@del_action="del_li"
4)父组件实现方法获取到子组件数据
del_li(index)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> body { font-size: 30px; } li:hover { color: orange; cursor: pointer; } .del:hover { color: red; } </style> </head> <body> <div id="app"> <p> <input type="text" v-model="info"> <button @click="add_msg">留言</button> <ul> <msg-tag @del_action="del_li" :msg="msg" :index="i" v-for="(msg, i) in msgs" :key="msg"></msg-tag> </ul> </p> </div> </body> <script src="js/vue.js"></script> <script> let msgTag = { props: ['msg', 'index'], template: ` <li> <span @click="del_fn" class="del">x</span> <span>{{ msg }}</span> </li> `, methods: { del_fn() { this.$emit('del_action', this.index) } } }; new Vue({ el: '#app', components: { msgTag }, data: { info: '', msgs: JSON.parse(sessionStorage.msgs || '[]'), }, methods: { add_msg() { let info = this.info; if (info) { this.msgs.unshift(this.info); this.info = ''; sessionStorage.msgs = JSON.stringify(this.msgs); } }, del_li(index) { console.log(index); this.msgs.splice(index, 1); sessionStorage.msgs = JSON.stringify(this.msgs); } } }); // 分析数据 子传父 // 1)子组件提供数据 // 2)子组件通过系统事件激活自己的绑定方法,发送一个自定义事件,携带自身数据 // 3)在父组件模板中的子组件标签中为自定义事件绑定父组件方法 // 4)父组件实现方法获取到子组件数据 </script> </html>