Vue基礎知識整理
vue實例方法:
<div id="root">
{{num}}
<my-components></my-components>
</div>
<template id="tem">
<div>
<p>這是組件</p>
</div>
</template>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
const app = new Vue({
el: "#root",
data: {
num: 123,
obj: {c: 666}
},
components: {
"my-components": {
template: "#tem"
}
}
})
</script>
-
app.$el
與app.$refs
都是獲取dom的節點,app.$el
是組件掛載的節點,而app.$refs.xxx
則是ref=xxx
的節點 -
app.$data
用於獲取data中的所有數據,如果要直接獲取數據可以通過app.$num
某個屬性即可 -
app.$children
獲取子組件 -
app.$root === app
相等獲取vue實例 -
app.$options
返回一個對象,裏面包含創建vue實例時傳入的參數以及默認的參數,所以可以通過app.$options.data().num
來獲取數據;app.$options.render = (h) => h("div", {}, "頁面上數據重新update時觸發"),例如加個定時器,那麼h函數就會執行並渲染頁面
-
const unWatch = app.$watch('xx', (n, o) => {})
,可用來監聽data中的數據變化,但是用app監聽是,watch
不會自動關閉,需要手動關閉,unWatch()
-
app.$on
與app.$emit
,用來定義事件以及觸發事件,在父組件emit子組件的on事件vm.$on('test', (a ,b) => { //vm.$once事件是代表只執行一次 console.log('test is emit') }) vm.$emit('test', 1, 2) //可以傳遞給a, b
-
app.$forceUpdate
與app.$set(app.obj, 'xx', 1)
可以用來渲染當data中的obj並沒🈶定義a時,但在html中我們有寫入了a,原來a是不會被渲染出來的,但是這兩條語句都能使得a渲染出來;起到了類似強制刷新的作用 -
app.$nextTick(function() {})
:常用來獲取dom更新後的數據,因爲dom更新數據時異步的,有時候並不能及時獲取到,則可用這麼方法;也可當做promise
使用Vue.nextTick() .then(function () { // DOM 更新了 })
vue的生命週期
- vue創建到掛載
beforeCreate () {
this.$on('test', (a, b) => {
console.log(a, b, '執行事件')
})
this.$emit('test', 1, 2)
//事件已完成,但dom與數據不能進行操作
},
created () {
console.log(this.msg)
this.msg = 888
console.log(this.msg)
//能操作data中的數據但不能操作dom
},
beforeMount () {
console.log(this.$refs.span, '還是不能操作獲取dom')
//b不能獲取dom
},
//這中間會執行render函數,進行虛擬dom的渲染
//接下來菜市mounted階段
mounted () {
console.log(this.$refs.span, 'mounted能進行dom的獲取與操作')
}
如果new Vue()時沒有進行el的指定則不會進行beforeMount與mounted
,我們可以手動vm.$mount("#app")
如果new Vue()時有template: '<div>888</div>',或者render (h) { h('div', {}, '888')}
都會對el:#app的dom進行整體覆蓋
- vue數據更新
beforeUpdate
與updated
當數據發生變化時會執行這兩個鉤子函數,但是一般可以通過watch與
Computed`進行監聽數據變化,執行相應操作,
官方提到:
注意 updated 不會承諾所有的子組件也都一起被重繪。如果你希望等到整個視圖都重繪完畢,可以用 vm.$nextTick 替換掉 updated:
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}
- vue卸載
vm.$destroy()
螚手動觸發beforeDestroy
與destroyed
;卸載不是消除頁面上的dom,而是解除任何綁定
vue-data
-
data中存放着組件或者vue實例的數據;但是在
new Vue()
時,data則可以直接
寫成一個對象,而在組件中時data必須爲一個方法,並且return
一個對象,這是爲什麼呢?
就是必須返回一個獨立的對象,防止組件之間相互影響當組件中的data爲一個對象時:因爲組件時可複用的,父組件A中使用了子組件b,並且對b組件中data的值進行了改變,那麼當父組件c再次使用子組件b時也會使用被A改變了的data,這是不合理的,所以在組件中data必須爲一個`function`並且返回一個對象
vue-html
<div v-html="html"></div>
data: {
html: '<span>888</span>' //會解析html結構並append進去
}
vue-bind
綁定dom的一些attribute
<div v-bind:class="{active: isActive}"></div> //v-bind可省略
data: {
isActive: true
}
//或者
<div :class="classname"></div>
computed: {
classname () {
return {
active: !this.isActive
}
}
},
computed
,watch
,methods
淺談區別
-
computed
本質就是get
方法,通常用的就是get
方法去獲取數據,該數據不用放在data
中;直接放在computed
中,通過計算通過get
方式獲取數據,默認第一次渲染就能獲取到,而不用等到重新渲染在獲取;(監聽多個data數據來get
自己想要數據,不要出現無限循環
)通常形式如下computed: { xx () { return 'xxx' } }
-
watch
通常用於監聽data中的數據,有兩個參數(new, old)
來改變相應的數據,看起來是一對多,與computed
的多對一有區別;而且默認第一次渲染不刷新;可以手動handle
並且不要改自身監聽的屬性的值
watch: { xxx (new, old) { .... } } //默認第一次渲染不刷新
watch: { xxx: { handle (new, old) { ... } }, immediate: true, deep: true //深度監聽,例如監聽obj時其中的元素髮生變化,並不會監聽到,但是deep爲true時則會生效,這樣性能開銷會大 } //通過handle第一次渲染刷新
所以我們可以使用
字符串形式
,來指定監聽obj中的awatch: { 'xxx.a': { //監聽xxx對象中的a屬性 handle (new, old) { ... } }, immediate: true, } //通過handle第一次渲染刷新
-
methods
與computed
不同,所有數據變化都會執行methods
內的方法
vue原生指令
-
v-text
等價於textContent
,v-html
等價於`innerHTML -
v-show="bool"
就是是否display:none
;v-if
,v-else-if
,v-else
是動態增刪dom會消耗性能不推薦使用 v-for
<div id="app">
<ul>
<li v-for="(item, index) in arr" :key="item">{{item}}: {{index}}</li>
</ul>
<ul>
<li v-for="(value, key, index) in obj" :key="key">{{key}}: {{value}} - {{index}}</li>
</ul>
</div>
<script>
Vue.config.devtools = true
const vm = new Vue({
el: '#app',
data: {
msg: 123,
obj: {
'a': 12,
'b': 34
},
arr: [1, 2, 3, 4]
}
})
</script>
-
v-on
綁定事件,當綁定對象不是vue實例時,實際上是使用addEventListener
進行事件添加,若是實例對象則vm.$on()
v-model
<div id="app">
<!-- <comp-one :value="num" @input="num = arguments[0]"></comp-one> -->
<comp-one v-model="num"></comp-one>
<div>{{num}}</div>
</div>
<script>
Vue.config.devtools = true
const component = {
props: ['value'],
template: "<input type='text' :value='value' @input='handleInput'/>",
methods: {
handleInput(e) {
this.$emit('input', e.target.value)
}
}
}
Vue.component('CompOne', component)
const vm = new Vue({
el: '#app',
components: {
CompOne: component
},
data: {
num: 1
}
})
</script>
vue組件
- 創建
- 方法1:全局創建一個組件
const component = {
template: '<span>{{text}}</span>',
data () {
return {
text: 123456
}
}
}
Vue.component('CompOne', component)
const vm = new Vue({
el: '#app',
template: '<comp-one></comp-one>',
})
- 組件內部創建組件
const component = {
template: '<span>{{text}}</span>',
data () {
return {
text: 123456
}
}
}
const vm = new Vue({
el: '#app',
components: {
CompOne: component
},
data: {
arr: [1, 2, 3]
}
})
-
props
屬性
通過父組件向子組件傳遞數據,但props
是單項數據流,不能有子組件進行改變,需要父組件傳遞一個函數,由父組件來決定怎麼改變props
的值
<div id="app">
<comp-one :prop-one="num" :on-change="handleChange"></comp-one>
//<comp-one :prop-one="num" @change="handleChange"></comp-one>
</div>
<script>
Vue.config.devtools = true
const component = {
template: '<span @click="handleClick">{{propOne}}</span>',
props:{
propOne: Number,
onChange: Function //這便可省略用$emit
},
methods: {
handleClick() {
this.onChange()
//this,$emit('change')
}
}
}
Vue.component('CompOne', component)
const vm = new Vue({
el: '#app',
components: {
CompOne: component
},
data: {
num: 1,
},
methods: {
handleChange() {
this.num += 1
}
}
})
</script>
-
extend
屬性
const component = {
template: '<span @click="handleClick">{{propOne}}{{text}}</span>',
props:{
propOne: Number,
},
data () {
return {
text: 888
}
},
mounted () {
console.log('component mounted') //先執行
},
methods: {
handleClick() {
// this.onChange()
this.$emit('change')
}
}
}
const compVue = Vue.extend(component) //生成vue子類並擁有組件的屬性
//也可通過新建一個組件並繼承上個組件屬性(extend:component),並new Vue()
new compVue({
el:'#app',
propsData: {
propOne: 12356 //用propsData進行賦值
},
data: {
text: 666 //後覆蓋繼承組件的data中的值
},
mounted () {
console.log('compVue mounted') //後執行
}
})
vue-插槽
父組件決定放什麼內容,子組件決定放哪
- 具名插槽
<div id="app">
<comp-one>
<span slot="body">具名插槽</span>
<span slot="foot" slot-sc>{{value}}</span>
<span slot-scope="props">{{props.value}}作用域插槽</span>
</comp-one>
</div>
<script>
Vue.config.devtools = true;
const component = {
template: `
<div>
<div>
<slot name='body'></slot>
</div>
<div>
<slot name='foot'></slot>
</div>
<div>
<slot :value="value"></slot>
</div>
</div>
`,
data () {
return {
value: 888
}
}
};
const vm = new Vue({
el: "#app",
components: {
CompOne: component
},
data: {
value: 666
}
});
</script>