uniapp开发的网页SEO优化方案-适用于uni-app开发的web站点, uniapp手机端网页适配优化

基于nginx服务器优化的方案, 适用于 uniapp开发的网站, 可适用于老项目

由于官网的插件暂时不支持老的项目,所以使用这种方法
本教程亲测可用, 以及上线的项目网址: http://al.jn1tea.com/
打开调试工具, 手机模式, ctrl + u 可以查看每个页面的 seo内容**

教程内容有点长, 请耐心看完

1、uniapp设置为history模式 2、nginx设置好转发规则 3、后端服务器(类同云函数),动态给模版html设置标题、描述、关键词(根据自己需要)返回html(注意:同uniapp h5 的首页html模版一致)

教程, 前置要求, 通过服务器转发,
必须能安装nginx, 以及 node.js, express 服务器框架

在宝塔, 配置反向代理配置文件, 如果是linux 注意格式问题

处理动态生成的HTML模板, 通配符匹配, uniapp前端路径都是pages/

8332, 为你的 node.js 中express 服务器框架的端口号
注意: 由于原来的系统要求, 配置了一个全局代理, 所以这个路由匹配转发需要在全局代理上面才能生效

location ~ ^/pages/.*{
    proxy_pass http://127.0.0.1:8332;
    proxy_http_version 1.1;
    proxy_read_timeout 360s;   
    proxy_redirect off; 
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;

    add_header X-Cache $upstream_cache_status;
}

# 以下是原来的反向代理文件, 不用动
location / {
    proxy_pass http://127.0.0.1:8325;
    proxy_http_version 1.1;
    proxy_read_timeout 360s;   
    proxy_redirect off; 
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;

    add_header X-Cache $upstream_cache_status;
    #Set Nginx Cache

    set $static_filetKzRZE5L 0;
    if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" )
    {
        set $static_filetKzRZE5L 1;
        expires 1m;
    }
    if ( $static_filetKzRZE5L = 0 )
    {
        add_header Cache-Control no-cache;
    }
}
#PROXY-END/

在宝塔中安装node.js, 以及express服务器
其他linux系统可以用命令行安装,
参考教程 https://www.cnblogs.com/front-web/p/15672575.html

安装node.js, 记得设置命令行版本一致

在这里插入图片描述

安装完成后需要启动一个node.js的网站
首先在服务器目录下创建一个文件夹, 刚开始是空的

[attach]136550[/attach]

进入命令行终端 cd /www/wwwroot/你创建的文件夹命
在终端中运行以下命令来初始化Node.js项目:npm init -y
在终端中运行以下命令来安装Express: npm install express
安装成功后创建 views 文件夹, app.js 文件 , 修改package.json文件

在这里插入图片描述

package.json 启动脚本文件内容
{
  "name": "putao_seo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.8",
    "express": "^4.18.2"
  }
}

[attach]136549[/attach]

app.js 文件内容, 重点, 里面内容需要根据自己的网站配置

1. 端口号, 要和上面配置反向代理一致

app.listen(8332, () => {
  console.log('Server is running on port 8332');
  console.log('express服务器启动成功! 端口号:8332');
});

2. 公共配置

const commonConfig = {
    BASE_URL: 'http://al.jn1tea.com/', // 设置BASE_URL, 你的域名, 例如:  http://al.jn1tea.com/pages/goods_details 设置为http://al.jn1tea.com/
    VUE_APP_INDEX_CSS_HASH: 'asxga454' //  uniapp 打包后会在static中生成一个css文件, index.xxx.css, 在这里填写
};

[attach]136547[/attach]

// 这里就是你的uniapp打包后的h5 每个页面的访问路径, seo优化就在这里修改title, description, keywords

// 想优化哪个页面就继续添加

app.get('/pages/goods_cate/goods_cate', (req, res) => {
    const pageData = {
        title: '商品分类页',
        description: '商品分类页描述',
        keywords: '商品, 分类',
        ...commonConfig
    };
    res.render('index', pageData);
});

// 下面是全部的源码, 根据个人网站自行修改

const express = require('express');
const ejs = require('ejs');
const path = require('path');

const app = express();

// 设置模板引擎
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// 静态文件目录
app.use(express.static(path.join(__dirname, 'public')));

// 公共配置
const commonConfig = {
    BASE_URL: 'http://xxx.xxxcom/', // 根据实际情况设置BASE_URL
    VUE_APP_INDEX_CSS_HASH: 'xxx' // 根据实际情况设置VUE_APP_INDEX_CSS_HASH
};

// 动态生成HTML
app.get('/pages/goods_cate/goods_cate', (req, res) => {
    const pageData = {
        title: '商品分类页',
        description: '商品分类页描述',
        keywords: '商品, 分类',
        ...commonConfig
    };
    res.render('index', pageData);
});

// 添加新的路由处理 /pages/store/home/index
app.get('/pages/store/home/index', (req, res) => {
    const pageData = {
        title: '店铺首页',
        description: '店铺首页描述',
        keywords: '店铺, 首页',
        ...commonConfig
    };
    res.render('index', pageData);
});

app.listen(8332, () => {
  console.log('Server is running on port 8332');
  console.log('express服务器启动成功! 端口号:8332');
});

进入views文件夹, 创建index.ejs 文件

在这里插入图片描述

// 配置文件, 刚才在app.js 的文件会动态解析到这里的title等标签中

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title><%= title %> | 葡萄有约</title>
        <meta name="Keywords" content="<%= keywords %>" />
        <meta name="Description" content="<%= description %>" />
       
        <script>
            var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
            document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
            if(window.location.protocol == 'http:'){
                document.write('<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">')
            }
        </script>
        <link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
    </head>
    <body>
        <noscript>
            <strong>Please enable JavaScript to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
    </body>
</html>

接下来创建一个node.js 网站

在这里插入图片描述

启动网站,

cd进入刚才初始化创建的目录, 用终端打开
输入命令 node app.js 启动express 服务器, 看到日志说明启动成功

在这里插入图片描述

注意, 如果中途修改配置文件, 记得重启 node app.js, 同理nginx 修改也要重启生效
如果没问题, 就可以访问你配置后的页面, ctrl + u 查看是否生效

##基于nginx服务器优化的方案, 适用于 uniapp开发的网站, 可适用于老项目

由于官网的插件暂时不支持老的项目,所以使用这种方法
本教程亲测可用, 以及上线的项目网址: http://al.jn1tea.com/
打开调试工具, 手机模式, ctrl + u 可以查看每个页面的 seo内容**

<think>好的,我现在需要解决用户在UniApp中遇到的`document.getElementById`为undefined的问题,并提供替代方案或解决方法。首先,我需要理解为什么会出现这个问题。 UniApp是一个使用Vue.js框架的跨平台开发工具,它主要支持小程序、H5以及App等平台。在传统Web开发中,我们经常使用`document.getElementById`来获取DOM元素,但在UniApp中,由于运行环境的不同(比如小程序),传统的DOM操作方法可能不可用,因为小程序没有传统浏览器的DOM模型。这就是导致`document.getElementById`返回undefined的原因。 接下来,我需要参考用户提供的引用内容来寻找可能的解决方案。引用[1]提到使用`document.getElementsByName()`的替代方案,解决了IE浏览器的一些兼容性问题,但这里的问题环境是UniApp,可能涉及小程序,所以需要考虑跨平台的兼容性。引用[2]讨论了在Vue中使用`ref`属性来引用组件或DOM元素,这可能在UniApp中同样适用,因为UniApp基于Vue.js。 首先,我需要确认UniApp中推荐的元素访问方法。在Vue中,通常使用`ref`来引用元素或组件实例。UniApp作为基于Vue的框架,应该也支持这种方式。例如,在模板中给元素添加`ref`属性,然后通过`this.$refs`来访问。这种方法不依赖于`document.getElementById`,而是利用Vue的响应式系统,更符合UniApp的设计模式。 另外,用户之前的问题涉及到微信小程序中的元素定位和滚动,解决方案中使用了`wx.createSelectorQuery`来获取元素位置。UniApp是否提供了类似的API?查阅UniApp文档,发现它确实封装了各平台的API,比如使用`uni.createSelectorQuery()`来创建节点查询,类似于微信小程序的`wx.createSelectorQuery`。这可能是在UniApp中替代`document.getElementById`的正确方法,尤其是在需要获取元素位置或尺寸时。 还有,用户可能在H5环境下使用UniApp,此时可能需要兼容浏览器的DOM操作。但为了跨平台,最好使用UniApp提供的统一方法,而不是直接操作DOM。例如,在H5中,虽然可以使用`document.getElementById`,但在小程序或App中会失败,因此应避免使用。 总结可能的解决方案: 1. 使用Vue的`ref`属性来引用元素,通过`this.$refs`访问。 2. 使用UniApp提供的`uni.createSelectorQuery()`API来查询节点信息。 3. 在需要动态操作元素时,使用数据驱动的方式,而不是直接操作DOM。 接下来需要详细说明这些方法的具体实现步骤,并给出代码示例,确保用户能够理解并应用。同时,需要比较不同方法的适用场景,比如何时使用`ref`,何时使用`createSelectorQuery`,以及如何处理跨平台兼容性问题。 可能还需要考虑生命周期的问题,比如在`mounted`或`onReady`阶段确保元素已经渲染完成再进行查询。此外,错误处理也是必要的,比如元素不存在时的处理,避免应用崩溃。 最后,需要验证这些方法在UniApp的不同平台(如H5、小程序、App)中的可行性,确保提供的解决方案是跨平台有效的。同时,提醒用户避免直接使用DOM API,遵循UniApp开发规范,以保证应用的稳定性和兼容性。</think>在UniApp中,由于跨平台特性和小程序环境限制,直接使用`document.getElementById`会返回`undefined`。以下是针对不同场景的解决方案--- ### 一、基础替代方案:使用Vue ref引用 **适用场景**:需要直接操作组件/元素时 ```vue <!-- 在template中标记元素 --> <view ref="myElement">目标元素</view> <script> export default { mounted() { // 通过this.$refs访问 const element = this.$refs.myElement; // H5环境下可操作DOM(仅限浏览器环境) if (typeof window !== 'undefined') { element.$el.style.color = 'red'; } } } </script> ``` **优势**: - 支持跨平台运行 - 符合Vue响应式规范[^2] **限制**: - 无法直接获取元素布局信息(宽高、位置等) --- ### 二、高级方案uni.createSelectorQuery **适用场景**:需要获取元素尺寸/位置信息 ```javascript // 获取元素布局信息 getElementRect() { uni.createSelectorQuery().in(this) .select('.target-class') .boundingClientRect(rect => { if (rect) { console.log('元素高度:', rect.height) console.log('离顶部距离:', rect.top) } }).exec() } // 滚动到指定位置(支持动画) scrollToElement() { uni.createSelectorQuery().select('#section2') .boundingClientRect(rect => { uni.pageScrollTo({ scrollTop: rect.top, duration: 300 }) }).exec() } ``` **特性**: - 全平台兼容(H5/小程序/App- 支持异步查询 - 可获取精确布局数据[^1] --- ### 三、动态渲染解决方案 **适用场景**:列表渲染等动态内容操作 ```vue <template> <view v-for="(item,index) in list" :ref="'item_'+index" @click="handleClick(index)"> {{item}} </view> </template> <script> export default { data() { return { list: ['A','B','C'] } }, methods: { handleClick(index) { // 通过动态ref访问特定元素 const target = this.$refs['item_'+index][0] uni.showToast({ title: `点击了${target.$el.innerText}` }) } } } </script> ``` --- ### 四、跨平台兼容技巧 | 场景 | 解决方案 | 注意事项 | |-----------------------|-----------------------------------|-----------------------------| | 需要DOM操作 | 条件编译 + H5 API | `#ifdef H5` 包裹代码块 | | 频繁操作元素 | 数据驱动代替DOM操作 | 通过修改data触发视图更新 | | 第三方库依赖DOM | 使用uniapp插件市场替代方案 | 优先选择标有"跨平台"的插件 | | 必须使用document方法 | 封装平台判断方法 | 小程序环境需降级处理 | **示例代码(条件编译)**: ```javascript // #ifdef H5 const element = document.getElementById('fallback'); // #endif // #ifndef H5 uni.createSelectorQuery().select('#fallback').fields({...}) // #endif ``` --- ### 常见问题排查 1. **refs访问为空** - 检查元素是否存在于当前组件 - 确保在`mounted`生命周期后访问 - 动态渲染内容使用`$nextTick`等待更新: ```javascript this.$nextTick(() => { console.log(this.$refs.dynamicElement) }) ``` 2. **SelectorQuery无响应** - 添加`.in(this)`指定组件上下文 - 确保选择器在页面中存在 - 检查基础库版本(需≥1.4.0) 3. **滚动定位偏移** - 计算时考虑导航栏高度: ```javascript const systemInfo = uni.getSystemInfoSync() const scrollTop = rect.top - systemInfo.statusBarHeight ``` --- ### 性能优化建议 1. **批量查询**:单次`exec()`执行多个查询 ```javascript const query = uni.createSelectorQuery() query.select('#header').boundingClientRect() query.select('#footer').boundingClientRect() query.exec(results => { const [header, footer] = results }) ``` 2. **缓存查询结果**:对静态元素位置信息进行缓存 ```javascript let cachedPosition = null function getPosition() { return cachedPosition || new Promise(resolve => { uni.createSelectorQuery().select(...) .exec(res => { cachedPosition = res[0] resolve(cachedPosition) }) }) } ``` --- ### 平台差异对照表 | 功能 | H5 | 小程序 | App | |----------------------|-------------|--------------|--------------| | document.getElementById | 可用 | 不可用 | 不可用 | | this.$refs | 支持 | 支持 | 支持 | | createSelectorQuery | 支持 | 支持 | 支持 | | getBoundingClientRect | 原生实现 | 异步获取 | 异步获取 | ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值