1. 调试没有 vm.$data问题
假设定义 vue 对象 如下。
var vm = Vue.createApp({
data() {
return {
price: 10,
};
},
template: ` 价格:<input type="number" v-model="price" />`,
}).mount("#app")
vue 运行后调试的话原本可以通过 vm.$加对应项查看变量。如图
![image-20211226182226019](https://i-blog.csdnimg.cn/blog_migrate/06180903ffd46320d14a1670524009cf.png)
但某次我的就莫名其妙没有了。 变成这样
![image-20211226182340471](https://i-blog.csdnimg.cn/blog_migrate/89bf7e8eb1adfdb0f48b9e2fc148a220.png)
原因如下,定义的时候如果是上边代码的形式,是可以查看的。但是,如果是先声明后绑定的话。就没法查看了。
不能查看的初始化例子如下:
var vm = Vue.createApp({
data() {
return {
price: 10,
};
},
template: ` 价格:<input type="number" v-model="price" />`,
});
vm.mount("#app")
可以查看的初始化例子 如下
<div>
</div>
<script>
var vm = Vue.createApp({
data() {
return {
price: 10,
};
},
template: ` 价格:<input type="number" v-model="price" />`,
}).mount("#app")
</script>
或者先创建变量,然后在另外赋值绑定。
代码如下。
<div id="app">
</div>
<script>
const vv = Vue.createApp({
data() {
return {
list: ["1532", "8465321"],
term: '',
}
},
methods: {
newValue() {
this.list.push(this.term);
}
},
template: `
<input v-model="term" />
<!-- 添加一个数据 -->
<button v-on:click="newValue"> 添加 </button>
<ul> <!-- 显示添加后的数据 -->
<my-li
v-for="(item,index) of list"
v-bind:liItem="item"
v-bind:liIndex="index"/>
</ul>
`,
});
//添加一个组件
vv.component("my-li", {
props: ['liItem', 'liIndex'],
template: `<li>第{{liIndex}}号姐姐:{{liItem}}</li>`
});
const vm=vv.mount("#app")
//在赋值绑定,查看时用 vm 查看
</script>
2.计算属性与侦听器
两种都可检测data里数值的变化。然后做出一些反应。
区别:
区别项 | computed | watch |
---|---|---|
页面渲染时是否执行 | yes | no |
局限 | 必须返回一个东西 | 必须侦听某一变量 |
执行时期 | 页面渲染到此属性时 | 侦听值发生变化时 |
3. v-if & v-show
3.1 v-if
渲染时通过变量或者表达式判断是否渲染绑定的标签或模块。
当值发生变化后,重新渲染某一模块。
3.2 v-show
通过一个bool变量或表达式决定一个标签或者模块的是否显示。
当bool变量或者表达式的值发生变化后,改变 display 使其显示。
区别 | v-if | v-show |
---|---|---|
HTML 中是否存在 | 不存在 | dislay:none隐藏 |
渲染时间 | 指定判别式或变量为true时 | 第一次页面渲染时 |
4. 计算属性添加参数
原来计算属性格式为
computed:{
getValue(){
return value;
}
}
如果在getValue
的括号里添加参数是会报错的。
可以结合计算属性的表面原理来改变下(真实原理还没理解)。
计算属性就是返回一个值。这个返回逻辑我们不知道怎么修改,可以对这个返回的值做手脚,比如我们再给他写一个函数,让它返回到这个函数里边继续去执行就行了。
格式如下。
computed: {
getClass() {
return (xy)=> {
//加上你的逻辑
return newValue
};
},
},
当然,箭头函数也可以换成别的function
,或者已经定义的函数。
引用时如下
<div :class="getClass(x)" id="bpp"></div><!--x为变量或值-->
5.组件定义的方法
5.1 向vue对象中添加
步骤:先初始化vue
对象,然后向这个对象中添加组件。
示例代码如下:
<div id="app"></div>
<script>
const pp = Vue.createApp({
template: `<sb />`,
});
pp.component("sb", {
template: `<h2>here are a sb!</h2>`,
});
const vm = pp.mount("#app");
</script>
最后重新定义
vm
的原因是方便调试。可以参考本文 1 中内容。不需要的话可直接在app
的最后进行mount()
5.2 vue对象引入
这种方法需要先定义组件,然后在初始化vue
对象时引入这些组件。
示例代码如下:
<div id="app"></div>
<script>
const sb = {
template: `<h2>here are a sb!</h2>`,
};
const pp = Vue.createApp({
components: {
sb,
"s-p": sb,
},
template: `<sb /><s-p/>`,
}).mount("#app");
</script>
5.3初始化时定义
这种方法是在vue对象初始化时在其内部直接定义,不过,少的话还行,多的话代码就臃肿了。
示例代码如下:
<div id="app"></div>
<script>
const pp = Vue.createApp({
components: {
sb:{
template: `<h2>here are a sb!</h2>`,
},
},
template: `<sb />`,
}).mount("#app");
</script>
6. 组件间传值问题
父组件可通过属性,参数,传递数据给子组件。也可以通过路由等(我还不会)。
子组件可以选择接受,或拒收。
6.1 接收
6.1.1 参数传值
父组件调用子组件,可直接在标签内声明属性,并赋值,也可通过参数向子组件传递参数。
-
通过参数接收。
<div id="app"></div> <script> const app=Vue.createApp({ template: ` <child message="what's a good day!"></child> ` }) app.component("child",{ props:["message"], methods: { conL(){ console.log(this.message); } }, template: ` <h2 @click="conL">{{message}}</h2> ` }).mount("#app") </script>
通过参数传来的值,是无法进行修改的,如果想修改,只能进行备份。
子组件传递参数,或者修改父组件中的值可参考本文
9--emit
的内容。如下:
<div id="app"></div> <script> app.component("clickAdd_2", { props: ["counter_son"], data() { return { here_counter:this.counter_son, } }, template: ` <h2>双向奔赴</h2> <h2>{{here_counter}}</h2> <button @click="here_counter++">点我+1</button> `, }); </script>
6.1.2 属性传值
<div id="app"></div>
<script>
const app=Vue.createApp({
template:
`
<child message="what's a good day!" style="color:red"></child>
`
})
app.component("child",{
template:
`
<h2>{{this.$attrs.msg}}</h2>
`
}).mount("#app")
</script>
在这个例子中,style
会直接继承给 h2
,
如果子模板中有多个标签,且没有根元素,则style属性默认将没人继承。
如果子模板有多个并列标签,可通过以下方式进行获取。
<div id="app"></div> <script> const app = Vue.createApp({ template: ` <child message="what's a good day!" style="color:red"></child> `, }); app.component("child", { template: ` <h2 :style="$attrs.style">4865313</h2> <h2 :style="$attrs.style">{{$attrs.message}}</h2> <h2>{{$attrs.message}}</h2> `, }).mount("#app");
6.1.3 子组件拒收
可在模板定义时指定inheritAttrs
属性为false
。
<div id="app"></div>
<script>
const app = Vue.createApp({
template: `
<child message="what's a good day!" style="color:red"></child>
`,
});
app
.component("child", {
inheritAttrs: false,
template: `
<div>
<h2>4865313</h2>
<h2>{{$attrs.message}}</h2>
<h2>{{$attrs.message}}</h2>
</div>
`,
})
.mount("#app");
</script>
此时 子模块 div
将不继承style属性。如果inherittAttrs
为true
,则将继承(此属性默认为true
)。
但是又会发现,下边的message
属性仍然显示了,所以这个值得改变并不能影响这种方法的获取,即子模版不能嘴上说不要,身体又很诚实
。
7. vue 样式绑定的方法
7.1 一般方法
声明模板时给标签添加id
或者样式类等信息,然后在css
文件或者style
标签中写样式。
<div id="app"></div>
<script>
const app = Vue.createApp({
data() {
return {
myStyle: "color:red;text-decoration:line-through",
};
},
template:
`
<div :style="myStyle">这怎么还有一个BUG</div>
`,
}).mount("#app");
</script>
7.2 data中写style
在vue
的data
属性中声明一个style
变量并赋值然后将此变量用v-model
绑定至标签上。
代码如下:
<div id="app"></div>
<script>
const app = Vue.createApp({
data() {
return {
myStyle: "color:red;text-decoration:line-through",
};
},
template:
`
<div :style="myStyle">asdsadsad</div>
`,
}).mount("#app");
</script>
7.3 在data中把样式类定义为变量。
这种也需要在css
文件或者style
标签中已经写好样式类。
用v-model
将值绑定至属性上。
<div id="app"></div>
<script>
const app = Vue.createApp({
data() {
return {
myClassRed:"red",
myClassGreen:"green",
};
},
template:
`
<div :class="myClassRed">asdsadsad</div>
`,
}).mount("#app");
</script>
7.4 样式类对象
同样需要先写样式。
7.4.1 true & false
在data
中把需要的样式写为一个对象,然后根据需要设置true
与false
。
<div id="app"></div>
<script>
const app = Vue.createApp({
data() {
return {
css: {
transition: true,
red: true,
green: false,
},
};
},
methods: {
switch_bt() {
this.css.red = this.css.green;
this.css.green = !this.css.red;
},
},
template: `
<span :class="css">everything is ok</span><br>
<button @click="switch_bt">switch</button>
`,
}).mount("#app");
</script>
渲染时,会先对对象中的值判断,为true时才会加入到classlist
中。
7.4.2 指定值
与7.2类似,只不过看着更直观,同样也是写成一个对象。
<div id="app"></div>
<script>
const app = Vue.createApp({
data() {
return {
myStyle:{
color:"red",
"text-decoration":"line-through"
},
};
},
template:
`
<div :style="myStyle">asdsadsad</div>
`,
}).mount("#app");
</script>
注意:如果某一个属性有横线,则必须用引号引起来,没有横线的话引号可以省略。
8. 事件修饰符
self
;prevent
;capture
;once
self
:点标签自己有用,子标签没用,
prevent
:清除默认事件,如form的提交。
catpure
:使事件从父标签至字标签执行。(默认顺序为从内到外)。
once
:只执行一次。
。。。等
官方地址:传送门
9. emit
第一次学真的有点懵,不过敲完代码,跑出来效果后,理解的就多了点。
先说下原理,与props
传参类似。只不过,props
传的是父组件的值,而emit是传递的函数。
产生这个组件时把父组件的某一个函数指定给它,而它就是通过emits属性接受的,同props接受数值一样。之后子函数就可以调用父组件的这个函数了。
之所以说是调用,是因为,如果你在父组件函数中使用父组件data的值,那么,子组件调用仍然可以正常使用。
然后看一个代码实例:
<div id="app"></div>
<script>
const app = Vue.createApp({
data() {
return {
counter: "I have nothing!",
}
},
methods: {
clickAdd(st){
console.log(st);
this.counter+=st;
}
},
template:
`
父数据<a>{{counter}}</a><br>
<button @click="clickAdd('father_Click')">老父亲的点击</button><br>
子数据<child @emitAdd="clickAdd" :cou="counter"></child>
`
})
app.component("child",{
props:["cou","Add"],
emits:["emitAdd"],
data() {
return {counter:this.cou}
},
methods: {
sonToFather(value){
console.log(value);
this.$emit("emitAdd",value)
}
},
template:
`
<div>
接受的:<a>{{cou}}</a><br>
<button @click='sonToFather("son_Click")'>来自子组件的点击</button>
</div>
`
})
const vm=app.mount('#app');
</script>
在这段代码中父组件声明一个child
标签,然后传给他counter
,clickAdd
,child
分别使用props
、emits
接收。
在父组件中,clickAdd
函数是默认把counter
字符串加father_Click
。但定义的函数是将一个参数加在counter
后边,所以在子组件中,我们就可以传入这个参数。
就是在子组件中在声明一个函数——sonToFather
。在这个函数体内就可以调用传入的函数——clickAdd
,并指定传入这个函数的参数。这样子组件执行sonToFather
就等效是父组件的这个函数了。
以此实现子组件对父组件值得修改。
10. slot
-
slot
插槽一般写法。 插槽,在子模板中声明一个位置,然后填充父组件传入的数据(字符串、对象、
html
代码等)。当子模板slot中有数据等东西时,是默认值,即当父组件啥都没传入时才会显示。 当子模板有多个插槽时,需要声明
slot
的name
属性,然后在父组件使用时指定值。格式如第一个代码块第7、10行。第二种为省略写法。 但是当使用的是第二个代码块的方法时,必须带上
default=
,如第二个代码块第12行。 当父组件中出现多个插槽的使用时,需要使用
template
标签。然后在template
标签内指定name
。示例代码如下。
<div id="app"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<person>
<template v-slot:first>
<div>第二首歌:好好过 - 胡歌</div>
</template>
<template #second>
<div>第二首歌:一念执着 - 胡歌/阿兰</div>
</template>
</person>
</div>
`,
});
app.component("person", {
template: `
<slot name="first">
<div>第一首歌:我们的纪念 - 李雅微</div>
</slot>
<slot name="second">
<div>第二首歌:父亲 - 筷子兄弟</div>
</slot>
<slot name="third">
<div>第三首歌:Letting GO - 蔡健雅</div>
</slot>
`,
});
const vm = app.mount("#app");
</script>
-
slot简写
这种简写算是都没有声明
name
的情况。这里第一次使用时用到了一个知识点对象解构赋值,其作用是将子组件传来的对象还是啥都变成值。同时,也可以设定默认值如下代码块第6行。
如果不解构,name输出的可能是个类。当然加
.valueName
也行。(valueName为类中项的名称)代码如下:
<div id="app"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<person v-slot="{song:item='未收录'}">
<div>{{item}}</div>
</person>
</div>
还可以缩写呦!<br>
<div>
<person #default="{song:item='未收录'}">
<div>{{item}}</div>
</person>
</div>
`,
});
app.component("person", {
data() {
return {
songs: [
"第一首歌:我们的纪念 - 李雅微",
"第二首歌:父亲 - 筷子兄弟",
"第三首歌:Letting GO - 蔡健雅",
undefined
],
}
},
template: `
<div>
<slot v-for="song in songs" :song="song" />
</div>
`,
});
const vm = app.mount("#app");
</script>