vue基础二,组件

vue二:
指令:
1,v-once指令:
v-once:单独使用,限制的标签内容一旦赋值,便不可被动更改(如果是输入框,可以主动修改)

<div id="app">
<input type="text" v-model="msg">
<!-- 一旦赋值,只可主动更改 -->
<input type="text" v-model="msg" v-once>
<p>{{ msg }}</p>
<!-- 一旦赋值,便不可更改 -->
<p v-once>{{ msg }}</p>
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: '初始值'
}
})
</script>

2,v-cloak:斗篷指令(了解)
v-cloak:防止页面闪烁

<style>
[v-cloak] {
display: none;
}
</style>
<!-- 不处理的情况下,每次新价值该页面,都会先渲染{{}},当vue环境加载成功,{{}}有会被解析消失 -->
<!-- 处理后,vue环境没加载好时,#app是被隐藏的,vue环境加载成功,会依次#app的v-cloak属性,就不会出现{{}}渲染闪烁问题 -->
<div id="app" v-cloak>
{{ }}
{{ }}
{{ }}
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
})
</script>

3,条件指令
v-if v-show
1,两种都可以控制标签的显隐,绑定的值是布尔值类型,但是在都隐藏标签时
v-if是不会渲染标签,在前端就无法看到此标签的数据,所以比较安全
v-show以display:none方式渲染,不显示,但是渲染了标签,隐藏了

<div id="app">
<p v-if="isShow">if条件指令</p>
<p v-show="isShow">show条件指令</p>
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
isShow: false,
}
})
</script>

2) v-if="变量"
v-else-if="变量"
v-else
一组分支,上成立分支会屏蔽下方所有分支,else分支没有条件,在所有分支不成立后才显示
即只要if成立就不会走else-if,从上到下都不成立才会走else

案例:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
400px;
height: 200px;
}
.r {background-color: red;}
.y {background-color: yellow;}
.b {background-color: green;}
.active{
background-color: orangered;
}

</style>

</head>
<body>
<!--<div id="app">-->
<!--<div v-if="isoif">if条件指令</div>-->
<!--<div v-show="isShow">show条件指令</div>-->
<!--</div>-->
<div id="app">
<div class="em">
<p>
<!-- :class="{active:showName=='rbox' }" 在这里active是true就会渲染此标签,为false不会渲染-->
<!--xxx是类名,是否起作用有布尔类型变量yyy值决定 -->
<!--<p :class="{xxx:yyy}">样式绑定5</p>-->
<button @click="changeBox('rbox')" :class="{active:showName=='rbox' }">红</button>
<button @click="changeBox('ybox')" :class="{active:showName=='ybox'}">黄</button>
<button @click="changeBox('bbox')" :class="{active:showName=='bbox'}">绿</button>
</p>
<p>
<!-- :class="showName=='rbox' ? 'active':'' 三元表达式,条件成立执行冒号前面的,不成立就执行冒号后面的-->
<button @click="changeBox('rbox')" :class="showName=='rbox' ? 'active':'' ">红</button>
<button @click="changeBox('ybox')" :class="showName=='ybox'? 'active':'' ">黄</button>
<button @click="changeBox('bbox')" :class="showName=='bbox'? 'active':'' ">绿</button>
</p>
<!-- v-if在遇到下一个v-if就会自动结束,即它自己就是一个分支-->
<div class="box r" v-if="showName=='rbox'"></div>
<div class="box y" v-else-if="showName=='ybox'"></div>
<div class="box b" v-else=""></div>
</div>
</div>
</body>
<script src="https://cn.vuejs.org/js/vue.min.js"></script>
<script>
new Vue({
el:'#app',
data:{
showName:'rbox'//属性绑定
},

methods:{ //方法判定用methods,在这里事件绑定,用冒号绑定
changeBox(name){
this.showName = name;
}
}
})
</script>
</html>
4,v-pre指令(了解)
v-pre指令可以在vue控制范围内,形成局部vue不控制区域(局部不解析vue语法)

<div id="app">
<p>{{ msg }}</p>
<!-- v-pre 指令可以在vue控制范围内,形成局部vue不控制区域
{{ }} 和 v-if 都会原样输出,不会被解析
-->
<p v-pre>
{{ }}
<span v-if="hehe"></span>
</p>
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'message'
}
})
</script>


5,v-for 循环指令
1) 遍历字符串:可以只逐一遍历字符,也可以连同遍历索引
<p v-for="ch in str"></p> | <p v-for="(ch, index) in str"></p>

2) 遍历数组:可以只逐一遍历成员元素,也可以连同遍历索引
<p v-for="ele in arr"></p> | <p v-for="(ele, index) in arr"></p>

3) 遍历对象:可以只逐一遍历成员元素,也可以连同遍历成员键(key),还可以遍历成员key索引
<p v-for="v in dic"></p> | <p v-for="(v,k) in arr"></p> | <p v-for="(v,k,i) in arr"></p>

案列:
<div id="app">
<p>{{ str }}</p>
<p>{{ str[0] }}</p>
<div>
<span v-for="ch in str">{{ ch }}</span>
</div>
<div>
<!--针对循环遍历的标签,通过会提供key属性来优化渲染速度,但key的值必须唯一(key可以不用提供) -->
<span v-for="(ch, i) in str" :key="ch + i">{{ i }}{{ ch }}</span>
</div>


<div>
<p v-for="(ele, i) in arr">{{ i }}{{ ele }}</p>
</div>


<div>
<p v-for="ele in dic">{{ ele }}</p>
</div>

<div>
<p v-for="(ele, k) in dic">{{ k }}:{{ ele }}</p>
</div>

<div>
<p v-for="(ele, k, i) in dic">{{ i }}{{ k }}:{{ ele }}</p>
</div>

</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
str: 'abc123呵呵',
arr: [3, 4, 1, 2, 5],
dic: {
name: 'Tank',
age: 80,
gender: '哇塞',
}
}
})
</script>

6,todolist留言板案例

1) 留言就是往留言数组中添加数据,删除留言就是从留言数组中移除数据

2) 前台数据库:localStorage 和 sessionStorage
localStorage永久保存数据
sessionStorage临时保存数据(当所属页面标签被关闭,数据被清空)

3) 前台localStorage 和 sessionStorage数据库存储的值是字符串类型,所以要存放arr、dic等复杂数据需要JSON参与

案列:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
<style>
li:hover {
color: red;
cursor: pointer;
}
</style>
</head>
<body>
<div id="app">
<p>
<input type="text" v-model="userMsg">
<button type="button" @click="sendMsg">留言</button>
</p>
<ul>
<li v-for="(msg, index) in msgs" @click="deleteMsg(index)">
{{ msg }}
</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msgs: localStorage.msgs ? JSON.parse(localStorage.msgs) : [], // 所有留言
userMsg: '', // 用户留言
},
methods: {
sendMsg() { // 留言事件
// 尾增
// this.msgs.push(this.userMsg);
// 首增
// this.msgs.unshift(this.userMsg);

// 增加完成后数据要做清空处理,即文本框中不在有内容操作如下
let userMsg = this.userMsg;
if (userMsg) {
this.msgs.unshift(userMsg); // 渲染给页面
localStorage.msgs = JSON.stringify(this.msgs); // 同步到数据库
this.userMsg = ''; // 清空留言框
}
},
deleteMsg(index) {
// 开始索引 操作长度 操作的结果们
//即括号中的第一个参数是开始索引,第二个参数是操作长度,第三个参数是结果,即在页面上对应索引你想要的显示的结果
this.msgs.splice(index, 1)
}
}
})
</script>

<script>
// localStorage['num'] = 10;
// sessionStorage.num = 888;
// console.log(localStorage.num);

// localStorage.msgs = JSON.stringify(['1111', '2222']);
// console.log(JSON.parse(localStorage.msgs));
// console.log(JSON.parse(localStorage.msgs)[0]);
</script>
</html>

7,实例成员 - 插值表达式符号(了解)
<div id="app">
{{ msg }}
{[ msg ]}
</div>
<script>
new Vue({
el: '#app',
data: {
msg: '12345'
},
// delimiters: ['{{', '}}'],
delimiters: ['{[', ']}'],
})
</script>

8,计算属性
1) computed是用来声明 方法属性 的
2) 声明的方法属性不能在data中重复定义
3) 方法属性必须在页面中渲染使用,才会对内部出现的所有变量进行监听
4) 计算属性的值来源于监听方法的返回值

<div id="app">
姓:<input type="text" v-model="fName">
名:<input type="text" v-model="lName">
姓名:<b>{{ flName }}</b>
</div>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
fName: '',
lName: '',
},
computed: {
flName(){
// this.fName和this.lName有值发送改变,该方法都会被调用
// 变量flName的值是由函数的返回值决定
return this.fName + this.lName;
}
}
})
</script>

案列:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>

</head>
<body>
<div id="app">
<p @click="fn">{{num}}</p>
<!--<p>十位:{{num / 10}} 除</p>-->
<!--<p>各位:{{num % 10}} 取余</p>-->
<!-- parseInt()为取整数 parseFloat为浮点型-->
<p>十位:{{parseInt(num / 10)}}</p>
<p>各位:{{num % 10}}</p>
十位:<input type="text" v-model="shi">
各位:<input type="text" v-model="ge">
<b>结果:{{shi*10 + +ge}}</b>
<b>结果:{{result}}</b>

</div>
<!--反过来 填个十位,填个各位,最后结果为十位数-->
</body>
<script src="https://cn.vuejs.org/js/vue.min.js"></script>
<script>
new Vue({
el:'#app',
data:{
num:100,
shi:0,
ge:0,
//result:0,
},
methods:{
fn(){
this.num -=2;
}
},
//1), computed是用来声明 方法属性 的
//2), 声明的方法属性不能在data中重复定义
//3) 方法属性必须在页面中渲染使用,才会对内部出现的所有变量进行监听 *****
//4) 计算属性的值来源于监听方法的返回值
computed:{
result(){ //result这个变量的值来源于所有被监听的变量,即shi和ge
return this.shi*10 + +this.ge
} //这就体现了监听机制
}
})
</script>
</html>

9,组件:

1) 组件:一个包含html、css、js独立的集合体,这样的集合体可以完成页面解构的代码复用
2) 分组分为根组件、全局组件与局部组件
根组件:所有被new Vue()产生的组件,在项目开发阶段,一个项目只会出现一个根组件
全局组件:不用注册,就可以成为任何一个组件的子组件
局部组件:必须注册,才可以成为注册该局部组件的子组件
3) 每一个组件都有自身的html结构,css样式,js逻辑
每一个组件其实都有自己的template,就是用来标识自己html结构的
template模板中有且只有一个根标签
根组件一般不提供template,就由挂载点的真实DOM提供html结构
4) 除根组件的其他组件,数据要有局部作用域,保证组件复用时,各组件间数据的独立性
5) 在多组件共处时,在哪个组件模板中出现的变量,有当前组件组件提供

<!-- template后是字符串,用引号,是html,css,js代码-->
1,局部组件:
1,创建局部组件
2,在父组件中注册该局部组件
3,在父组件的template模板中渲染该局部组件

案列:
<style>
.box {
box-shadow: 0 3px 5px 0 #666;
240px;
height: 300px;
text-align: center;
padding: 20px 0;
float: left;
margin: 5px;
}
.box img {
200px;
}
</style>
<div id="app">
<!--<mcc></mcc>-->
<!--在父组件的template模板中渲染该局部组件-->
<local-tag></local-tag>
<local-tag></local-tag>
</div>
<script src="js/vue.js"></script>
<script>
<!-- 创建局部组件localTag 大括号中关键字template-->
let localTag = {
template: `
<div class="box">
<img src="img/666.jpg" alt="">
<h3>凤哥</h3>
<p>马叉虫❤马叉虫</p>
</div>
`
};

new Vue({
el: '#app',
//2,在父组件中注册该局部组件,关键字components
components: {
// mcc: localTag,
// localTag,
'local-tag': localTag, <!--在父组件的template模板中渲染该局部组件-->
}
})
</script>

2,全局组件:
1,创建全局组件
2,在父组件的template模板中渲染该全局组件


<style>
.box {
box-shadow: 0 3px 5px 0 #666;
240px;
height: 300px;
text-align: center;
padding: 20px 0;
float: left;
margin: 5px;
}
.box img {
200px;
}
</style>
<div id="app">
<global-tag></global-tag>
<global-tag></global-tag>
<global-tag></global-tag>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component('global-tag', {
template: `
<div class="box" @click="action">
<img src="img/666.jpg" alt="">
<h3>凤哥</h3>
<p>马叉虫❤{{ num }}</p>
</div>
`,
data () {
return {
num: 0
}
},
methods: {
action() {
this.num++;
}
}
});

// 数据局部化分析导入
// a = function () {
// return {num: 10}
// };
// b1 = a();
// b2 = a();
// b3 = a();
// 这样处理b1,b2,b3的数据就彼此独立的,但是都来源于a

new Vue({
el: '#app',
})
</script>

3,组件交互-父传子
数据交互-父传子 - 通过绑定属性的方式
1,数据由父组件提供
2,在父组件模板中,为子组件标签设置自定义属性,绑定的值由父组件提供
3,在子组件实例中,通过props实例成员来获取自定义属性


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.info {
text-align: center;
180px;
padding: 3px;
box-shadow:0 3px 5px #666666 ;
margin: 5px;
float: left;
}
.info img{
180px;
}
</style>
</head>
<body>
<div id="app">
<info v-for="info in infos" :key="info.imags" :myinfo="info"></info>
</div>
</body>
<script src="https://cn.vuejs.org/js/vue.min.js"></script>
<script>
let infos = [{
imags:'img/222.jpg',
title:'长发',
},
{
imags:'img/333.jpg',
title:'独骚',
},
{
imags:'img/444.jpg',
title:'花花',
},
{
imags:'img/666.jpg',
title:'贝子',
},
{
imags:'img/432.jpg',
title:'松鼠',
},
];
let info = {
template: `
<div class="info">
<img :src="myinfo.imags" alt="">
<p><h3>{{myinfo.title}}</h3></p>
</div>
`,
props:['myinfo']
};
new Vue({
el:'#app',
components:{
info
},
data:{
infos
}
})
</script>
</html>

4,组件交互-子传父
// 组件交互-子传父
1) 数据由子组件提供
2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来
3) 父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数

<style>
.close:hover {
cursor: pointer;
color: red;
}
</style>
<div id="app">
<p>
<input type="text" v-model="userMsg">
<button @click="sendMsg">留言</button>
</p>
<ul>
<!-- 2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来 -->
<msg-li @remove_msg="removeAction" v-for="(msg, i) in msgs" :msg="msg" :index="i" :key="msg"></msg-li>
</ul>
</div>
<script src="js/vue.js"></script>
<script>
let msgLi = {
template: `
<li>
<span class="close" @click="deleteMsg(index)">x </span>
<span>第{{ index + 1 }}条:</span>
<span>{{ msg }}</span>
</li>
`,
props: ['msg', 'index'],
methods: {
// 系统的click事件
deleteMsg(i) {
// 1) 数据由子组件提供
// $emit('自定义事件名', 参数们)
this.$emit('remove_msg', i);
}
}
};
new Vue({
el: '#app',
data: {
msgs: [],
userMsg: ''
},
methods: {
sendMsg() {
if (this.userMsg) {
this.msgs.push(this.userMsg);
this.userMsg = "";
}
},
// 3) 父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数
removeAction(i) {
this.msgs.splice(i, 1)
}
},
components: {
msgLi
}
})
</script>
原文地址:https://www.cnblogs.com/Fzhiyuan/p/11650069.html