Vue - 组件
目录
Vue成员获取
获取自定义成员和methods时,用$options.成员
来获取,
<div id="app">
<h1 @click="btnClick">{{ msg }}</h1>
<p>{{$data}}</p>
<p>{{$options}}</p>
<p>{{$options.myarr}}</p>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
msg: '数据'
},
methods: {
btnClick() {
console.log(this.msg)
}
},
myarr: [1, 2, 3, 4]
});
console.log(app.msg);
console.log(app.$data);
console.log(app.$options.methods);
console.log(app.$options.myarr)
</script>
Vue原义指令
<div class="app">
<p v-pre>
<!--v-pre的内部解除vue控制,都是原义输出:插值表达式不是插值表达式,变量也不是变量,vue指令也只是普通的属性-->
{{msg}}
<span v-on="abc"></span>
</p>
</div>
<script>
new Vue({
el: '#app',
data: {
msg: 'msg'
}
})
</script>
Vue循环指令
<div id="app">
<!--列表-->
<p>{{arr}}</p>
<div>
<!--值遍历-->
<p v-for="v in arr">
<span>{{ v }}</span>
</p>
<!--值、索引遍历-->
<p v-for="(v,i) in arr">
<span>第{{ i+1 }}个值为:{{ v }}</span>
</p>
</div>
<!--字典-->
<p>{{ student }}</p>
<div>
<!--value遍历-->
<p v-for="v in student">
<span>{{ v }}</span>
</p>
<!--value、key遍历-->
<p v-for="(v,k) in student">
<span>{{ k }}:{{ v }}</span>
</p>
<!--value、key、索引遍历-->
<p v-for="(v,k,i) in student">
<span>{{ k }}:{{ v }}({{i}})</span>
</p>
</div>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
arr: [1, 2, 3, 4, 5],
student:{
'name':'Bob',
'age':18,
'gender':'男'
}
}
})
</script>
todolist案列
<style>
li:hover {
color: red;
cursor: pointer;
}
</style>
<div id="app">
<input type="text" v-model="info">
<button @click="addMsg">留言</button>
<ul>
<li v-for="(msg,i) in msgs" @click="delMsg(i)">{{msg}}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
info: '',
msgs: JSON.parse(sessionStorage.msgs || '[]'),
},
methods: {
addMsg() {
if (this.info) {
this.msgs.unshift(this.info);
this.info = ''
sessionStorage.msgs = JSON.stringify(this.msgs); // sessionStorage中不能直接存列表,需要先转成JSON字符串存入,在取得时候再解析回列表
}
},
delMsg(i) {
this.msgs.splice(i, 1)
sessionStorage.msgs = JSON.stringify(this.msgs);
}
}
})
</script>
Vue分隔符
<div id="app">{{msg}}</div>
<script>
new Vue({
el:'#app',
data:{
msg:'message'
},
// 修改插值表达式符号.在Django中的模块渲染中也是用的{{ }}。这样导致在取变量时有冲突,所以可以用delimiters来修改插值表达式符号
delimiters:['[[','}}'],
})
</script>
Vue计算属性成员
<div id="app">
<input type="text" v-model="a">
<input type="text" v-model="b">
<span>{{xyz}}</span>
</div>
<script>
new Vue({
el:'#app',
data:{
a:'',
b:''
},
// 1)计算后属性不需要再data中重复定义
// 2)计算后属性必须渲染后,绑定的方法才会生效
// 3)计算后属性绑定的方法中的任意变量值更新,方法都会被调用
// 4)计算后属性为只读属性(不可写)
computed:{
xyz(){
this.a;
this.b;
console.log('我被调用了')
}
},
// 应用场景:一个计算后属性的值,可以来源于多个属性值
})
</script>
Vue监听属性
<div id="app">
<input type="text" v-model="num_a">
<p>num_b:{{num_b}}</p>
<p>num_c:{{num_c}}</p>
</div>
<script>
// 1)监听绑定的属性,该属性可以get、set
// 2)监听的属性一旦发生值更新,绑定的方法就会被调用
// 3)监听的属性是已定义的属性(必须在data中定义)
new Vue({
el:'#app',
data:{
num_a:'',
num_b:'',
num_c:'',
},
watch:{
// 很多变量依赖同一个变量值,给这个变量设监听函数来处理这些变量
num_a(){
console.log('num_a更新时,我被调用了')
this.num_b = this.num_a*10;
this.num_c = this.num_a*20
}
},
})
</script>
Vue组件
组件:由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只能解析一个根标签,根标签里可以有多个标签
<div id="app">
<div>
{{msg}}
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
msg: 'message'
},
template: `
<div class="main">
<p>{{msg}}</p>
<p>{{msg}}</p>
</div>
`
})
</script>
局部组件
// 1) 创建组件
// 2) 注册组件
// 3) 渲染组件
<style>
.ad {
width: 200px;
margin: 5px;
padding: 5px;
box-shadow: 0 0 5px 0 gold;
float: left;
}
.ad img {
width: 100%;
}
.ad h4 {
text-align: center;
font: normal 20px/30px '微软雅黑';
}
</style>
<div id="app">
<!-- 3) 渲染组件 -->
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
</div>
<script>
// 1) 创建局部组件
let localTag = {
template: `
<div class="ad">
<img src="img/dog.jpg" alt="">
<h4>可爱柯基</h4>
</div>
`
};
new Vue({
el: '#app',
// 2) 注册组件
components:{
// localTag:localTag
localTag
}
})
</script>
全局组件
// 1)创建组件
// 2)渲染组件
<div>
<div id="app">
<global-tag></global-tag>
</div>
<div id="main">
<global-tag></global-tag>
</div>
</div>
<script>
// 创建全局组件
Vue.component('global-tag', {
template: `
<div class="ad">
<img src="img/dog.jpg" alt="">
<h4>可爱柯基</h4>
</div>
`
});
new Vue({el: '#app',});
new Vue({el: '#main',})
</script>
组件复用的数据隔离
<div>
<div id="app">
<global-tag></global-tag>
<local-tag></local-tag>
</div>
<div id="main">
<global-tag></global-tag>
<local-tag></local-tag>
</div>
</div>
<script>
let localTag = {
template: `
<div class="ad" @click="click1">
<img src="img/dog.jpg" alt="">
<h4>局部组件柯基点{{num}}次</h4>
</div>
`,
data() {
return {num: 0,}
},
methods: {
click1() {this.num++}
}
};
Vue.component('global-tag', {
template: `
<div class="ad" @click="click2">
<img src="img/dog.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>
组件信息交互 - 父传子
<div>
<div id="app">
<local-tag :my_dic="ad" v-for="ad in ads" :key="ad.title"></local-tag>
</div>
</div>
<script>
let localTag = {
props:['my_dic',],
template: `
<div class="ad">
<img :src="my_dic.img" alt="">
<h4>{{my_dic.title}}</h4>
</div>
`
};
let ads = [
{
img:'img/dog.jpg',
title:'柯基1'
},
{
img:'img/dog.jpg',
title:'柯基2'
},
{
img:'img/dog.jpg',
title:'柯基3'
},
];
new Vue({
el: '#app',
components:{localTag,},
data:{
ads:ads,
}
})
// 1)父级提供数据
// 2)在父级模板中,为子组件标签设置自定义属性绑定父级数据
// 3)在子级props成员中,接收自定义属性
// 4)在子组件模板和方法中,使用自定义属性名就可以访问父级数据
</script>
组件信息交互 - 子传父
<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>
<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>