createVNode() 函数
,但是为了简便在Vue将之简化为h() 函数;h()函数如何使用呢?它接受三个参数:
第一个参数
props
,那么通常可以将children
作为第二个参数传入;null
作为第二个参数传入,将children
作为第三个参数传入;1 .render函数选项中使用;
=>没有template模板
<script>
import { h } from 'vue';
export default {
render() {
return h("h2", {class: "title"}, "Hello Render")
}
}
</script>
<style scoped>
</style>
2 . setup函数选项中使用
(setup本身需要是一个函数类型,函数再返回h函数创建的VNode)
<script>
import { h } from 'vue';
export default {
data() {
return {
counter: 0
}
},
render() {
return h("div", {class: "app"}, [
h("h2", null, `当前计数: ${this.counter}`),
h("button", {
onClick: () => this.counter++
}, "+1"),
h("button", {
onClick: () => this.counter--
}, "-1"),
])
}
}
</script>
<style scoped>
</style>
<script>
import { ref, h } from 'vue';
export default {
setup() {
const counter = ref(0);
return () => {
return h("div", {class: "app"}, [
h("h2", null, `当前计数: ${counter.value}`),
h("button", {
onClick: () => counter.value++
}, "+1"),
h("button", {
onClick: () => counter.value--
}, "-1"),
])
}
}
}
</script>
App.vue
<script>
import { h } from 'vue';
import HelloWorld from './HelloWorld.vue';
export default {
render() {
return h("div", null, [
h(HelloWorld, null, {
default: props => h("span", null, `app传入到HelloWorld中的内容: ${props.name}`)
})
])
}
}
</script>
HelloWord.vue'
<script>
import { h } from "vue";
export default {
render() {
return h("div", null, [
h("h2", null, "Hello World"),
this.$slots.default ? this.$slots.default({name: "coderwhy"}): h("span", null, "我是HelloWorld的插槽默认值")
])
}
}
</script>
npm install @vue/babel-plugin-jsx -D
<script>
export default {
data() {
return {
counter: 0
}
},
render() {
const increment = () => this.counter++;
const decrement = () => this.counter--;
return (
<div>
<h2>当前计数: {this.counter}</h2>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
</div>
)
}
}
</script>
App.vue
<script>
import HelloWorld from './HelloWorld.vue';
export default {
data() {
return {
counter: 0
}
},
render() {
const increment = () => this.counter++;
const decrement = () => this.counter--;
return (
<div>
<h2>当前计数: {this.counter}</h2>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
<HelloWorld>
</HelloWorld>
</div>
)
}
}
</script>
<style lang="scss" scoped>
</style>
HelloWord.vue
<script>
export default {
render() {
return (
<div>
<h2>HelloWorld</h2>
{this.$slots.default ? this.$slots.default(): <span>哈哈哈</span>}
</div>
)
}
}
</script>
<style scoped>
</style>
<template>
<div>
<button v-if="counter < 2" v-why.aaaa.bbbb="'coderwhy'" @click="increment">当前计数: {{counter}}</button>
</div>
</template>
<script>
import { ref } from "vue";
export default {
// 局部指令
directives: {
why: {
created(el, bindings, vnode, preVnode) {
console.log("why created", el, bindings, vnode, preVnode);
console.log(bindings.value);
console.log(bindings.modifiers);
},
beforeMount() {
console.log("why beforeMount");
},
mounted() {
console.log("why mounted");
},
beforeUpdate() {
console.log("why beforeUpdate");
},
updated() {
console.log("why updated");
},
beforeUnmount() {
console.log("why beforeUnmount");
},
unmounted() {
console.log("why unmounted");
}
}
},
setup() {
const counter = ref(0);
const increment = () => counter.value++;
return {
counter,
increment
}
}
}
</script>
<style scoped>
</style>
自定义指令分为两种:
组件中通过directives 选项
,只能在当前组件中使用;app的directive 方法,
可以在任意组件中被使用;<template>
<div>
<input type="text" ref="input">
</div>
</template>
<script>
import { ref, onMounted } from "vue";
export default {
setup() {
const input = ref(null);
onMounted(() => {
input.value.focus();
})
return {
input
}
}
}
</script>
<style scoped>
</style>
<template>
<input type="text" v-focuss="" value="取值" /> 值
</template>
<script>
// import {directives} from 'vue';
export default {
// 自定义组件实现聚焦
// 自定义组件利用directives方法实现的实现
directives: {
// 自定义组件的方式
focuss: {
// 挂载前
mounted(el,any,anyy,anyyy) {
el.focus()
// 第三个数值可以拿去值
console.log(el,any,anyy,anyyy);
console.log(anyy.props.value);
}
},
},
};
</script>
<style>
</style>
app.directive("focus", {
mounted(el, bindings, vnode, preVnode) {
console.log("focus mounted");
el.focus();
}
})
如果我们指令需要接受一些参数或者修饰符应该如何操作呢?
aaa-bbb是修饰符的名称;
后面是传入的具体的值;
时间戳的显示需求:
实现一个可以自动对时间格式化的指令v-format-time
:
App.vue
<template>
<h2 v-format-time="'YYYY/MM/DD'">{{timestamp}}</h2>
<h2 v-format-time>{{timestamp}}</h2>
</template>
<script>
export default {
// 创建时间戳进行返回
setup() {
const timestamp = 1624452193;
return {
timestamp
}
},
mounted() {
console.log("app mounted");
}
}
</script>
<style scoped>
</style>
index.js
=>入口
import registerFormatTime from './format-time';
export default function registerDirectives(app) {
registerFormatTime(app);
}
format-time.js
import dayjs from 'dayjs';
export default function(app) {
app.directive("format-time", {
created(el, bindings) {
bindings.formatString = "YYYY-MM-DD HH:mm:ss";
if (bindings.value) {
bindings.formatString = bindings.value;
}
},
mounted(el, bindings) {
const textContent = el.textContent;
let timestamp = parseInt(textContent);
if (textContent.length === 10) {
timestamp = timestamp * 1000
}
el.textContent = dayjs(timestamp).format(bindings.formatString);
}
})
}
main.js
import { createApp } from 'vue'
import App from './03_自定义指令/App.vue'
import registerDirectives from './directives'
const app = createApp(App);
registerDirectives(app);
// app.directive("focus", {
// mounted(el, bindings, vnode, preVnode) {
// console.log("focus mounted");
// el.focus();
// }
// })
app.mount('#app');
通常我们向Vue全局添加一些功能时,会采用插件的模式,它有两种编写方式:
对象类型:
一个对象,但是必须包含一个install 的函数,该函数会在安装插件时执行;函数类型:
一个function,这个函数会在安装插件时自动执行;插件可以完成的功能没有限制,比如下面的几种都是可以的:
对象类型
export default {
install(app,el) {
app.config.globalProperties.$name = 'coderwhy'
},
};
App.vue
中访问自定义组件的值<template>
{{ $name }}
</template>
<script>
import { getCurrentInstance } from "vue";
export default {
// 在setup中拿取自定义组件中的属性值
// setup没有this的绑定拿取不到自定义组件的值因此需要在导入app=>getCurrentInstance
setup(props) {
const app=getCurrentInstance()
//进行取值
console.log(app.appContext.config);
},
// 生命周期中拿取自定义组件中的值
created() {
console.log(this.$name)
},
};
</script>
<style>
</style>
插件的编写具体方法
App.vue
的代码
<template>
<div class="app">
<teleport to="#why">
<h2>当前计数</h2>
<button>+1</button>
<hello-world></hello-world>
</teleport>
<teleport to="#why">
<span>呵呵呵呵</span>
</teleport>
</div>
</template>
<script>
import HelloWorld from './HelloWorld.vue';
export default {
components: {
HelloWorld
},
}
</script>
<style scoped>
</style>
HelloWord.vue
代码
<template>
<div>
<h2>Hello World</h2>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>