赞
踩
项目需求:在页面上显示帖子,帖子内的数据来源于后端,形式是"<p>内容</p>"这样的字符串。其中,要为所有的img元素添加一个点击之后看全图的功能,研究了一下,实现方案如下。
- <template>
- <div>
- <div v-for="post in posts" :id="post.id">
- <p>{{ post.author }}</p>
- <p>{{ post.create_time }}</p>
- <div class="content" v-html="post.content"></div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted } from 'vue';
- import { getPost } from '@/api/index";
-
- const posts = ref([])
- onMounted(() => {
- getData();
- })
- const getData = () => {
- getPost().then((res) => {
- posts.value = res.data;
- }).catch(err => {});
- }
- </script>
- <style scoped>
- .content >>> img {
- max-width: 500px;
- }
- </style>
由于要为img元素添加点击事件,起初我的想法是,用replaceAll函数手动给img添加@click或onclick事件,将字符串变成<img οnclick="test" src="/pictures/01.png" />这样的形式,后来发现不行,添加@click浏览器无法识别,添加onclick,浏览器也无法获取写在vue文件中的test函数,必须要对dom节点进行操作。
网上的写法都是在onMounted中通过ref获取对应节点,但是因为项目逻辑是在onMounted中调用api接口访问后端,所以必须要等到数据回来之后再去访问节点,才能获取对应的内容。
这时候就可以用到finally。在异步操作中,then, catch, finally是一组,finally内的内容在then和catch执行后执行,非常符合当前的场景。
- const getData = () => {
- getPost().then((res) => {
- posts.value = res.data;
- }).catch(err => {
- console.log(err);
- }).finally(() => {
- const elements = document.querySelectorAll('.content img'); // 获取所有img节点
- elements.forEach(item => item.addEventListener('click', handleClick);
- });
- }
本来想使用ant-design中的Modal实现图片放大后的弹窗,但是默认的样式和需求差得太远,所以自己写了个。其中还有个小插曲,因为这个组件外部还有内容,所以将.modal_mask的样式写为position:absolute;的时候,并没有达到全屏的效果,只是占满了外部组件的全部,所以要写成position:fixed;
- <template>
- <div>
- ...
- <div v-show="showModal" class="modal_mask">
- <div class="close_btn" @click="showModal=false">
- <img src="@/assets/pictures/close.png" />
- </div>
- <img :src="imgsrc" />
- </div>
- </template>
- <script setup>
- ...
-
- const showModal = ref(false); //控制弹窗显示隐藏
- const imgsrc = ref('');
- ...
- const handleClick = (event) => {
- showModal.value = true;
- imgsrc.value = event.target.src; //必须要通过传来的event获取图片src
- }
- </script>
- <style scoped>
- .modal_mask {
- position: fixed;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- background-color: rgba(0, 0, 0, 0.45);
- z-index: 9999;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .modal_mask .close_btn {
- position: absolute;
- right: 10px;
- top: 10px;
- cursor: pointer;
- }
- .modal_mask img {
- max-width: 100%;
- max-height: 100%;
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。