api及参数参考:https://juejin.cn/post/7310977323484971071
简单实现:
addAnimationClass(){
//交叉观察器
if (window?.IntersectionObserver) {
//获取所有需要添加进场动画的元素,放到一个数组
let items = [...document.getElementsByClassName('need-fide-in')]
let io = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
//给元素加上进场动画的类名
item.target.classList.add('fade-in-animation')
//取消对元素的观察(添加已完成)
io.unobserve(item.target)
}
})
}, {
root: null,//根元素,根据这个元素的范围来监听,默认是视口
rootMargin: '0px 0px 0px 0px', //监听的扩大范围,上右下左,必须要设置root才生效
threshold: 0 // 阀值,出现程度为多少[0, 1]
})
//观察数组里的所有元素
items.forEach(item => io.observe(item))
//可以移除对所有元素的监听
// observe.disconnect();
//可以返回所有被观察的对象,返回值是数组
// observer.takeRecords();
}
},
.fade-in-animation{
animation: fidein 0.7s linear;
}
@keyframes fidein{
from {
opacity: 0;
transform: translate3d(0px, 90px, 0px) scale3d(1, 1, 1) rotateX(0deg) rotateY(0deg) rotateZ(0deg) skew(0deg, 0deg);
transform-style: preserve-3d;
}
to {
opacity: 1;
transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1) rotateX(0deg) rotateY(0deg) rotateZ(0deg) skew(0deg, 0deg);
transform-style: preserve-3d;
}
}
原本的实现是用了scrollIntoView,但是发现block设置为top或者center的时候页面底部会出现空白,只有nearst不会,但是目标内容在视线最底部,效果又不太好
document.getElementById('block').scrollIntoView({
behavior: 'auto',
block: 'center',
})
换成了vue-scroll,并将ref属性设置为scroll, srcoll.value就是获取到vueScroll元素
scroll.value.setScrollTop(element.getBoundingClientRect().top - 容器高度 / 2 + 元素element本身高度)
获取:
function getCursorPosition = (element: any) => {
try {
let caretOffset = 0;
const doc = element.ownerDocument || element.document;
const win = doc.defaultView || doc.parentWindow;
let sel;
if (typeof win.getSelection != "undefined") {//谷歌、火狐
sel = win.getSelection();
if (sel.rangeCount > 0) {//选中的区域
const range = win.getSelection().getRangeAt(0);
const preCaretRange = range.cloneRange();//克隆一个选中区域
preCaretRange.selectNodeContents(element);//设置选中区域的节点内容为当前节点
preCaretRange.setEnd(range.endContainer, range.endOffset); //重置选中区域的结束位置
caretOffset = preCaretRange.toString().length;
}
} else if ((sel = doc.selection) && sel.type != "Control") {//IE
const textRange = sel.createRange();
const preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
} catch (e) {
return 0;
}
}
设置:
function setCaretPosition(element, pos) {
let range, selection;
range = document.createRange();//创建一个选中区域
// range.selectNodeContents(element);//选中节点的内容
if(element.innerHTML.length > 0) {
range.setStart(element.childNodes[0], pos); //设置光标起始为指定位置
range.setEnd(element.childNodes[0], pos); //设置光标起始为指定位置
}
range.collapse(true); //设置选中区域为一个点
selection = window.getSelection();//获取当前选中区域
selection.removeAllRanges();//移出所有的选中范围
selection.addRange(range);//添加新建的范围
// 设置最后光标对象
isPosition.value = selection.getRangeAt(0);
}
文档地址:https://vue-i18n.intlify.dev/guide/
配置locales文件夹里的内容:一个index.js的入口文件和各语言的json文件
index文件内容:
import { createI18n } from "vue-i18n";
import en from "./en.json";
import cn from "./zh.json";
const i18n = createI18n({
legacy: false,
locale: process.env.VUE_APP_LANG, // set locale
messages: {
en,
cn,
},
});
export default i18n;
项目引用main.ts中
import i18n from "./locales";
const app = createApp(App);
app.use(i18n);
app.mount("#app");
配置打包脚本
build.sh:
# 创建 dist 文件夹,如果存在 dist 文件夹则先删除再创建
if [ -e "dist" ]; then
rm -rf dist
mkdir dist
else
mkdir dist
fi
# 每种语言都打包一次。ubuntu系统,可能对此行报括号错误,规避处理:在终端执行 dpkg-reconfigure dash,选择no。
# dash,选择no之后,系统的shell会使用bash,bash会降低ubuntu系统性能。所以,可以应优先通过 bash build.sh执行脚本。
# dash for debian。bash则支持更多语法。
langList=(en cn)
for item in ${langList[*]}; do
echo 'build for '$item' in ('${langList[*]}')'
export VUE_APP_LANG="$item"
npm run build
done
按需设置网站语言,seo等
//获取国际化选择语言,用于项目跳转。优先级:localStorage中的语言信息 > url地址语言信息 > 浏览器语言
utils.getWebLanguage = function () {
let lang: string | null = "en";
//预渲染只看地址中的参数
if (!(!window.__PRERENDER_INJECTED || window.__PRERENDER_INJECTED.isPrerender !== true)) {
if (window.location.pathname && window.location.pathname !== "/") {
//地址栏中携带了语言参数
const pathArray = window.location.pathname.split("/");
for (let i = 0; i < webLangList.length; i++) {
if (webLangList[i].langCode.toLowerCase() === pathArray[1]) {
lang = pathArray[1];
break;
}
}
}
return lang
}
const LangList = webLangList;
let isExist = true;
//本地有存储的语言
if (localStorage.getItem(constants.WEB_CHOOSE_LANGUAGE)) {
lang = localStorage.getItem(constants.WEB_CHOOSE_LANGUAGE);
isExist = false;
} else if (window.location.pathname && window.location.pathname !== "/") {
//地址栏中携带了语言参数
const pathArray = window.location.pathname.split("/");
for (let i = 0; i < webLangList.length; i++) {
if (webLangList[i].langCode.toLowerCase() === pathArray[1]) {
lang = pathArray[1];
isExist = false;
break;
}
}
}
if (isExist) {
//浏览器默认语言参数
for (let i = 0; i < LangList.length; i++) {
let flag = "";
if (navigator.language == "zh-TW" || navigator.language == "zh-HK") {
flag = "tw";
} else if (navigator.language == "zh-CN" || navigator.language == "zh") {
flag = "cn";
} else {
flag = navigator.language.substring(0, 2).toLowerCase();
}
if (LangList[i].langCode.toLowerCase() === flag) {
lang = LangList[i].langCode.toLowerCase();
break;
}
}
}
return lang;
};
//获取挂载时的语言参数
utils.getMountLanguage = function () {
const chosenLang = utils.getWebLanguage();
const url = window.location.href;
const routePath = window.location.pathname === "/" ? "" : window.location.pathname;
const searchParams = window.location.search;
const pathArray = routePath.split("/");
let path = routePath;
let isExist = -1;
if (pathArray.length > 1) {
isExist = webLangList.findIndex(item => {
return pathArray[1] == item.langCode;
});
}
if (isExist !== -1) {
const langCode = webLangList[isExist].langCode;
path = routePath.substring(langCode.length + 1, routePath.length + 1);
}
if (chosenLang !== "en") {
if (!url.includes(`/${chosenLang}`)) {
window.location.href = `${window.location.origin}/${chosenLang}${path}${searchParams}`;
}
} else if (chosenLang == "en"){
if (isExist !== -1) {
window.location.href = `${window.location.origin}${path}`;
}
}
};
nginx网站配置,新增location /语种